Commit 4d9b51a7 by 庄钊鑫

代码复制

parents
FROM harbor.dankal.cn/common/php-nginx
ENV VIRTUAL_HOST api-php.dankal.cn
ENV LETSENCRYPT_HOST api-php.dankal.cn
ENV LETSENCRYPT_EMAIL bingo@dankal.cn
COPY . /app
RUN chmod 777 /app/runtime
This diff is collapsed. Click to expand it.
Folder
*.zip
*.rar
*.via
*.tmp
*.err
/runtime/
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
deny from all
\ No newline at end of file
<?php
/**
* 授权基类,包含请求方式过滤 请求参数处理 请求资源限制等
*/
namespace app\api\controller;
use think\Controller;
use think\exception\HttpResponseException;
use think\Request;
class Api extends Controller
{
use Send;
protected $param = [];
protected $userId;
protected $pageIndex;
protected $pageSize;
/**
* 对应操作
* @var array
*/
public $methodToAction = [
'get' => 'read',
'post' => 'save',
'put' => 'update',
'delete' => 'delete',
'patch' => 'patch',
'head' => 'head',
'options' => 'options',
];
/**
* 允许访问的请求类型
* @var string
*/
public $restMethodList = 'get|post|put|delete|patch|head|options';
/**
* 默认不验证
* @var bool
*/
public $apiAuth = true;
protected $request;
/**
* 当前请求类型
* @var string
*/
protected $method;
/**
* 当前资源类型
* @var string
*/
protected $type;
public static $app;
/**
* 返回的资源类的
* @var string
*/
protected $restTypeList = 'json';
/**
* REST允许输出的资源类型列表
* @var array
*/
protected $restOutputType = [
'json' => 'application/json',
];
/**
* 客户端信息
*/
protected $clientInfo;
/**
* 控制器初始化操作
*/
public function _initialize()
{
$request = Request::instance();
$this->request = $request;
$this->init(); //检查资源类型
}
public function __construct(Request $request = null)
{
parent::__construct();
$this->param = $request->param();
$this->getPageIndexAndSize();
}
/**
* 初始化方法
* 检测请求类型,数据格式等操作
*/
public function init()
{
$request = Request::instance();
$ext = $request->ext();
if ('' == $ext) {
// 自动检测资源类型
$this->type = $request->type();
} elseif (!preg_match('/\(' . $this->restTypeList . '\)$/i', $ext)) {
// 资源类型非法 则用默认资源类型访问
$this->type = $this->restDefaultType;
} else {
$this->type = $ext;
}
$this->setType();
// 请求方式检测
$method = strtolower($request->method());
$this->method = $method;
if (false === stripos($this->restMethodList, $method)) {
throw new HttpResponseException(json((object)array('error'=>405,'message'=>'No routing path can be found for the request.'),200));
}
}
/**
* 空操作
* @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Xml
*/
public function _empty()
{
return $this->render(200);
}
/**
* 单个参数验证
*
* @param $value
* @param $key
* @param $validate
*/
protected function checkSingle($value, $key, $validate)
{
$this->check([$key => $value], $validate);
}
/**
* 验证参数
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
*/
protected function check($data, $validate, $message = [])
{
$validateResult = $this->validate($data, $validate, $message);
if ($validateResult !== true) {
self::returnmsg(403, [], [], "", "param error", $validateResult);
}
}
/**
* 获取页码和每页数量
* @param int $defaultIndex
* @param int $defaultSize
* @param int $sizeLimit
*/
protected function getPageIndexAndSize($defaultIndex = 1, $defaultSize = 20, $sizeLimit = 1000)
{
$this->pageIndex = isset($this->param['page_index']) ? $this->param['page_index'] : null;
$this->pageSize = isset($this->param['page_size']) ? $this->param['page_size'] : null;
$this->pageIndex = $this->pageIndex ?: $defaultIndex;
$this->pageSize = $this->pageSize ?: $defaultSize;
$this->checkSingle($this->pageIndex, 'page_index', 'Base.page_index');
$this->checkSingle($this->pageSize, 'page_size', 'Base.page_size');
if ($this->pageSize > $sizeLimit) {
self::returnmsg(403, [], [], "", "param error", "参数不合法");
}
}
/**
* 获取指定参数
*
* @param string $key
* @param mixed|null $defaultValue
* @return mixed|null
*/
protected function getParam($key, $defaultValue = null)
{
return isset($this->param[$key])
? (is_string($this->param[$key]) ? trim($this->param[$key]) : $this->param[$key])
: $defaultValue;
}
/**
* 获取多个参数,keysArray为空时获得全部参数
* 注意键名不能为数字
*
* @param array|null $keysArray
* @return array
*/
protected function selectParam($keysArray = null)
{
if ($keysArray) {
$paramResult = [];
foreach ($keysArray as $key => $value) {
if (is_int($key)) {
// 没有 key , 用数字作为key
$paramResult[$value] = $this->getParam($value);
} else {
// 有 key 和 value , value为参数默认值
$paramResult[$key] = $this->getParam($key, $value);
}
}
return $paramResult;
} else {
return $this->param;
}
}
}
\ No newline at end of file
<?php
/**
*
*/
namespace app\api\controller;
class Factory
{
private static $Factory;
private function __construct()
{
}
public static function getInstance($className, $options = null)
{
if (!isset(self::$Factory[$className]) || !self::$Factory[$className]) {
self::$Factory[$className] = new $className($options);
}
return self::$Factory[$className];
}
}
\ No newline at end of file
<?php
namespace app\api\controller;
use app\api\controller\UnauthorizedException;
use app\api\controller\Send;
use think\Exception;
use think\Request;
use think\Db;
use think\Cache;
class Oauth
{
use Send;
/**
* accessToken存储前缀
*
* @var string
*/
public static $accessTokenPrefix = 'accessToken_';
/**
* accessTokenAndClientPrefix存储前缀
*
* @var string
*/
public static $accessTokenAndClientPrefix = 'accessTokenAndClient_';
/**
* 过期时间秒数
*
* @var int
*/
public static $expires = 72000;
/**
* 客户端信息
*
* @var
*/
public $clientInfo;
/**
* 认证授权 通过用户信息和路由
* @param Request $request
* @return \Exception|UnauthorizedException|mixed|Exception
* @throws UnauthorizedException
*/
final function authenticate()
{
$request = Request::instance();
// var_dump($request);die;
try {
//验证授权
$clientInfo = $this->getClient();
// var_dump($clientInfo);die;
$checkclient = $this->certification($clientInfo);
if($checkclient){
return $clientInfo;
}
} catch (Exception $e) {
// return $this->returnmsg(402,'Invalid1 authentication credentials.');
$this->returnmsg('402',[],[],'service_message','Invalid1 authentication credentials.','验证码错误');
}
}
/**
* 获取用户信息
* @param Request $request
* @return $this
* @throws UnauthorizedException
*/
public function getClient()
{
$request = Request::instance();
//获取头部信息
try {
//========关键信息在头部传入例如key,用户信息,token等,==============
$authorization = $request->header('token');
// var_dump($authorization);die;
// $authorization = explode(" ", base64_decode($authorization));
// $authorization = explode(':', $authorization[1]);
// $app_key = $authorization[0];
$access_token = $authorization;
// $user_id = $authorization[2];//$_SERVER['PHP_AUTH_USER']
// $clientInfo['user_id'] = $user_id;
// $clientInfo['app_key'] = $app_key;
$clientInfo['token'] = $access_token;
// $clientInfo = $request->param();
} catch (Exception $e) {
return $this->returnmsg(402,$e.'Invalid authentication credentials');
}
return $clientInfo;
}
/**
* 获取用户信息后 验证权限
* @return mixed
*/
public function certification($data = []){
// ======下面注释部分是缓存验证access_token是否有效,这次使用数据库验证======
$time = date("Y-m-d H:i:s",time());
$checkclient = Db::name('token')->field('end_time')->where('uuid',$data['uuid'])->where('access_token',$data['access_token'])->find();
if(empty($checkclient)){
$this->returnmsg(401);
}
if($checkclient <= $time){
$this->returnmsg('402',[],[],'service_message','Token time out','token已过期');
}
return true;
// $getCacheAccessToken = Cache::get(self::$accessTokenPrefix . $data['access_token']); //获取缓存access_token
// if(!$getCacheAccessToken){
// return $this->returnmsg(402,'Access_token expired or error!');
// }
// if($getCacheAccessToken['client']['app_key'] != $data['app_key']){
//
// return $this->returnmsg(402,'App_token does not match app_key'); //app_key与缓存中的appkey不匹配
// }
//
// return true;
}
/**
* 生成签名
* _字符开头的变量不参与签名
*/
public function makeSign ($data = [],$app_secret = '')
{
unset($data['version']);
unset($data['signature']);
foreach ($data as $k => $v) {
if(substr($data[$k],0,1) == '_'){
unset($data[$k]);
}
}
dump($data);
return $this->_getOrderMd5($data,$app_secret);
}
/**
* 计算ORDER的MD5签名
*/
private function _getOrderMd5($params = [] , $app_secret = '') {
ksort($params);
$params['key'] = $app_secret;
return strtolower(md5(urldecode(http_build_query($params))));
}
}
\ No newline at end of file
<?php
/**
* 向客户端发送相应基类
*/
namespace app\api\controller;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\Response;
use think\response\Redirect;
trait Send
{
/**
* 默认返回资源类型
* @var string
*/
protected $restDefaultType = 'json';
/**
* 设置响应类型
* @param null $type
* @return $this
*/
public function setType($type = null)
{
$this->type = (string)(!empty($type)) ? $type : $this->restDefaultType;
return $this;
}
/**
* 失败响应
* @param int $error
* @param string $message
* @param int $code
* @param array $data
* @param array $headers
* @param array $options
* @return Response|\think\response\Json|\think\response\Jsonp|\think\response\Xml
*/
public function sendError($error = 400, $message = 'error', $code = 400, $data = [], $headers = [], $options = [])
{
$responseData['error'] = (int)$error;
$responseData['message'] = (string)$message;
if (!empty($data)) $responseData['data'] = $data;
$responseData = array_merge($responseData, $options);
return $this->response($responseData, $code, $headers);
}
/**
* 成功响应
* @param array $data
* @param string $message
* @param int $code
* @param array $headers
* @param array $options
* @return Response|\think\response\Json|\think\response\Jsonp|Redirect|\think\response\Xml
*/
public function render($code, $result = '')
{
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Headers:token,content-type');
// 组合返回数据
http_response_code($code);
session_start();
if (is_array($result)) {
foreach ((array)$result as $name => $data) {
// (array)强制转化,增强程序的健壮性
if (strpos($name, '.list')) {
// strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)
$model = trim(str_replace('.list', '', $name));
// 替换函数
foreach ((array)$data as $key => $value) {
$result[$name][$key] = $value;
}
} else {
$model = trim($name);
$result[$name] = $data;
}
}
}
// 输出中文字符的时候会进行json格式转码
echo json_encode(
$result
,JSON_UNESCAPED_UNICODE);
$result = null;
unset($result);
ob_flush();
flush();
session_destroy();
exit();
}
public function sendSuccess($data = [], $code = 200, $headers = [], $options = [])
{
if(empty($data)) $responseData['data']="";
if (!empty($data)) $responseData['data'] = $data;
$responseData = array_merge($responseData, $options);
return $this->response($responseData, $code, $headers);
}
/**
* 重定向
* @param $url
* @param array $params
* @param int $code
* @param array $with
* @return Redirect
*/
public function sendRedirect($url, $params = [], $code = 302, $with = [])
{
$response = new Redirect($url);
if (is_integer($params)) {
$code = $params;
$params = [];
}
$response->code($code)->params($params)->with($with);
return $response;
}
/**
* 响应
* @param $responseData
* @param $code
* @param $headers
* @return Response|\think\response\Json|\think\response\Jsonp|Redirect|\think\response\View|\think\response\Xml
*/
public function response($responseData, $code, $headers)
{
if (!isset($this->type) || empty($this->type)) $this->setType();
return Response::create($responseData, $this->type, $code, $headers);
}
/**
* 如果需要允许跨域请求,请在记录处理跨域options请求问题,并且返回200,以便后续请求,这里需要返回几个头部。。
* @param string|int $code 状态码
* @param string $message 返回信息
* @param array $data 返回信息
* @param array $header 返回头部信息
* @param string $reason
* @param string $type
*
*/
public function returnMsg($code = '400', $data = [], $header = [], $type = "", $reason = "", $message = "")
{
switch ($code) {
case 200:
$error = "SUCCESS";
break;
case 400:
$error['error']['type'] = "BAD REQUEST";
$error['error']['reason'] = empty($reason) ? "param missing" : $reason;
$error['error']['message'] = empty($message) ? "请求体不完整" : $message;
break;
case 401:
$error['error']['type'] = empty($type) ? "AUTH ERROR" : $type;
$error['error']['reason'] = empty($reason) ? "token error." : $reason;;
$error['error']['message'] = empty($message) ? "鉴权失败" : $message;
break;
case 403:
$error['error']['type'] = "Forbidden";
$error['error']['reason'] = $reason;
$error['error']['message'] = $message;
break;
case 405:
$error['error']['reason'] = empty($reason) ? "Method Not Allowed " : $reason;
$error['error']['message'] = empty($message) ? "资源请求类型有误" : $message;
break;
case 409:
$error['error']['type'] = "Conflict";
$error['error']['reason'] = "data already exists";
$error['error']['message'] = $message;
break;
case 500:
$error['error']['type'] = "Internal Server Error";
$error['error']['reason'] = $reason;
$error['error']['message'] = $message;
break;
case 404:
default:
$error['error']['type'] = "Not Found";
$error['error']['reason'] = "url error.";
$error['error']['message'] = "请求资源不存在";
break;
}
if (!empty($data)) $error['error']['data'] = $data;
// 发送头部信息
foreach ($header as $name => $val) {
is_null($val) ? header($name) : header($name . ':' . $val);
}
throw new HttpResponseException(json((object)$error, $code));
}
}
\ No newline at end of file
<?php
/**
* 授权失败
*/
namespace app\api\controller;
use think\Exception;
class UnauthorizedException extends Exception
{
public $authenticate;
public function __construct($challenge = 'Basic', $message = 'authentication Failed')
{
$this->authenticate = $challenge;
$this->message = $message;
}
/**
* 获取验证错误信息
* @access public
* @return array|string
*/
public function getError()
{
return $this->error;
}
/**
* WWW-Authenticate challenge string
* @return array
*/
public function getHeaders()
{
return array('WWW-Authenticate' => $this->authenticate);
}
}
\ No newline at end of file
<?php
/**
* 获取access_token以及验证access_token 在此类中完成 每个Base类模块相对独立
* User: Airon
* Date: 2018/7/17
* Time: 上午11:04
*/
namespace app\api\controller\v1\app;
use app\api\model\UserToken;
use app\api\controller\Api;
class Base extends Api
{
/**
* @author: Airon
* @time: 2018年5月
* description
* @return array|bool|false|\PDOStatement|string|\think\Model
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
protected function validateToken()
{
$token = get_token();
$bool = UserToken::build()->validateToken($token);
if (!$bool) {
self::returnmsg(401, [], [], "", "AUTH ERROR", "鉴权失败");
}
return $bool;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: xiezhixian
* Date: 2018/5/4
* Time: 上午11:05
*/
namespace app\api\controller\v1\app;
use app\api\model\APPUser;
use app\api\model\Sms;
use app\api\controller\Api;
use think\Controller;
use app\api\logic\app\SendLogic;
use app\common\tools\Guodulink;
use app\api\logic\app\UserLogic;
/**
* 所有资源类接都必须继承基类控制器
* 基类控制器提供了基础的验证,包含app_token,请求时间,请求是否合法的一系列的验证
* 在所有子类中可以调用$this->clientInfo对象访问请求客户端信息,返回为一个数组
* 在具体资源方法中,不需要再依赖注入,直接调用$this->request返回为请具体信息的一个对象
* date:2017-07-25
*/
class Send extends Base
{
/**
* 允许访问的方式列表,资源数组如果没有对应的方式列表,请不要把该方法写上,如user这个资源,客户端没有delete操作
*/
public $restMethodList = 'get|post|put|';
/* public function index()
{
$request = $this->selectParam(['mobile','sms_type']);
$this->check($request,'Base.sendSms');
$info = SendLogic::SendSms($request['mobile'],$request['sms_type']);
if ($info) {
$this->returnmsg(403, $data = [], $header = [], $type = "", $info, $message = "信息发送出现了一点小问题哟~");
}
//发送成功
$this->render(200);
}*/
/**
* @author: Airon
* @time: 2018年5月
* description 发送验证码
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function index()
{
$request = $this->selectParam(['mobile', 'sms_type' => 'login']);
$this->check($request, 'Base.sendSms');
if ($request['sms_type'] != 'login' and $request['sms_type'] != 'bind') {
$bool = UserLogic::checkUser($request['mobile']);
if(empty($bool)){
$this->returnmsg(403, [], [],"", [], "该手机号未注册");
}
}
$info = SendLogic::SendSms($request['mobile'], $request['sms_type']);
if ($info === false) {
$this->returnmsg(403, [], [],"", [], "信息发送出现了一点小问题哟~");
}
//发送成功
$this->render(200);
}
/**
* @author: Airon
* @time: 2018年5月
* description 验证验证码
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function validateCode()
{
$request = $this->selectParam(['mobile', 'sms_type' => 'pass','code']);
$request['sendPartnerSms'] = $request['sms_type'];
$this->check($request, 'Base.sendSms');
if ($request['sms_type'] != 'login' and $request['sms_type'] != 'bind') {
$bool = UserLogic::checkUser($request['mobile']);
if(empty($bool)){
$this->returnmsg(403, [], [],"", [], "该手机号未注册");
}
}
$info = SendLogic::validateCode($request);
if ($info === false) {
$this->returnmsg(403, [], [], "", [], "验证码错误");
}
$this->render("验证成功",200);
}
}
<?php
namespace app\api\controller\v1\app;
use app\api\controller\Api;
use app\api\model\UserToken;
use app\common\tools\wechatUtil;
use think\Db;
use app\api\logic\app\SendLogic;
use app\api\model\User as UserModel;
use app\api\logic\app\UserLogic;
/**
* 所有资源类接都必须继承基类控制器
* 基类控制器提供了基础的验证,包含app_token,请求时间,请求是否合法的一系列的验证
* 在所有子类中可以调用$this->clientInfo对象访问请求客户端信息,返回为一个数组
* 在具体资源方法中,不需要再依赖注入,直接调用$this->request返回为请具体信息的一个对象
* date:2017-07-25
*/
class User extends Base
{
/**
* 允许访问的方式列表,资源数组如果没有对应的方式列表,请不要把该方法写上,如user这个资源,客户端没有delete操作
*/
public $restMethodList = 'get|post|put';
/**
* @author: Airon
* @time: 2018年5月
* description 获取用户详情
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function index()
{
$user_info = $this->validateToken();
$this->render(200,['user_info' => $user_info]);
}
/**
* @author: Airon
* @time: 2018年5月
* description 编辑用户信息
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function save()
{
$user_info = $this->validateToken();
$requestData = $this->selectParam(['name', 'avatar']);
$this->check($requestData, "User.edit");
foreach ($requestData as $key=>$value){
if(empty($value)){
unset($requestData[$key]);
}
}
$bool = UserModel::build()->saveInfo($requestData, $user_info['uuid']);
if ($bool) {
$this->render(200);
} else {
$this->returnmsg(403);
}
}
/**
* @author: Airon
* @time: 2018年5月
* description 更新token
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function updateToken()
{
$requestData = $this->selectParam(['refresh_token']);
$result = UserToken::refreshToken($requestData);
if($result == false){
$this->returnmsg(412);
}
$this->render($result);
}
/**
* @author: Airon
* @time: 2018年5月
* description 验证码登录
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function login()
{
$requestData = $this->selectParam(['mobile', 'code','oauth_uuid'=>""]);
$this->check($requestData, 'Base.login');
$requestData['sms_type'] = 'login';
$bool = SendLogic::validateCode($requestData);
if (!$bool) {
self::returnmsg(403, [], [], 'service_message', 'code error.', '验证码错误');
}
$result = UserModel::build()->login($requestData['mobile'],$requestData['oauth_uuid']);
if ($result) {
$this->render($result);
} else {
$this->returnmsg(403, $data = [], $header = [], $type = "", "Login error", $message = "登录失败");
}
}
/*
* 退出登录
*/
public function logout()
{
$this->render(200);
}
/*
* 微信分享签名
*/
public function getShareSign()
{
$requestData = $this->selectParam(['url'=>""]);
if(empty($requestData['url'])){
self::returnmsg(403, [], [], "", "param error", "请上传必填参数");
}
$appid = config('wechat')['PublicAppID'];
$secret = config('wechat')['PublicAppSecret'];
$wechat = new wechatUtil();
$data = $wechat::getShareSign($appid,$secret,$requestData['url']);
if(empty($data)){
self::returnmsg(403, [], [], "", "make sign error", "签名失败");
}
$this->render($data,200);
}
/**
* @author: Airon
* @time: 2018年5月
* description 公众号授权
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function publicLogin()
{
$requestData = $this->selectParam(['jscode' => '']);
if(empty($requestData['jscode'])){
self::returnmsg(403, [], [], "", "param error", "请上传必填参数");
}
$data = UserLogic::publicLogin($requestData);
$data !== false ? $this->render($data) : $this->returnmsg(403,"","","","","登录失败");
}
}
<?php
namespace app\api\controller\v2;
use app\api\model\User as UserModel;
class User
{
// 获取用户信息
public function save($id = 0)
{
return $id;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: Airon
* Date: 2017/7/11
* Time: 14:56
*/
namespace app\api\logic\app;
use app\api\model\Sms as SmsModel;
class SendLogic
{
public static function SendSms($mobile, $sms_type)
{
return SmsModel::sendSms($mobile, randString(6), $sms_type);
}
/**
* @author: Airon
* @time: 2018年5月
* description
* @param $requestData
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function validateCode($requestData)
{
return SmsModel::validateCode(
$requestData['mobile'],
$requestData['code'],
$requestData['sms_type']
);
}
}
\ No newline at end of file
<?php
/**
*
* Created by PhpStorm.
* User: fenggaoyuan
* Email: 253869997@qq.com
* Date: 2018/7/26
* Time: 11:35
*/
namespace app\api\logic\app;
use app\api\model\User;
use think\Config;
use app\api\model\UserOauth;
use think\Db;
use app\common\tools\wechatUtil;
class UserLogic
{
/**
* @author: Airon
* @time: 2018年5月
* description
* @param $mobile
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function checkUser($mobile)
{
$bool = User::build()->where(['mobile' => $mobile, 'is_banned' => 0])->find();
return empty($bool) ? false : true;
}
/**
* @author: Airon
* @time: 2018年5月
* description 公众号登录
* @param $data
* @return array|bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function publicLogin($data)
{
$config = config('wechat');
$result = wechatUtil::getAccessToken($config['PublicAppID'], $config['PublicAppSecret'], $data['jscode']);
$result = json_decode($result, true);
if (!empty($result['errcode'])) {
ResponseDirect( "jsCode验证失败",403);
}
$user_info = wechatUtil::getUserInfo($result['access_token'], $result['openid']);
if(empty($user_info)){
ResponseDirect( "login Error",403);
}
$user_info = json_decode($user_info, true);
$unionid = empty($result['unionid'])?"":$result['unionid'];
$result = [];
$result['unionid'] = $unionid;
$result['oauth_type'] = "wechat_public";
$result['oauth_id'] = $user_info['openid'];
$user = UserOauth::build()
->where(['oauth_id' => $result['oauth_id']])
->find();
if (!empty($user)) {
return ['uuid'=>$user['uuid']];
}
$result['uuid'] = uuid();
$result['create_time'] = timeToDate();
$bool_1 = UserOauth::build()->insert($result);
if (empty($bool_1)) {
return false;
}
return ['uuid' => $result['uuid']];
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: xiezhixian
* Date: 2018/5/4
* Time: 上午10:48
*/
namespace app\api\model;
use think\Model;
use Dysmsapi\Request\V20170525\SendSmsRequest;
require VENDOR_PATH . 'aliApiSdk/aliyun-php-sdk-core/Config.php';
require VENDOR_PATH . 'aliApiSdk/Dysmsapi/Request/V20170525/SendSmsRequest.php';
class Sms extends Model
{
/**
* 表名,
*/
protected $table = 'sms';
protected $dateFormat = false;
/**
* @return Sms
*/
public static function build()
{
return new self();
}
/**
* @author: Airon
* @time: 2018年5月
* description
* @param array $dataMap
* @return int|string
* @throws \think\Exception
*/
public static function whereCount($dataMap = [])
{
return static::build()->where($dataMap)->count();
}
/**
* 发送短信
* @param String $mobile
* @param String $code
* @param String $smsType 短信类型,enum:登录:login 绑定手机号: bind 修改支付密码:pay_password
* @return bool
*/
public static function sendSms($mobile, $code, $smsType)
{
// 调用sdk发送短信
$aliConfig = config('alidayu');
// 加载区域结点配置
// 初始化用户Profile实例
$profile = \DefaultProfile::getProfile("cn-hangzhou", $aliConfig['AccessKey'], $aliConfig['SecretKey']);
// 增加服务结点
\DefaultProfile::addEndpoint("cn-hangzhou", "cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");
// 初始化AcsClient用于发起请求
$acsClient = new \DefaultAcsClient($profile);
// 初始化SendSmsRequest实例用于设置发送短信的参数
$request = new SendSmsRequest();
// 必填,设置雉短信接收号码
$request->setPhoneNumbers($mobile);
// 必填,设置签名名称
$request->setSignName($aliConfig['smsType'][$smsType]['signName']);
// 必填,设置模板CODE
$request->setTemplateCode($aliConfig['smsType'][$smsType]['templateCode']);
$params = array(
'code' => $code,
);
// 可选,设置模板参数
$request->setTemplateParam(json_encode($params));
$acsResponse = $acsClient->getAcsResponse($request);
$send_result = $acsResponse->Code == 'OK' ? 'ok' : $acsResponse->Code . ":" . $acsResponse->Message;
date_default_timezone_set("Asia/Shanghai");//短信SDK强行转换了时区导致PHP无法识别使用了默认时区,这里需要强制转换回上海时区
//修改其它验证码的有效性
self::build()->update(['is_effected' => 0], ['mobile' => $mobile, 'sms_type' => $smsType]);
// 写入数据库
$bool = self::build()->insert([
'uuid' => uuid(),
'mobile' => $mobile,
'sms_type' => $smsType,
'sms_code' => $code,
'send_result' => $send_result,
'create_time' => timeToDate(time()),
'update_time' => timeToDate(time()),
]);
return $bool;
}
/**
* @author: Airon
* @time: 2018年5月
* description 验证短信验证码
* @param $mobile
* @param $code
* @param $smsType
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function validateCode($mobile, $code, $smsType)
{
$smsModel = self::build()->where([
'mobile' => $mobile,
'sms_type' => $smsType,
'is_effected' => '1',
])->order(['create_time' => 'desc'])->find();
// 验证码不存在
if (empty($smsModel)) {
return false;
}
// 验证码已过期
if ((strtotime($smsModel['create_time']) + 3600 ) < time()) {
self::build()->where([ 'uuid' => $smsModel['uuid'] ])->update([ 'is_effected' => '0','update_time'=>timeToDate(time())]);
return false;
}
// 验证码错误,
if ($smsModel['sms_code'] != $code) {
// 尝试次数+1, 尝试次数大于10次,销毁
if ($smsModel['try_times'] >= 10) {
self::build()->where([ 'uuid' => $smsModel['uuid'] ])->update([ 'is_effected' => '0' ]);
} else {
self::build()->where([ 'uuid' => $smsModel['uuid'] ])->inc('try_times')->update();
}
return false;
}
//验证成功后销毁
self::build()->where([ 'uuid' => $smsModel['uuid'] ])->update([ 'is_effected' => '0' ]);
return true;
}
}
<?php
/**
* Created by PhpStorm.
* User: ChiaHsiang
* Date: 2018/8/1
* Time: 20:39
*/
namespace app\api\model;
use think\Db;
use think\Model;
class User extends Model
{
protected $table = 'user';
protected $dateFormat = false;
public static function build() {
return new self();
}
public function saveInfo($requestData, $uuid)
{
return self::build()->where(['uuid' => $uuid])->update($requestData);
}
/**
* @author: Airon
* @time: 2018年5月
* description 验证码登录
* @param $mobile
* @param $oauth_uuid
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function login($mobile,$oauth_uuid)
{
$user = self::build()->where(['mobile' => $mobile])
->field(['nickname','is_deleted','ban_time'],true)->find();
Db::startTrans();
if ($user) {
if ($user['is_banned']) {
ResponseDirect('当前账号已被禁用',403);
}
if(!empty($oauth_uuid)){
$oauth= UserOauth::build()->where(['uuid'=>$oauth_uuid])->find();
if(!empty($oauth)){
UserOauth::build()->where(['user_uuid'=>$user['uuid']])->update(['user_uuid'=>""]);
UserOauth::build()->where(['uuid'=>$oauth_uuid])->update(['user_uuid'=>$user['uuid']]);
}
}
$token = UserToken::storeToken($user['uuid']);
} else {
//创建新用户
$user['uuid'] = uuid();
$user['mobile'] = $mobile;
$user['name'] = replaceToStar($mobile);
$user['create_time'] = timeToDate(time());
// $user['invite_code'] = $this->get_unique_invite_code();
$result = self::build()->insert($user);
if ($result) {
//创建token
$token = UserToken::storeToken($user['uuid']);
if(!empty($oauth_uuid)){
$oauth= UserOauth::build()->where(['uuid'=>$oauth_uuid])->find();
if(!empty($oauth)){
UserOauth::build()->where(['uuid'=>$oauth_uuid])->update(['user_uuid'=>$user['uuid']]);
}
}
} else {
Db::rollback();
return false;
}
}
Db::commit();
$users['token'] = $token;
$users['user_info'] = self::build()
->where(['mobile'=>$mobile])
->field(['nickname','is_deleted','ban_time'],true)
->find();
return $users;
}
}
\ No newline at end of file
<?php
/**
* 用户收货地址模型
* Created by PhpStorm.
* User: fenggaoyuan
* Email: 253869997@qq.com
* Date: 2018/7/26
* Time: 11:49
*/
namespace app\api\model;
use app\api\controller\Send;
use think\Model;
use think\Db;
class UserOauth extends Model
{
protected $table = 'user_oauth';
protected $dateFormat = false;
public static function build()
{
return new self();
}
}
\ No newline at end of file
<?php
namespace app\api\model;
use think\Model;
/**
* TOKEN
*/
class UserToken extends Model
{
/**
* 表名
*/
protected $table = 'user_token';
protected $dateFormat = false;
/**
* @return UserToken
*/
public static function build()
{
return new self();
}
/**
* @author: Airon
* @time: 2018年5月
* description
* @param $token
* @return array|bool|false|\PDOStatement|string|Model
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function validateToken($token)
{
$time = date("Y-m-d H:i:s", time());
$where = ['access_token'=>$token,'expiry_time'=>['gt',$time]];
$user = self::build()->alias('t')
->join('user u', 't.user_uuid=u.uuid')
->where($where)
->field('u.*')
->find();
if ($user) {
$user = $user->toArray();
unset($user['pay_password']);
return $user;
} else {
return false;
}
}
/**
* @author: Airon
* @time: 2018年5月
* description
* @param $uuid
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function storeToken($uuid){
$where = ["user_uuid" => $uuid];
$bool = self::build()->where($where)->field('access_token,refresh_token,expiry_time')->find();
$token['update_time'] = timeToDate(time());
$token['expiry_time'] = timeToDate(time() + 604800);
if($bool){
$token['access_token'] = $bool['access_token'];
$token['refresh_token'] = $bool['refresh_token'];
$bool = self::build()->where($where)->update($token);
}else{
$token['uuid'] = uuid();
$token['access_token'] = token($uuid);
$token['refresh_token'] = token($uuid);
$token['user_uuid'] = $uuid;
$token['create_time'] = timeToDate(time());
$bool = self::build()->insert($token);
}
return $bool?$token:false;
}
/**
* @author: Airon
* @time: 2018年5月
* description
* @param $requestData
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function refreshToken($requestData)
{
$where = ["refresh_token" => $requestData['refresh_token']];
$info = self::build()->where($where)
->field(['user_uuid','access_token','refresh_token','expiry_time'])->find();
if ($info) {
$token['update_time'] = timeToDate(time());
$token['expiry_time'] = timeToDate(time() + 604800);
$token['access_token'] = token($info['user_uuid']);
$token['refresh_token'] = token($info['user_uuid']);
$bool = self::build()->where($where)->update($token);
$token['user_uuid'] = $info['user_uuid'];
return $bool?$token:false;
}
return false;
}
}
\ No newline at end of file
<?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 [];
\ No newline at end of file
<?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>
// +----------------------------------------------------------------------
// 应用公共文件
// 定义静态资源目录 或 URL
define('G_HTTP', isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443' ? "https://" : "http://");
define('G_HTTP_HOST', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : "");
defined('PUBLIC_PATH') or define('PUBLIC_PATH', dirname("https://" . G_HTTP_HOST . $_SERVER['SCRIPT_NAME']));
/**
* 验证POS json格式数据
* @param string $string
* @return string|bool
*/
function isJson($string)
{
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
function get_token()
{
//从协议头获取token
return \think\Request::instance()->header('X-Access-Token');
}
function get_brand()
{
//从协议头获取token
return \think\Request::instance()->header('BRAND');
}
function timeToDate($time = 0)
{
return date("Y-m-d H:i:s", empty($time) ? time() : $time);
}
function randString($len = 4)
{
$chars = str_repeat('0123456789', $len);
$chars = str_shuffle($chars);
$str = substr($chars, 0, $len);
return $str;
}
function getToken()
{
//从协议头获取token
return \think\Request::instance()->header('X-Access-Token');
}
function uuid($prefix = '')
{
$chars = md5(uniqid(mt_rand(), true));
return $prefix . $chars;
}
function object2array($object)
{
$array = array();
if (is_object($object)) {
foreach ($object as $key => $value) {
$array[$key] = $value;
}
} else {
$array = $object;
}
return $array;
}
function curlSend($url)
{
try {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$res = curl_exec($ch);
curl_close($ch);
return $res;
} catch (\Exception $e) {
return false;
}
}
function curl_post($url, $res)
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => FALSE,
CURLOPT_TIMEOUT => 300,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode($res),
CURLOPT_HTTPHEADER => array(
"Content-type: application/json;charset='utf-8'",
)
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
return $err;
} else {
return json_decode($response, true);
}
}
function token($uuid)
{
return md5(md5($uuid . time() . rand(10, 19999)));
}
function logFile($content, $title = 'LOG', $filename = 'log_file')
{
try {
$titleShow = (strlen($title) > 30) ? substr($title, 0, 27) . '...' : $title;
$spaceNum = (66 - strlen($titleShow)) / 2;
$titleShow = '=' . str_repeat(' ', intval($spaceNum)) . $titleShow . str_repeat(' ', ceil($spaceNum)) . '=';
$time = date('Y-m-d H:i:s');
$content = var_export($content, true);
$logContent = <<<EOT
====================================================================
{$titleShow}
====================================================================
time: {$time}
title: {$title}
--------------------------------------------------------------------
content: \n{$content}\n\n\n
EOT;
$logPath = LOG_PATH;
$logName = $filename . date('Ymd') . '.log';
if (!is_dir($logPath)) {
mkdir($logPath);
}
$logFile = fopen($logPath . $logName, "a");
fwrite($logFile, $logContent);
fclose($logFile);
} catch (\Exception $e) {
// do nothing
}
}
function getSign($Obj)
{
foreach ($Obj as $k => $v) {
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = formatBizQueryParaMap($Parameters, false);
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
return $result_;
}
function formatBizQueryParaMap($paraMap, $urlencode)
{
// var_dump($paraMap);//die;
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if ($urlencode) {
$v = urlencode($v);
}
//$buff .= strtolower($k) . "=" . $v . "&";
// $buff .= $k . "=" . $v . "&";
$buff .= $k;
}
/*if (strlen($buff) > 0)
{
$reqPar = substr($buff, 0, strlen($buff)-1);
}*/
return $buff;
}
//将uuid数组组合成 ('1','2','3')这种形式的
function arrayToString($uuid)
{
$uuids = '(';
foreach ($uuid as $k => $v) {
$uuids .= "'" . $v . "',";
}
$uuids = rtrim($uuids, ",");
$uuids .= ')';
return $uuids;
}
/**
* @author: Airon
* @time: 2018年5月
* description 计算百分比
* @param int $divisor 基数
* @param int $dividend 总数
* @return string
*/
function percent($divisor, $dividend)
{
if ($dividend == 0) {
return '0%';
}
return (round($divisor / $dividend, 2) * 100) . "%";
}
/**
* 替换字符串中间位置字符为星号
* @param [type] $str [description]
* @return [type] [description]
*/
function replaceToStar($str)
{
$len = strlen($str) / 2; //a0dca4d0****************ba444758]
return substr_replace($str, str_repeat('*', $len), floor(($len) / 2), $len);
}
/**
* @author: ChiaHsiang
* @time: 2018/8/7
* @description: 判断日期是否连续,0:同一日;1:日期相邻;其他值为日期相差天数
* @param $start
* @param $end
* @return int|mixed
*/
function timeDiff($start, $end) {
$earlier = new DateTime($start);
$later = new DateTime($end);
$date1 = $earlier->format('Y-m-d');
$date2 = $later->format('Y-m-d');
$earlier = new DateTime($date1);
$later = new DateTime($date2);
$day_diff = $later->diff($earlier)->days;
/*if ($day_diff == 0) {
$date1 = $earlier->format('Y-m-d');
$date2 = $later->format('Y-m-d');
dump($date1);dump($date2);exit;
$d1 = explode('-', $date1);
$d2 = explode('-', $date2);
if (end($d1) !== end($d2)) {
return 1;
}
}*/
return $day_diff;
}
/**
* @author: ChiaHsiang
* @time: 2018/8/26
* @description: 直接返回响应
* @param $msg
* @param int $code
*/
function ResponseDirect($msg, $code = 400) {
throw new think\exception\HttpResponseException(json(array('error' => ['message' => $msg]), $code));
}
function array2JsonStr($array) {
$arrayRecursive = function (&$array, $function, $apply_to_keys_also = false) {
static $recursive_counter = 0;
if (++$recursive_counter > 1000) {
die('possible deep recursion attack');
}
foreach ($array as $key => $value) {
if (is_array($value)) {
$this->arrayRecursive($array[$key], $function, $apply_to_keys_also);
} else {
$array[$key] = $function($value);
}
if ($apply_to_keys_also && is_string($key)) {
$new_key = $function($key);
if ($new_key != $key) {
$array[$new_key] = $array[$key];
unset($array[$key]);
}
}
}
$recursive_counter--;
};
$arrayRecursive($array, 'urlencode', true);
$json = json_encode($array);
return urldecode($json);
}
function send_post($url, $post_data) {
$postdata = http_build_query($post_data);
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type:application/x-www-form-urlencoded',
'content' => $postdata,
'timeout' => 15 * 60 // 超时时间(单位:s)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
/**
* 获取客户端IP地址
* @return string
*/
function get_client_ip() {
if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$ip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
$ip = getenv('REMOTE_ADDR');
} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
$ip = $_SERVER['REMOTE_ADDR'];
} else {
$ip = '0.0.0.0';
}
return preg_match('/[\d\.]{7,15}/', $ip, $matches) ? $matches[0] : '';
}
<?php
/**
* Created by PhpStorm.
* User: ChiaHsiang
* Date: 2018/8/20
* Time: 13:03
*/
namespace app\common\behavior;
use app\api\model\AdminLog;
use think\Request;
use think\Session;
use think\Config;
class Log
{
public function run() {
try {
$request = Request::instance();
$controller = $request->controller();
$controller_path = explode('.', $controller);
$controller = strtolower(end($controller_path));
$action = strtolower($request->action());
$data['controller'] = $controller;
$data['action'] = $action;
$data['params'] = $request->param('id');
$admin_info = Session::get('admin_info');
$data['admin_uuid'] = $admin_info['uuid'];
$this->getDesc($data);
$data['uuid'] = uuid();
return AdminLog::build()
->save($data);
} catch (\Exception $e) {
return false;
}
}
private function getDesc(&$data) {
$controller = $data['controller'];
$action = $data['action'];
$log2desc = Config::get('log2desc');
$controller_desc = $log2desc[$controller]['desc'];
$operate_desc = $log2desc[$controller]['action'][$action]['desc'];
$data['desc'] = "管理员在[{$controller_desc}]进行了[{$operate_desc}]操作";
if (!empty($data['params'])) {
$data['desc'] .= ",对应参数 id 为 {$data['params']}";
}
}
}
\ No newline at end of file
<?php
namespace app\common\tools;
use app\admin\model\User;
use \think\Db;
use think\Model;
/**
* 权限验证类
*
* Class Auth
* @package app\common\tools
*/
class Auth
{
/**
* 检查权限
*
* @param $name 获得权限$name 可以是字符串或数组或逗号分割
* @param $uid 认证的用户id
* @param string $relation 是否为or关系,为true是, name为数组,只要数组中有一个条件通过则通过,如果为false需要全部条件通过
* @return bool
* name元素中的字符串需要对大小写保持一致,避免验证 或者添加 strtolower() 函数不区分大小写 为保证数据格式一致,建议转为小(大)写
*/
public function check($uid, $name)
{
$authList = $this->getAuthList($uid);
if (in_array($name, $authList)) {
return true;
}
return false;
}
/**
* 获得权限列表
*
* @param $uid
* @return array
*/
protected function getAuthList($uid)
{
static $_authList = array();
if (isset($_authList[$uid])) {
return $_authList[$uid];
}
//获取所属角色的权限列表
$roles = $this->getRoles($uid);
$ids = array();
foreach ($roles as $g) {
$ids = array_merge($ids, explode(',', trim($g['rule_name'], ',')));
}
$ids = array_unique($ids);
if (empty($ids)) {
$_authList[$uid] = array();
} else {
$_authList[$uid] = $ids;
}
return $_authList[$uid];
}
/**
* 获得用户组,外部也可以调用
*
* @param $uid
* @return mixed
*/
public function getRoles($uid) {
static $groups = array();
if (isset($groups[$uid]))
return $groups[$uid];
$user_groups = Db::name('role_user')->alias('a')->where(['a.user_id'=>$uid])->join('auth_access g', 'a.role_id=g.role_id')->select();
$groups[$uid]=$user_groups?$user_groups:array();
return $groups[$uid];
}
}
<?php
namespace app\common\tools;
use \think\Config;
use \think\Db;
/**
*
*/
class DbManage
{
// 换行符
private static $ds = "\n";
// 一次循环条数
private static $size = 20;
// 每条sql语句的结尾符
private static $sqlEnd = ";";
public static function backup($table, $dir = "backupMysql")
{
$dir = RUNTIME_PATH . $dir . DS . date('Y-m-d') . DS;
if (!file_exists($dir)) {
mkdir($dir, 0755, true);
}
$filename = $table . ".sql";
$sql = self::_startBackup($table);
return file_put_contents($dir . $filename, $sql);
}
/**
* 备份数据表
* @param [type] $table [description]
* @param [type] $dir [description]
* @param [type] $size [description]
* @return [type] [description]
*/
private static function _startBackup($table)
{
try {
$tableColumns = Db::execute("SHOW COLUMNS FROM `{$table}`");
} catch (\PDOException $e) {
return false;
}
// 插入dump信息
$sql = self::_retrieve();
$sql .= self::_insertTableStructure($table);
// 数据总条数
$count = Db::table($table)->count();
if ($count == 0) {
return $sql;
}
// 数据总页数
$pageSize = ceil($count / self::$size);
//数据备份
$sql .= self::_insertRecord($table, $pageSize);
return $sql;
}
/**
* 插入数据库备份基础信息
* @return [type] [description]
*/
private static function _retrieve()
{
$version = self::get('select VERSION() as v');
$value = '';
$value .= '--' . self::$ds;
$value .= '-- MySQL database dump' . self::$ds;
$value .= '-- Created by DbManage class, Power By luffyzhao. ' . self::$ds;
$value .= '-- https://github.com/lovezhao311 ' . self::$ds;
$value .= '--' . self::$ds;
$value .= '-- 主机: ' . Config::get('database.hostname') . self::$ds;
$value .= '-- 生成日期: ' . date('Y') . ' 年 ' . date('m') . ' 月 ' . date('d') . ' 日 ' . date('H:i') . self::$ds;
$value .= '-- MySQL版本: ' . $version['v'] . self::$ds;
$value .= '-- PHP 版本: ' . phpversion() . self::$ds;
$value .= self::$ds;
$value .= '--' . self::$ds;
$value .= '-- 数据库: `' . Config::get('database.database') . '`' . self::$ds;
$value .= '--' . self::$ds . self::$ds;
$value .= '-- -------------------------------------------------------';
$value .= self::$ds . self::$ds;
return $value;
}
/**
* 插入表结构
* @param string $value [description]
* @return [type] [description]
*/
private static function _insertTableStructure($table)
{
$sql = '';
$sql .= "--" . self::$ds;
$sql .= "-- 表的结构" . $table . self::$ds;
$sql .= "--" . self::$ds . self::$ds;
// 如果存在则删除表
$sql .= self::dropTableIfExists($table);
$res = self::get("SHOW CREATE TABLE `user`;");
$sql .= $res['Create Table'] . self::$sqlEnd . self::$ds;
$sql .= self::$ds;
$sql .= "--" . self::$ds;
$sql .= "-- 转存表中的数据 " . $table . self::$ds;
$sql .= "--" . self::$ds;
$sql .= self::$ds;
return $sql;
}
/**
* [_insertRecord description]
* @param [type] $record [description]
* @return [type] [description]
*/
private static function _insertRecord($table, $pageSize)
{
$sql = "INSERT INTO `{$table}` VALUES " . self::$ds;
for ($i = 0; $i < $pageSize; $i++) {
$rows = Db::table($table)->limit($i, self::$size)->select();
$delimiter1 = "";
foreach ($rows as $row) {
$sql .= "{$delimiter1}(";
$delimiter2 = "";
foreach ($row as $value) {
$sql .= "{$delimiter2}" . Db::quote($value);
$delimiter2 = ",";
}
$sql .= ")" . self::$ds;
$delimiter1 = ",";
}
}
$sql .= self::$sqlEnd;
return $sql;
}
/**
* 如果存在则删除表 sql 语句
* @param [type] $table [description]
* @return [type] [description]
*/
private static function dropTableIfExists($table)
{
return "DROP TABLE IF EXISTS `" . $table . '`' . self::$sqlEnd . self::$ds;
}
/**
* [get description]
* @param [type] $sql [description]
* @return [type] [description]
*/
private static function get($sql)
{
$query = Db::query($sql);
return $query[0];
}
}
<?php
namespace app\common\tools;
/**
* ------------------------------------------
* 图片处理类 (GD2库)
* ------------------------------------------
*
* 根据实际需求设计的图片处理类, “居中剪裁”通常使用在用户头像、缩略图等场景, “等比缩放”通常用来压缩图片
*
* 1. 居中剪裁 (宽高自动)
* 2. 等比缩放 (宽高自动, 源图小于宽高的不做缩放)
* 3. 创建缩略图
* 4. 如果操作网络图片, 会在根目录生成"tmp.jpg" (用于测试)
*
*/
class Image
{
protected $sourceImage = ''; // 源文件路径
protected $width = ''; // 要设置的宽度
protected $height = ''; // 要设置的高度
protected $createThumb = false; // 是否创建缩略图
protected $thumbMarker = '_thumb'; // 缩略图后缀
/**
* [__construct description]
* @param array $props [description]
*/
public function __construct($props = array())
{
if (count($props) > 0) {
$this->initialize($props);
}
}
/**
* 初始化配置
* @param [type] $props [description]
* @return [type] [description]
*/
public function initialize($props)
{
$this->clear(); // 清除之前的配置
$this->sourceImage = !isset($props['sourceImage']) ? $this->sourceImage : $props['sourceImage'];
$this->width = !isset($props['width']) ? $this->width : $props['width'];
$this->height = !isset($props['height']) ? $this->height : $props['height'];
$this->createThumb = !isset($props['createThumb']) ? $this->createThumb : $props['createThumb'];
$this->thumbMarker = !isset($props['thumbMarker']) ? $this->thumbMarker : $props['thumbMarker'];
}
/**
* 清除配置
* @return [type] [description]
*/
protected function clear()
{
$this->sourceImage = '';
$this->width = '';
$this->height = '';
$this->createThumb = false;
$this->thumbMarker = '_thumb';
}
/**
* 等比缩放
* @param string $value [description]
* @return [type] [description]
*/
public function resize($value = '')
{
$sourcePath = $this->sourceImage;
$targetWidth = $this->width;
$targetHeight = $this->height;
$sourceInfo = getimagesize($sourcePath);
$sourceWidth = $sourceInfo[0];
$sourceHeight = $sourceInfo[1];
$sourceMime = $sourceInfo['mime'];
switch ($sourceMime) {
case 'image/gif':
$sourceImage = imagecreatefromgif($sourcePath);
break;
case 'image/jpeg':
$sourceImage = imagecreatefromjpeg($sourcePath);
break;
case 'image/png':
$sourceImage = imagecreatefrompng($sourcePath);
break;
default:
$sourceImage = imagecreatefromjpeg($sourcePath); // 兼容app, 许多app上传的图片无mime信息
break;
}
$widthRatio = $targetWidth / $sourceWidth;
$heightRatio = $targetHeight / $sourceHeight;
// 源图宽高均小于要设置的值
if ($widthRatio >= 1 && $heightRatio >= 1) {
$targetImage = $sourceImage;
} else {
// 根据缩放倍率小的宽或者高缩放
if ($widthRatio < $heightRatio) {
$zoom_width = $targetWidth;
$zoom_height = $sourceHeight * ($targetWidth / $sourceWidth);
} else {
$zoom_height = $targetHeight;
$zoom_width = $sourceWidth * ($targetHeight / $sourceHeight);
}
// 声明图片资源
$targetImage = imagecreatetruecolor($zoom_width, $zoom_height);
// 缩放
imagecopyresampled($targetImage, $sourceImage, 0, 0, 0, 0, $zoom_width, $zoom_height, $sourceWidth, $sourceHeight);
}
// 图片地址为url
if (strpos($sourcePath, 'http') !== false) {
imagejpeg($targetImage, $_SERVER['DOCUMENT_ROOT'] . '/tmp.jpg');
} else {
if ($this->createThumb) {
$sourcePath = str_replace('.', $this->thumbMarker . '.', $sourcePath);
}
imagejpeg($targetImage, $sourcePath);
}
//销毁资源
imagedestroy($sourceImage);
@imagedestroy($targetImage);
$this->clear();
}
/**
* 居中剪裁
* @return [type] [description]
*/
public function crop()
{
$sourcePath = $this->sourceImage;
$targetWidth = $this->width;
$targetHeight = $this->height;
$sourceInfo = getimagesize($sourcePath);
$sourceWidth = $sourceInfo[0];
$sourceHeight = $sourceInfo[1];
$sourceMime = $sourceInfo['mime'];
$sourceRatio = $sourceHeight / $sourceWidth;
$targetRatio = $targetHeight / $targetWidth;
if ($sourceRatio > $targetRatio) {
// 源图过高
$croppedWidth = $sourceWidth;
$croppedHeight = $sourceWidth * $targetRatio;
$source_x = 0;
$source_y = ($sourceHeight - $croppedHeight) / 2;
} elseif ($sourceRatio < $targetRatio) {
// 源图过宽
$croppedWidth = $sourceHeight / $targetRatio;
$croppedHeight = $sourceHeight;
$source_x = ($sourceWidth - $croppedWidth) / 2;
$source_y = 0;
} else {
// 源图适中
$croppedWidth = $sourceWidth;
$croppedHeight = $sourceHeight;
$source_x = 0;
$source_y = 0;
}
switch ($sourceMime) {
case 'image/gif':
$sourceImage = imagecreatefromgif($sourcePath);
break;
case 'image/jpeg':
$sourceImage = imagecreatefromjpeg($sourcePath);
break;
case 'image/png':
$sourceImage = imagecreatefrompng($sourcePath);
break;
default:
$sourceImage = imagecreatefromjpeg($sourcePath); // 兼容app, 许多app上传的图片无mime信息
break;
}
// 声明图片资源
$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
$cropped_image = imagecreatetruecolor($croppedWidth, $croppedHeight);
// 裁剪
imagecopy($cropped_image, $sourceImage, 0, 0, $source_x, $source_y, $croppedWidth, $croppedHeight);
// 缩放
imagecopyresampled($targetImage, $cropped_image, 0, 0, 0, 0, $targetWidth, $targetHeight, $croppedWidth, $croppedHeight);
// 图片地址为url
if (strpos($sourcePath, 'http') !== false) {
imagejpeg($targetImage, $_SERVER['DOCUMENT_ROOT'] . '/tmp.jpg');
} else {
if ($this->createThumb) {
$sourcePath = str_replace('.', $this->thumbMarker . '.', $sourcePath);
}
imagejpeg($targetImage, $sourcePath);
}
// 销毁资源
imagedestroy($sourceImage);
imagedestroy($targetImage);
imagedestroy($cropped_image);
$this->clear();
}
}
<?php
/**
* Created by PhpStorm.
* User: rudy
* Date: 17-10-26
* Time: 下午6:14
*/
namespace app\common\tools;
class RedisUtil
{
private static $instance = null;
private static $options = [
'host' => 'redis',
'port' => 6379,
'password' => '0D9F8640-3FB1-4A56-9E26-646F71EE2E45',
'timeout' => 0,
'expire' => 0,
];
public static function getInstance()
{
if (self::$instance == null) {
self::$instance = new \Redis;
self::$instance->connect(self::$options['host'], self::$options['port'], self::$options['timeout']);
if ('' != self::$options['password']) {
self::$instance->auth(self::$options['password']);
}
}
return self::$instance;
}
}
\ No newline at end of file
<?php
namespace app\common\tools;
/**
* 获取受访者信息
*/
class Strings
{
/**
* 替换字符串中间位置字符为星号
* @param [type] $str [description]
* @return [type] [description]
*/
public static function replaceToStar($str)
{
$len = strlen($str) / 2;
return substr_replace($str, str_repeat('*', $len), floor(($len) / 2), $len);
}
/**
* 获取文件访问地址
* @param string $value [description]
*/
public static function fileWebLink($realPath)
{
$replace = dirname(ROOT_PATH);
return str_replace($replace, '', $realPath);
}
/**
* 通过文件访问地址获取 文件绝对地址
* @param string $value [description]
* @return [type] [description]
*/
public static function fileWebToServer($webLink)
{
$replace = dirname(ROOT_PATH);
return $replace . $webLink;
}
/**
* 删除文件
* @param string $value [description]
* @return [type] [description]
*/
public static function deleteFile($filename)
{
if (!file_exists($filename)) {
$filename = self::fileWebToServer($filename);
}
if (file_exists($filename) && is_file($filename)) {
unlink($filename);
}
}
}
<?php
namespace app\common\tools;
/**
* 获取受访者信息
*/
class Visitor
{
/**
* 获取浏览器
* @return [type] [description]
*/
public static function getBrowser()
{
$agent = $_SERVER["HTTP_USER_AGENT"];
if (strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) //ie11判断
{
return "ie";
} else if (strpos($agent, 'Firefox') !== false) {
return "firefox";
} else if (strpos($agent, 'Chrome') !== false) {
return "chrome";
} else if (strpos($agent, 'Opera') !== false) {
return 'opera';
} else if ((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false) {
return 'safari';
} else if (strpos($agent, 'MicroMessenger') !== false) {
return 'weixin';
} else {
return 'unknown';
}
}
/**
* 获取浏览器版本号
* @return [type] [description]
*/
public static function getBrowserVer()
{
if (empty($_SERVER['HTTP_USER_AGENT'])) {
//当浏览器没有发送访问者的信息的时候
return 'unknow';
}
$agent = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif (preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif (preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif (preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) {
return $regs[1];
} elseif ((strpos($agent, 'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) {
return $regs[1];
} else {
return 'unknow';
}
}
/**
* 获取ip
* @return [type] [description]
*/
public static function getIP()
{
if (getenv('HTTP_CLIENT_IP')) {
$ip = getenv('HTTP_CLIENT_IP');
} else if (getenv('HTTP_X_FORWARDED_FOR')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} else if (getenv('REMOTE_ADDR')) {
$ip = getenv('REMOTE_ADDR');
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
/**
* 获取用户系统
* @return [type] [description]
*/
public static function getOs()
{
$agent = $_SERVER['HTTP_USER_AGENT'];
$os = false;
if (preg_match('/win/i', $agent) && strpos($agent, '95')) {
$os = 'Windows 95';
} else if (preg_match('/win 9x/i', $agent) && strpos($agent, '4.90')) {
$os = 'Windows ME';
} else if (preg_match('/win/i', $agent) && preg_match('/98/i', $agent)) {
$os = 'Windows 98';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 6.0/i', $agent)) {
$os = 'Windows Vista';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 6.1/i', $agent)) {
$os = 'Windows 7';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 6.2/i', $agent)) {
$os = 'Windows 8';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 10.0/i', $agent)) {
$os = 'Windows 10'; #添加win10判断
} else if (preg_match('/win/i', $agent) && preg_match('/nt 5.1/i', $agent)) {
$os = 'Windows XP';
} else if (preg_match('/win/i', $agent) && preg_match('/nt 5/i', $agent)) {
$os = 'Windows 2000';
} else if (preg_match('/win/i', $agent) && preg_match('/nt/i', $agent)) {
$os = 'Windows NT';
} else if (preg_match('/win/i', $agent) && preg_match('/32/i', $agent)) {
$os = 'Windows 32';
} else if (preg_match('/linux/i', $agent)) {
$os = 'Linux';
} else if (preg_match('/unix/i', $agent)) {
$os = 'Unix';
} else if (preg_match('/sun/i', $agent) && preg_match('/os/i', $agent)) {
$os = 'SunOS';
} else if (preg_match('/ibm/i', $agent) && preg_match('/os/i', $agent)) {
$os = 'IBM OS/2';
} else if (preg_match('/Mac/i', $agent) && preg_match('/10_12_2/i', $agent)) {
$os = 'Mac OS X 10_12_2';
}else if (preg_match('/Mac/i', $agent)) {
$os = 'Mac OS X';
}else if (preg_match('/PowerPC/i', $agent)) {
$os = 'PowerPC';
} else if (preg_match('/AIX/i', $agent)) {
$os = 'AIX';
} else if (preg_match('/HPUX/i', $agent)) {
$os = 'HPUX';
} else if (preg_match('/NetBSD/i', $agent)) {
$os = 'NetBSD';
} else if (preg_match('/BSD/i', $agent)) {
$os = 'BSD';
} else if (preg_match('/OSF1/i', $agent)) {
$os = 'OSF1';
} else if (preg_match('/IRIX/i', $agent)) {
$os = 'IRIX';
} else if (preg_match('/FreeBSD/i', $agent)) {
$os = 'FreeBSD';
} else if (preg_match('/teleport/i', $agent)) {
$os = 'teleport';
} else if (preg_match('/flashget/i', $agent)) {
$os = 'flashget';
} else if (preg_match('/webzip/i', $agent)) {
$os = 'webzip';
} else if (preg_match('/offline/i', $agent)) {
$os = 'offline';
} else {
$os = 'unknow';
}
return $os;
}
}
<?php
/**
* Created by PhpStorm.
* User: fio
* Date: 2017/2/21
* Time: 下午4:47
*/
namespace app\common\tools;
class wechatUtil
{
public static function getAccessToken($appId, $secret, $code)
{
if (empty($appId) || empty($secret) || empty($code)) {
return false;
}
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?"
. "appid={$appId}&secret={$secret}&code={$code}&grant_type=authorization_code";
$result = self::getCurl($url);
return $result;
}
public static function getUserInfo($accessToken, $openId)
{
if (empty($accessToken) || empty($openId)) {
return false;
}
$url = "https://api.weixin.qq.com/sns/userinfo?"
. "access_token={$accessToken}&openid={$openId}";
$result = self::getCurl($url);
return $result;
}
/*
* 获取公众号access_token
*/
public static function getPublicAccessToken($appId, $appSecret)
{
$access_token = RedisUtil::getInstance()->get('wechat_public_access_token');
if (!empty($access_token)) {
return $access_token;
}
$url = "https://api.weixin.qq.com/cgi-bin/token"
. "?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
$result = self::getCurl($url);
$result = json_decode($result, true);
if (!empty($result['errcode'])) {
return false;
}
RedisUtil::getInstance()->set('wechat_public_access_token', $result['access_token'], $result['expires_in']);
return $result['access_token'];
}
public static function getJSAPITicket($appId, $appSecret)
{
$jsapi_ticket = RedisUtil::getInstance()->get('wechat_jsapi_ticket');
if (!empty($jsapi_ticket)) {
return $jsapi_ticket;
}
$access_token = self::getPublicAccessToken($appId, $appSecret);
if (empty($access_token)) {
return false;
}
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$access_token}&type=jsapi";
$result = self::getCurl($url);
$result = json_decode($result, true);
if (!empty($result['errcode'])) {
return false;
}
RedisUtil::getInstance()->set('wechat_jsapi_ticket', $result['ticket'], $result['expires_in']);
return $result['ticket'];
}
public static function getShareSign($appId, $appSecret, $url)
{
$ticket = self::getJSAPITicket($appId, $appSecret);
if(empty($ticket)){
return false;
}
$requestData = [
'timestamp' => time(),
'noncestr' => wechatUtil::getRandomString(32),
'jsapi_ticket' => $ticket,
'url' => $url
];
$sign = self::makeSha1Sign($requestData);
$requestData['signature'] = $sign;
return $requestData;
}
// get方法请求
public static function getCurl($url)
{
try {
$curlHandle = curl_init();
curl_setopt($curlHandle, CURLOPT_URL, $url);
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, false);
$result = curl_exec($curlHandle);
curl_close($curlHandle);
return $result;
} catch (\Exception $e) {
return false;
}
}
public static function curl_post_ssl($url, $vars)
{
try {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);//证书检查
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
curl_setopt($ch, CURLOPT_SSLCERT, dirname(__FILE__) . '/wechatCert/apiclient_cert.pem');//证书路径
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
curl_setopt($ch, CURLOPT_SSLKEY, dirname(__FILE__) . '/wechatCert/apiclient_key.pem');
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/wechatCert/DigiCert_Global_Root_CA.pem');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
$data = curl_exec($ch);
curl_close($ch);
return $data;
} catch (\Exception $e) {
return false;
}
}
// post方法请求
public static function postCurl($url, $postData)
{
try {
$curlHandle = curl_init();
curl_setopt($curlHandle, CURLOPT_URL, $url);
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curlHandle, CURLOPT_POST, 1);
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $postData);
$result = curl_exec($curlHandle);
curl_close($curlHandle);
return $result;
} catch (\Exception $e) {
return false;
}
}
public static function getRandomString($length = 6)
{
$chars = array(
"a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t",
"u", "v", "w", "x", "y", "z",
"A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N",
"O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z",
"0", "1", "2", "3", "4",
"5", "6", "7", "8", "9"
);
$charsLen = count($chars) - 1;
shuffle($chars);
$output = "";
for ($i = 0; $i < $length; $i++) {
$output .= $chars[mt_rand(0, $charsLen)];
}
return $output;
}
public static function toUrlParams($dataArray)
{
$buff = "";
foreach ($dataArray as $k => $v) {
if (strtolower($k) != "sign" && $v != "" && !is_array($v)) {
$buff .= "{$k}={$v}&";
}
}
unset($k);
unset($v);
$buff = trim($buff, "&");
return $buff;
}
public static function makeSign($dataArray, $key)
{
//签名步骤一:按字典序排序参数
ksort($dataArray);
$string = self::toUrlParams($dataArray);
//签名步骤二:在string后加入KEY
$string = $string . "&key=" . $key;
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
public static function makeSha1Sign($dataArray)
{
//签名步骤一:按字典序排序参数
ksort($dataArray);
$string = self::toUrlParams($dataArray);
//签名步骤二:对string进行sha1签名,得到signature
$result = sha1($string);
return $result;
}
public static function toXml($dataArray)
{
if (!is_array($dataArray) || count($dataArray) <= 0) {
// throw new WxPayException("数组数据异常!");
return false;
}
$xml = "<xml>";
foreach ($dataArray as $key => $val) {
if (is_numeric($val)) {
$xml .= "<{$key}>{$val}</{$key}>";
} else {
$xml .= "<{$key}><![CDATA[{$val}]]></{$key}>";
}
}
$xml .= "</xml>";
return $xml;
}
public static function xmlParser($data)
{
unset($vals);
unset($parser);
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); // 不转换为大写
xml_parse_into_struct($parser, $data, $vals);
xml_parser_free($parser);
$result = [];
foreach ($vals as $item) {
if ($item['tag'] == 'xml') {
continue;
}
$result[$item['tag']] = $item['value'];
}
return $result;
}
public static function log_file($content, $title = 'LOG', $filename = 'wc_log_file', $logPath)
{
try {
$titleShow = (strlen($title) > 30) ? substr($title, 0, 27) . '...' : $title;
$spaceNum = (66 - strlen($titleShow)) / 2;
$titleShow = '=' . str_repeat(' ', intval($spaceNum)) . $titleShow . str_repeat(' ', ceil($spaceNum)) . '=';
$time = date('Y-m-d H:i:s');
$content = var_export($content, true);
$logContent = <<<EOT
====================================================================
{$titleShow}
====================================================================
time: {$time}
title: {$title}
--------------------------------------------------------------------
content: \n{$content}\n\n\n
EOT;
$logName = $filename . date('Ymd') . '.log';
if (!is_dir($logPath)) {
mkdir($logPath);
}
$logFile = fopen($logPath . $logName, "a");
fwrite($logFile, $logContent);
fclose($logFile);
} catch (\Exception $e) {
// do nothing
}
}
}
<?php
/**
* Created by PhpStorm.
* User: airon
*/
namespace app\common\validate;
use think\Validate;
class Base extends Validate
{
protected $regex = [
'mobile' => '1\d{10}'
];
protected $rule = [
'page_index' => 'require|number|gt:0',
'page_size' => 'require|number|gt:0',
'uuid' => 'require|length:32',
'id' => 'require|number|gt:0',
'content' => 'require|max:255',
'mobile' => 'require|number|length:11|regex:mobile',
'sms_type' => 'require|in:login,bind,pay_password',
'partner_sms_type' => 'require|in:pass,set_pay,bind_card',
'code' => 'require|max:6',
'password' => 'require|min:6',
'message_type' => 'require|in:con,chat,system',
'province' => 'chsAlpha',
'school_name' => 'chsAlpha',
'city.json' => 'chsAlpha',
'money' => 'require|number|egt:1',
'pay_type' => 'require|in:alipay,wechat',
'nya' => 'in:no,yes,all,,',
'ny' => 'in:no,yes',
'tf' => 'in:no,yes,0,1,true,false',
'id_can_null' => 'number|gt:0',
'keyword' => 'chsDash',
'refresh_token' => 'require|length:32',
'collect_type' => 'require|in:school,speciality',
'name' => 'require|chsAlphaNum|length:0,64',
'gender' => 'require|in:男,女',
'birth' => 'require|chsAlphaNum|length:0,64',
'avatar' => 'require|chsAlphaNum|length:0,64',
'city' => 'require|chsAlphaNum|length:0,64',
];
protected $field = [
'mobile' => '手机号码'
];
protected $message = [
'page_index' => '页码要大于0',
'page_size' => '每页数量要大于0',
'id' => 'id参数不符合',
'content.require' => '内容不能为空',
'content.max' => '超出最大长度',
'mobile.regex' => ':attribute格式错误',
'sms_type' => '短信类型错误',
'code' => '验证码格式错误',
'password.require' => '密码必须',
'password.min' => '密码过短',
'message_type' => '消息类型错误',
'province' => '省份设置错误',
'city.json' => '城市设置错误',
'money' => '金额格式不正确',
'pay_type' => '充值方式不正确',
'nya' => '参数不正确',
'ny' => '参数不正确',
'id_can_null' => '参数不正确',
'keyword' => '关键字不能带符号',
'tf' => 'bool错误',
'collect_type' => '收藏类型',
'name' => '姓名',
'gender' => '性别',
'birth' => '出生年月',
'avatar' => '头像',
'city' => '所在地区',
];
protected $scene = [
'page_index' => ['page_index'],
'page_size' => ['page_size'],
'page' => ['page_index', 'page_size'],
'id' => ['id'],
'uuid' => ['uuid'],
'sendSms' => ['mobile', 'sms_type'],
'sendPartnerSms' => ['mobile', 'sms_type_partner'],
'validatePartnerCode' => ['mobile', 'sms_type_partner', 'code'],
'validateCode' => ['mobile', 'sms_type', 'code'],
'login' => ['mobile', 'code'],
'bind' => ['mobile', 'code', 'password'],
'nya' => ['nya'],
'ny' => ['ny'],
'id_can_null' => ['id_can_null'],
'keyword' => ['keyword'],
'tf' => ['tf'],
'refresh_token' => ['refresh_token'],
'feedback' => ['content'],
'collect_list' => ['collect_type'],
'cmsLogin' => ['name', 'password'],
'admissionScore' => ['province','school_name'],
'batchCritical' => ['province']
];
public function getEnumRule($words)
{
$reg = implode('|', $words);
$rule = "/^({$reg})$/";
return $rule;
}
}
<?php
namespace app\common\validate;
use \think\Db;
trait Validate
{
/**
* 验证是否存在!
* @author luffy<luffyzhao@vip.126.com>
* @dateTime 2016-04-19T09:48:57+0800
* @param [type] $roleId [description]
* @return [type] [description]
*/
public function exist($value, $rule, $data)
{
if (is_string($rule)) {
$rule = explode(',', $rule);
}
$db = Db::table($rule[0]);
$field = isset($rule[1]) ? $rule[1] : 'id';
$map = [$field => $value];
if ($db->where($map)->field($field)->find()) {
return true;
}
return false;
}
/**
* 验证PID是否存在 并且不等于本身
* @author luffy<luffyzhao@vip.126.com>
* @dateTime 2016-06-03T16:47:36+0800
* @param [type] $value [description]
* @param [type] $rule [description]
* @param [type] $data [description]
* @return [type] [description]
*/
public function existPid($value, $rule, $data)
{
if (intval($value) === 0) {
return true;
}
if (is_string($rule)) {
$rule = explode(',', $rule);
}
$db = Db::table($rule[0]);
$field = $db->getPk($rule[0]);
if (isset($data[$field]) && $data[$field] == $value) {
return false;
}
if ($db->where([$field => $value])->field($field)->find()) {
return true;
}
return false;
}
}
<?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_namespace' => 'app',
// 应用调试模式
'app_debug' => true,
// 应用Trace
// 'app_trace' => true,
// 应用模式状态
'app_status' => '',
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展配置文件
'extra_config_list' => ['database', 'validate'],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
'default_return_type' => 'html', //DIY
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'PRC',
// 是否开启多语言
'lang_switch_on' => true,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'www',
// 禁止访问模块
'deny_module_list' => ['common'],
//允许访问模块
'allow_module_list' => ['www','admin'],
// 默认控制器名
'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_config_file' => ['route'],
// 是否强制使用路由
'url_route_must' => false,
// 域名部署
'url_domain_deploy' => false,
// 域名根,如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 模板路径
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DS,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// 视图输出字符串内容替换
'view_replace_str' => [
'__STATIC__DOMAIN__'=>STATIC_PATH,
],
// 默认跳转页面对应的模板文件
'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' => '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,
],
// +----------------------------------------------------------------------
// | 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,
],
//写安装程序的时候随即生成authId
'user_auth_key' => 'authId',
'wechat_min' => [
'appid' => 'wxb6cbb81471348fec',
'secret' => 'b201962b8a3da757c72a0747eb6f1110',
],
'wechat_h5' => [
'appid' => 'wxeabf215955fdf1e4',
'secret' => '27a2b6b68510ba7ec7882bd8aa7f5364',
],
'wechat_app' => [
'appid' => 'wxb7e13ea0208bc4c1',
'secret' => 'b2b4a4085061d15241936c3114b6d9d6',
],
'qq' => [
'appid' => '1106125395',
'secret' => 'BFkuRYzTkHdTmtIs',
],
'jiguang' => [
'appid' => '7c76ead627d2e75a1667eb1a',
'secret' => 'a8f86a0630cc51d7a110ea0a',
],
'qiniu' => [
'AccessKey' => 'Jyi6Ntprm38nI6n1heGjwXyQmzie8ZjY7l9Cq_Je',
'SecretKey' => 'eBqe82USZuB6gnqvjTsyg_qki6C6HwnkFIvNIH-y',
'BucketName' => 'dankal-cdn',
'BucketDomain' => 'http://or9tdbe53.bkt.clouddn.com/',
],
];
<?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 [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => 'db.dankal.cn',
// 数据库名
'database' => 'template',
// 用户名
'username' => 'deploy',
// 密码
'password' => '0D9F8640-3FB1-4A56-9E26-646F71EE2E45',
// 端口
'hostport' => '3306',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型 array 数组 collection Collection对象
'resultset_type' => 'array',
// 是否自动写入时间戳字段
'auto_timestamp' => true,
// 是否需要进行SQL性能分析
'sql_explain' => false,
];
<?php
/**
* Created by PhpStorm.
* User: xiezhixian
* Date: 2018/5/4
* Time: 上午10:50
*/
return [
'AccessKey' => '',
'SecretKey' => '',
'smsType' => [
'bind' => [
'signName' => '',
'templateCode' => 'SMS_158941940',
'smsParam' => [
'code' => '',
],
],
'login' => [
'signName' => '',
'templateCode' => 'SMS_158941936',
'smsParam' => [
'code' => '',
],
],
'pass' => [
'signName' => '',
'templateCode' => 'SMS_158941943',
'smsParam' => [
'code' => '',
],
]
],
];
<?php
// +----------------------------------------------------------------------
// | Qiniu设置
// +----------------------------------------------------------------------
return [
'AccessKey' => '',
'SecretKey' => '',
'BucketName' => '',
'BucketDomain' => '',
'OverseasBucketName' =>''
];
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: Airon
* Date: 2017/4/14
* Time: 10:13
*/
// +----------------------------------------------------------------------
// | 微信设置
// +----------------------------------------------------------------------
return [
'Pay' => [
'MchId' => "",
'Key' => ''
],
//公众号
'PublicAppID' => '',
'PublicAppSecret' => "",
'PublicPay' => [
'MchId' => "",
'Key' => ''
],
];
\ No newline at end of file
<?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>
// +----------------------------------------------------------------------
use think\Route;
use think\Request;
Route::resource(':version/app/Send', 'api/:version.app.Send');//短信
Route::resource(':version/app/User', 'api/:version.app.User');//用户 //注册一个资源路由
//restful方法中另外一个方法等。。。
Route::rule(':version/app/User/login', 'api/:version.app.User/login');//用户登录
Route::rule(':version/app/User/updateToken', 'api/:version.app.User/updateToken');//更新token
Route::rule(':version/app/User/publicLogin', 'api/:version.app.User/publicLogin');//公众号授权
Route::rule(':version/app/User/pointDeal', 'api/:version.app.User/pointDeal');//积分明细
Route::rule(':version/app/User/getShareSign', 'api/:version.app.User/getShareSign');
Route::rule(':version/app/Send/validate', 'api/:version.app.Send/validate');//验证
Route::miss('Error/index');
$request = Request::instance();
if ($request->method() === "OPTIONS") {
exit (json_encode(array('error' => 200, 'message' => 'Options Success.')));
}
return [
'__pattern__' => [
'name' => '\w+',
],
];
<?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_init' => [],
// 应用开始
'app_begin' => [],
// 模块初始化
'module_init' => [],
// 操作开始执行
'action_begin' => [],
// 视图内容过滤
'view_filter' => [],
// 日志写入
'log_write' => [],
// 应用结束
'app_end' => [],
];
<?php
namespace app\www\controller;
use think\Request;
class Error
{
public function index()
{
return json(array('error'=>405,'message'=>'No routing path can be found for the request.'));
}
}
\ No newline at end of file
<?php
namespace app\www\controller;
use app\common\controller\Common;
class Index extends Common
{
public function index()
{
return '';
}
}
\ No newline at end of file
<?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'],
],
// 其他更多的模块定义
// 定义test模块的自动生成
'test'=>[
'__dir__' => ['behavior','controller','model','widget'],
'controller'=> ['Index','Test','UserType'],
'model' => ['User','UserType'],
'view' => ['index/index','index/test'],
],
];
{
"name": "topthink/think",
"description": "the new thinkphp framework",
"type": "project",
"keywords": [
"framework",
"thinkphp",
"ORM"
],
"homepage": "http://thinkphp.cn/",
"license": "Apache-2.0",
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
}
],
"require": {
"php": ">=5.4.0",
"topthink/framework": "5.0.*",
"topthink/think-captcha": "^1.0.7",
"topthink/think-testing": "^1.0",
"zircote/swagger-php": "^2.0",
"qiniu/php-sdk": "^7.2",
"jpush/jpush": "^3.5"
},
"extra": {
"think-path": "thinkphp"
},
"config": {
"preferred-install": "dist"
}
}
This diff is collapsed. Click to expand it.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">application/</directory>
</whitelist>
</filter>
</phpunit>
<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>
<?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>
// +----------------------------------------------------------------------
// [ 应用入口文件 ]
if(version_compare(PHP_VERSION,'5.4.0','<')) die('require PHP > 5.4.0 !');
// 定义应用目录
define('APP_PATH', __DIR__ . '/../app/');
// 定义静态资源目录 或 URL
define('STATIC_PATH', '/static/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
User-agent: *
Disallow:
<?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 {
require __DIR__ . "/index.php";
}
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* version: 1.11.0
* https://github.com/wenzhixin/bootstrap-table/
*/
.bootstrap-table .table {
margin-bottom: 0 !important;
border-bottom: 1px solid #dddddd;
border-collapse: collapse !important;
border-radius: 1px;
}
.bootstrap-table .table:not(.table-condensed),
.bootstrap-table .table:not(.table-condensed) > tbody > tr > th,
.bootstrap-table .table:not(.table-condensed) > tfoot > tr > th,
.bootstrap-table .table:not(.table-condensed) > thead > tr > td,
.bootstrap-table .table:not(.table-condensed) > tbody > tr > td,
.bootstrap-table .table:not(.table-condensed) > tfoot > tr > td {
padding: 8px;
}
.bootstrap-table .table.table-no-bordered > thead > tr > th,
.bootstrap-table .table.table-no-bordered > tbody > tr > td {
border-right: 2px solid transparent;
}
.bootstrap-table .table.table-no-bordered > tbody > tr > td:last-child {
border-right: none;
}
.fixed-table-container {
position: relative;
clear: both;
border: 1px solid #dddddd;
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
}
.fixed-table-container.table-no-bordered {
border: 1px solid transparent;
}
.fixed-table-footer,
.fixed-table-header {
overflow: hidden;
}
.fixed-table-footer {
border-top: 1px solid #dddddd;
}
.fixed-table-body {
overflow-x: auto;
overflow-y: auto;
height: 100%;
}
.fixed-table-container table {
width: 100%;
}
.fixed-table-container thead th {
height: 0;
padding: 0;
margin: 0;
border-left: 1px solid #dddddd;
}
.fixed-table-container thead th:focus {
outline: 0 solid transparent;
}
.fixed-table-container thead th:first-child {
border-left: none;
border-top-left-radius: 4px;
-webkit-border-top-left-radius: 4px;
-moz-border-radius-topleft: 4px;
}
.fixed-table-container thead th .th-inner,
.fixed-table-container tbody td .th-inner {
padding: 8px;
line-height: 24px;
vertical-align: top;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.fixed-table-container thead th .sortable {
cursor: pointer;
background-position: right;
background-repeat: no-repeat;
padding-right: 30px;
}
.fixed-table-container thead th .both {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC');
}
.fixed-table-container thead th .asc {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==');
}
.fixed-table-container thead th .desc {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ');
}
.fixed-table-container th.detail {
width: 30px;
}
.fixed-table-container tbody td {
border-left: 1px solid #dddddd;
}
.fixed-table-container tbody tr:first-child td {
border-top: none;
}
.fixed-table-container tbody td:first-child {
border-left: none;
}
/* the same color with .active */
.fixed-table-container tbody .selected td {
background-color: #f5f5f5;
}
.fixed-table-container .bs-checkbox {
text-align: center;
}
.fixed-table-container .bs-checkbox .th-inner {
padding: 8px 0;
}
.fixed-table-container input[type="radio"],
.fixed-table-container input[type="checkbox"] {
margin: 0 auto !important;
}
.fixed-table-container .no-records-found {
text-align: center;
}
.fixed-table-pagination div.pagination,
.fixed-table-pagination .pagination-detail {
margin-top: 10px;
margin-bottom: 10px;
}
.fixed-table-pagination div.pagination .pagination {
margin: 0;
}
.fixed-table-pagination .pagination a {
padding: 6px 12px;
line-height: 1.428571429;
}
.fixed-table-pagination .pagination-info {
line-height: 34px;
margin-right: 5px;
}
.fixed-table-pagination .btn-group {
position: relative;
display: inline-block;
vertical-align: middle;
}
.fixed-table-pagination .dropup .dropdown-menu {
margin-bottom: 0;
}
.fixed-table-pagination .page-list {
display: inline-block;
}
.fixed-table-toolbar .columns-left {
margin-right: 5px;
}
.fixed-table-toolbar .columns-right {
margin-left: 5px;
}
.fixed-table-toolbar .columns label {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.428571429;
}
.fixed-table-toolbar .bs-bars,
.fixed-table-toolbar .search,
.fixed-table-toolbar .columns {
position: relative;
margin-top: 10px;
margin-bottom: 10px;
line-height: 34px;
}
.fixed-table-pagination li.disabled a {
pointer-events: none;
cursor: default;
}
.fixed-table-loading {
display: none;
position: absolute;
top: 42px;
right: 0;
bottom: 0;
left: 0;
z-index: 99;
background-color: #fff;
text-align: center;
}
.fixed-table-body .card-view .title {
font-weight: bold;
display: inline-block;
min-width: 30%;
text-align: left !important;
}
/* support bootstrap 2 */
.fixed-table-body thead th .th-inner {
box-sizing: border-box;
}
.table th, .table td {
vertical-align: middle;
box-sizing: border-box;
}
.fixed-table-toolbar .dropdown-menu {
text-align: left;
max-height: 300px;
overflow: auto;
}
.fixed-table-toolbar .btn-group > .btn-group {
display: inline-block;
margin-left: -1px !important;
}
.fixed-table-toolbar .btn-group > .btn-group > .btn {
border-radius: 0;
}
.fixed-table-toolbar .btn-group > .btn-group:first-child > .btn {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.fixed-table-toolbar .btn-group > .btn-group:last-child > .btn {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.bootstrap-table .table > thead > tr > th {
vertical-align: bottom;
border-bottom: 1px solid #ddd;
}
/* support bootstrap 3 */
.bootstrap-table .table thead > tr > th {
padding: 0;
margin: 0;
}
.bootstrap-table .fixed-table-footer tbody > tr > td {
padding: 0 !important;
}
.bootstrap-table .fixed-table-footer .table {
border-bottom: none;
border-radius: 0;
padding: 0 !important;
}
.pull-right .dropdown-menu {
right: 0;
left: auto;
}
/* calculate scrollbar width */
p.fixed-table-scroll-inner {
width: 100%;
height: 200px;
}
div.fixed-table-scroll-outer {
top: 0;
left: 0;
visibility: hidden;
width: 200px;
height: 150px;
overflow: hidden;
}
/*
Common
*/
.wizard,
.tabcontrol
{
display: block;
width: 100%;
overflow: hidden;
}
.wizard a,
.tabcontrol a
{
outline: 0;
}
.wizard ul,
.tabcontrol ul
{
list-style: none !important;
padding: 0;
margin: 0;
}
.wizard ul > li,
.tabcontrol ul > li
{
display: block;
padding: 0;
}
/* Accessibility */
.wizard > .steps .current-info,
.tabcontrol > .steps .current-info
{
position: absolute;
left: -999em;
}
.wizard > .content > .title,
.tabcontrol > .content > .title
{
position: absolute;
left: -999em;
}
/*
Wizard
*/
.wizard > .steps
{
position: relative;
display: block;
width: 100%;
}
.wizard.vertical > .steps
{
display: inline;
float: left;
width: 30%;
}
.wizard > .steps > ul > li
{
width: 25%;
}
.wizard > .steps > ul > li,
.wizard > .actions > ul > li
{
float: left;
}
.wizard.vertical > .steps > ul > li
{
float: none;
width: 100%;
}
.wizard > .steps a,
.wizard > .steps a:hover,
.wizard > .steps a:active
{
display: block;
width: auto;
margin: 0 0.5em 0.5em;
padding: 8px;
text-decoration: none;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.wizard > .steps .disabled a,
.wizard > .steps .disabled a:hover,
.wizard > .steps .disabled a:active
{
background: #eee;
color: #aaa;
cursor: default;
}
.wizard > .steps .current a,
.wizard > .steps .current a:hover,
.wizard > .steps .current a:active
{
background: #1AB394;
color: #fff;
cursor: default;
}
.wizard > .steps .done a,
.wizard > .steps .done a:hover,
.wizard > .steps .done a:active
{
background: #6fd1bd;
color: #fff;
}
.wizard > .steps .error a,
.wizard > .steps .error a:hover,
.wizard > .steps .error a:active
{
background: #ED5565 ;
color: #fff;
}
.wizard > .content
{
background: #eee;
display: block;
margin: 5px 5px 10px 5px;
min-height: 120px;
overflow: hidden;
position: relative;
width: auto;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.wizard-big.wizard > .content {
min-height: 320px;
}
.wizard.vertical > .content
{
display: inline;
float: left;
margin: 0 2.5% 0.5em 2.5%;
width: 65%;
}
.wizard > .content > .body
{
float: left;
position: absolute;
width: 95%;
height: 95%;
padding: 2.5%;
}
.wizard > .content > .body ul
{
list-style: disc !important;
}
.wizard > .content > .body ul > li
{
display: list-item;
}
.wizard > .content > .body > iframe
{
border: 0 none;
width: 100%;
height: 100%;
}
.wizard > .content > .body input
{
display: block;
border: 1px solid #ccc;
}
.wizard > .content > .body input[type="checkbox"]
{
display: inline-block;
}
.wizard > .content > .body input.error
{
background: rgb(251, 227, 228);
border: 1px solid #fbc2c4;
color: #8a1f11;
}
.wizard > .content > .body label
{
display: inline-block;
margin-bottom: 0.5em;
}
.wizard > .content > .body label.error
{
color: #8a1f11;
display: inline-block;
margin-left: 1.5em;
}
.wizard > .actions
{
position: relative;
display: block;
text-align: right;
width: 100%;
}
.wizard.vertical > .actions
{
display: inline;
float: right;
margin: 0 2.5%;
width: 95%;
}
.wizard > .actions > ul
{
display: inline-block;
text-align: right;
}
.wizard > .actions > ul > li
{
margin: 0 0.5em;
}
.wizard.vertical > .actions > ul > li
{
margin: 0 0 0 1em;
}
.wizard > .actions a,
.wizard > .actions a:hover,
.wizard > .actions a:active
{
background: #1AB394;
color: #fff;
display: block;
padding: 0.5em 1em;
text-decoration: none;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.wizard > .actions .disabled a,
.wizard > .actions .disabled a:hover,
.wizard > .actions .disabled a:active
{
background: #eee;
color: #aaa;
}
.wizard > .loading
{
}
.wizard > .loading .spinner
{
}
/*
Tabcontrol
*/
.tabcontrol > .steps
{
position: relative;
display: block;
width: 100%;
}
.tabcontrol > .steps > ul
{
position: relative;
margin: 6px 0 0 0;
top: 1px;
z-index: 1;
}
.tabcontrol > .steps > ul > li
{
float: left;
margin: 5px 2px 0 0;
padding: 1px;
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.tabcontrol > .steps > ul > li:hover
{
background: #edecec;
border: 1px solid #bbb;
padding: 0;
}
.tabcontrol > .steps > ul > li.current
{
background: #fff;
border: 1px solid #bbb;
border-bottom: 0 none;
padding: 0 0 1px 0;
margin-top: 0;
}
.tabcontrol > .steps > ul > li > a
{
color: #5f5f5f;
display: inline-block;
border: 0 none;
margin: 0;
padding: 10px 30px;
text-decoration: none;
}
.tabcontrol > .steps > ul > li > a:hover
{
text-decoration: none;
}
.tabcontrol > .steps > ul > li.current > a
{
padding: 15px 30px 10px 30px;
}
.tabcontrol > .content
{
position: relative;
display: inline-block;
width: 100%;
height: 35em;
overflow: hidden;
border-top: 1px solid #bbb;
padding-top: 20px;
}
.tabcontrol > .content > .body
{
float: left;
position: absolute;
width: 95%;
height: 95%;
padding: 2.5%;
}
.tabcontrol > .content > .body ul
{
list-style: disc !important;
}
.tabcontrol > .content > .body ul > li
{
display: list-item;
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// validator
function zh_validator() {
// 验证手机号
jQuery.validator.addMethod("mobile", function(value, element) {
var tel = /^1[3|4|5|7|8]\d{9}$/;
return this.optional(element) || (tel.test(value));
}, "Please enter a valid phone number");
// 验证身份证号
jQuery.validator.addMethod("cardid", function(value, element) {
var tel = /^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$/;
return this.optional(element) || (tel.test(value));
}, "Please enter a valid ID number");
// 自定义正则验证
jQuery.validator.addMethod("regular", function(value, element) {
var regular = eval(element.getAttribute('data-rule-regular'));
return this.optional(element) || (regular.test(value));
}, "Input error");
$.extend($.validator.messages, {
required: "This field is required.",
remote: "Please fix this field.",
email: "Please enter a valid email address.",
url: "Please enter a valid URL.",
date: "Please enter a valid date.",
dateISO: "Please enter a valid date ( ISO ).",
number: "Please enter a valid number.",
digits: "Please enter only digits.",
equalTo: "Please enter the same value again.",
maxlength: $.validator.format( "Please enter no more than {0} characters." ),
minlength: $.validator.format( "Please enter at least {0} characters." ),
rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
range: $.validator.format( "Please enter a value between {0} and {1}." ),
max: $.validator.format( "Please enter a value less than or equal to {0}." ),
min: $.validator.format( "Please enter a value greater than or equal to {0}." ),
step: $.validator.format( "Please enter a multiple of {0}." )
});
}
// table
function zh_table() {
$.extend($.fn.bootstrapTable.defaults, {
formatLoadingMessage: function () {
return 'Loading, please wait...';
},
formatRecordsPerPage: function (pageNumber) {
return pageNumber + ' rows per page';
},
formatShowingRows: function (pageFrom, pageTo, totalRows) {
return 'Showing ' + pageFrom + ' to ' + pageTo + ' of ' + totalRows + ' rows';
},
formatSearch: function () {
return 'Search';
},
formatNoMatches: function () {
return 'No matching records found';
},
formatPaginationSwitch: function () {
return 'Hide/Show pagination';
},
formatRefresh: function () {
return 'Refresh';
},
formatToggle: function () {
return 'Toggle';
},
formatColumns: function () {
return 'Columns';
},
formatAllRows: function () {
return 'All';
},
formatExport: function () {
return 'Export data';
},
formatClearFilters: function () {
return 'Clear filters';
}
});
}
/*
* metismenu - v2.0.2
* A jQuery menu plugin
* https://github.com/onokumus/metisMenu
*
* Made by Osman Nuri Okumus
* Under MIT License
*/
!function(a){"use strict";function b(){var a=document.createElement("mm"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}function c(b){return this.each(function(){var c=a(this),d=c.data("mm"),f=a.extend({},e.DEFAULTS,c.data(),"object"==typeof b&&b);d||c.data("mm",d=new e(this,f)),"string"==typeof b&&d[b]()})}a.fn.emulateTransitionEnd=function(b){var c=!1,e=this;a(this).one("mmTransitionEnd",function(){c=!0});var f=function(){c||a(e).trigger(d.end)};return setTimeout(f,b),this};var d=b();d&&(a.event.special.mmTransitionEnd={bindType:d.end,delegateType:d.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}});var e=function(b,c){this.$element=a(b),this.options=a.extend({},e.DEFAULTS,c),this.transitioning=null,this.init()};e.TRANSITION_DURATION=350,e.DEFAULTS={toggle:!0,doubleTapToGo:!1,activeClass:"active"},e.prototype.init=function(){var b=this,c=this.options.activeClass;this.$element.find("li."+c).has("ul").children("ul").addClass("collapse in"),this.$element.find("li").not("."+c).has("ul").children("ul").addClass("collapse"),this.options.doubleTapToGo&&this.$element.find("li."+c).has("ul").children("a").addClass("doubleTapToGo"),this.$element.find("li").has("ul").children("a").on("click.metisMenu",function(d){var e=a(this),f=e.parent("li"),g=f.children("ul");return d.preventDefault(),f.hasClass(c)?b.hide(g):b.show(g),b.options.doubleTapToGo&&b.doubleTapToGo(e)&&"#"!==e.attr("href")&&""!==e.attr("href")?(d.stopPropagation(),void(document.location=e.attr("href"))):void 0})},e.prototype.doubleTapToGo=function(a){var b=this.$element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},e.prototype.show=function(b){var c=this.options.activeClass,f=a(b),g=f.parent("li");if(!this.transitioning&&!f.hasClass("in")){g.addClass(c),this.options.toggle&&this.hide(g.siblings().children("ul.in")),f.removeClass("collapse").addClass("collapsing").height(0),this.transitioning=1;var h=function(){f.removeClass("collapsing").addClass("collapse in").height(""),this.transitioning=0};return d?void f.one("mmTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(e.TRANSITION_DURATION).height(f[0].scrollHeight):h.call(this)}},e.prototype.hide=function(b){var c=this.options.activeClass,f=a(b);if(!this.transitioning&&f.hasClass("in")){f.parent("li").removeClass(c),f.height(f.height())[0].offsetHeight,f.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var g=function(){this.transitioning=0,f.removeClass("collapsing").addClass("collapse")};return d?void f.height(0).one("mmTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(e.TRANSITION_DURATION):g.call(this)}};var f=a.fn.metisMenu;a.fn.metisMenu=c,a.fn.metisMenu.Constructor=e,a.fn.metisMenu.noConflict=function(){return a.fn.metisMenu=f,this}}(jQuery);
\ No newline at end of file
/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version: 1.3.6
*
*/
(function(e){e.fn.extend({slimScroll:function(g){var a=e.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},g);this.each(function(){function v(d){if(r){d=d||window.event;
var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);e(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&m(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function m(d,e,g){k=!1;var f=d,h=b.outerHeight()-c.outerHeight();e&&(f=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),f=Math.min(Math.max(f,0),h),f=0<d?Math.ceil(f):Math.floor(f),c.css({top:f+"px"}));l=parseInt(c.css("top"))/(b.outerHeight()-c.outerHeight());
f=l*(b[0].scrollHeight-b.outerHeight());g&&(f=d,d=f/b[0].scrollHeight*b.outerHeight(),d=Math.min(Math.max(d,0),h),c.css({top:d+"px"}));b.scrollTop(f);b.trigger("slimscrolling",~~f);w();p()}function x(){u=Math.max(b.outerHeight()/b[0].scrollHeight*b.outerHeight(),30);c.css({height:u+"px"});var a=u==b.outerHeight()?"none":"block";c.css({display:a})}function w(){x();clearTimeout(B);l==~~l?(k=a.allowPageScroll,C!=l&&b.trigger("slimscroll",0==~~l?"top":"bottom")):k=!1;C=l;u>=b.outerHeight()?k=!0:(c.stop(!0,
!0).fadeIn("fast"),a.railVisible&&h.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(B=setTimeout(function(){a.disableFadeOut&&r||y||z||(c.fadeOut("slow"),h.fadeOut("slow"))},1E3))}var r,y,z,B,A,u,l,C,k=!1,b=e(this);if(b.parent().hasClass(a.wrapperClass)){var n=b.scrollTop(),c=b.closest("."+a.barClass),h=b.closest("."+a.railClass);x();if(e.isPlainObject(g)){if("height"in g&&"auto"==g.height){b.parent().css("height","auto");b.css("height","auto");var q=b.parent().parent().height();b.parent().css("height",
q);b.css("height",q)}if("scrollTo"in g)n=parseInt(a.scrollTo);else if("scrollBy"in g)n+=parseInt(a.scrollBy);else if("destroy"in g){c.remove();h.remove();b.unwrap();return}m(n,!1,!0)}}else if(!(e.isPlainObject(g)&&"destroy"in g)){a.height="auto"==a.height?b.parent().height():a.height;n=e("<div></div>").addClass(a.wrapperClass).css({position:"relative",overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden",width:a.width,height:a.height});var h=e("<div></div>").addClass(a.railClass).css({width:a.size,
height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=e("<div></div>").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius,WebkitBorderRadius:a.borderRadius,zIndex:99}),q="right"==a.position?
{right:a.distance}:{left:a.distance};h.css(q);c.css(q);b.wrap(n);b.parent().append(c);b.parent().append(h);a.railDraggable&&c.bind("mousedown",function(a){var b=e(document);z=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);m(0,c.position().top,!1)});b.bind("mouseup.slimscroll",function(a){z=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll",function(a){a.stopPropagation();a.preventDefault();return!1});
h.hover(function(){w()},function(){p()});c.hover(function(){y=!0},function(){y=!1});b.hover(function(){r=!0;w();p()},function(){r=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(A=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&(m((A-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),A=b.originalEvent.touches[0].pageY)});x();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),
m(0,!0)):"top"!==a.start&&(m(e(a.start).position().top,null,!0),a.alwaysVisible||c.hide());window.addEventListener?(this.addEventListener("DOMMouseScroll",v,!1),this.addEventListener("mousewheel",v,!1)):document.attachEvent("onmousewheel",v)}});return this}});e.fn.extend({slimscroll:e.fn.slimScroll})})(jQuery);
\ No newline at end of file
// validator
function zh_validator() {
// 验证手机号
jQuery.validator.addMethod("mobile", function(value, element) {
var tel = /^1[3|4|5|7|8]\d{9}$/;
return this.optional(element) || (tel.test(value));
}, "请输入有效的手机号码");
// 验证身份证号
jQuery.validator.addMethod("cardid", function(value, element) {
var tel = /^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$/;
return this.optional(element) || (tel.test(value));
}, "请输入有效的身份证号");
// 自定义正则验证
jQuery.validator.addMethod("regular", function(value, element) {
var regular = eval(element.getAttribute('data-rule-regular'));
return this.optional(element) || (regular.test(value));
}, "输入有误");
$.extend($.validator.messages, {
required: "这是必填字段",
remote: "请修正此字段",
email: "请输入有效的电子邮件地址",
url: "请输入有效的网址",
date: "请输入有效的日期",
dateISO: "请输入有效的日期 (YYYY-MM-DD)",
number: "请输入有效的数字",
digits: "只能输入数字",
creditcard: "请输入有效的信用卡号码",
equalTo: "你的输入不相同",
extension: "请输入有效的后缀",
maxlength: $.validator.format("最多可以输入 {0} 个字符"),
minlength: $.validator.format("最少要输入 {0} 个字符"),
rangelength: $.validator.format("请输入长度在 {0} 到 {1} 位字符"),
range: $.validator.format("请输入范围在 {0} 到 {1} 之间的数值"),
max: $.validator.format("请输入不大于 {0} 的数值"),
min: $.validator.format("请输入不小于 {0} 的数值")
});
}
// table
function zh_table() {
$.extend($.fn.bootstrapTable.defaults, {
formatLoadingMessage: function() {
return '加载数据中,请稍候……'; },
formatRecordsPerPage: function(pageNumber) {
return '每页显示 ' + pageNumber + ' 条记录'; },
formatShowingRows: function(pageFrom, pageTo, totalRows) {
return '显示第 ' + pageFrom + ' 到第 ' + pageTo + ' 条记录,总共 ' + totalRows + ' 条记录'; },
formatSearch: function() {
return '搜索'; },
formatNoMatches: function() {
return '没有找到匹配的记录'; },
formatRefresh: function() {
return '刷新'; },
formatToggle: function() {
return '切换'; },
formatColumns: function() {
return '选择列'; }
});
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"swagger": "2.0",
"paths": {
"/index": {
"get": {
"tags": [
"\u7528\u6237\u4fe1\u606f"
],
"summary": "Add a new pet to the store",
"description": "",
"operationId": "read",
"consumes": [
"multipart/form-data"
],
"produces": [
"multipart/form-data"
],
"parameters": [
{
"name": "id",
"description": "Pet object that needs to be added to the store",
"required": false,
"schema": {
"$ref": "#/definitions/Pet"
},
"paramType": "form"
}
],
"responses": {
"405": {
"description": "Invalid input"
}
},
"security": [
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
]
}
}
},
"definitions": {}
}
\ No newline at end of file
/*
Navicat Premium Data Transfer
Source Server : test_dankal
Source Server Type : MySQL
Source Server Version : 50722
Source Host : db.dankal.cn:3306
Source Schema : template
Target Server Type : MySQL
Target Server Version : 50722
File Encoding : 65001
Date: 11/03/2019 09:47:31
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for address
-- ----------------------------
DROP TABLE IF EXISTS `address`;
CREATE TABLE `address` (
`uuid` char(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '地址表 uuid',
`user_uuid` char(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户uuid',
`province` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '省',
`city` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '市',
`area` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '区',
`detail` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '详细地址',
`is_invalid` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否有效:o:有效;1:无效',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `uuid` (`uuid`),
KEY `IK_ADDRESS_USER_UUID` (`user_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='地址表';
-- ----------------------------
-- Table structure for captcha
-- ----------------------------
DROP TABLE IF EXISTS `captcha`;
CREATE TABLE `captcha` (
`uuid` char(32) NOT NULL,
`code` int(6) NOT NULL,
`create_time` datetime NOT NULL,
`type` tinyint(4) DEFAULT NULL,
`mobile` char(11) DEFAULT NULL,
PRIMARY KEY (`uuid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for carousel
-- ----------------------------
DROP TABLE IF EXISTS `carousel`;
CREATE TABLE `carousel` (
`uuid` char(32) NOT NULL,
`images` varchar(255) DEFAULT NULL,
`sort` int(10) DEFAULT NULL,
`title` varchar(128) DEFAULT NULL COMMENT '标题',
`content` text,
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for classify
-- ----------------------------
DROP TABLE IF EXISTS `classify`;
CREATE TABLE `classify` (
`uuid` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类 uuid',
`type` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '类型',
`operator` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '操作员uuid',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除:o:未删除;1:已删除',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `uuid` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='分类表';
-- ----------------------------
-- Table structure for evaluate
-- ----------------------------
DROP TABLE IF EXISTS `evaluate`;
CREATE TABLE `evaluate` (
`uuid` varchar(33) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '评价uuid',
`user_uuid` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户 uuid',
`grade` tinyint(1) NOT NULL DEFAULT '1' COMMENT '评分:1-5',
`content` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '评价',
`images` json DEFAULT NULL COMMENT '评价图片意见',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除:o:未删除;1:已删除',
`is_handle` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否处理:o:未处理;1:已处理',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `uuid` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='评价表';
-- ----------------------------
-- Table structure for feedback
-- ----------------------------
DROP TABLE IF EXISTS `feedback`;
CREATE TABLE `feedback` (
`uuid` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '意见反馈 uuid',
`user_uuid` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 uuid',
`images` json DEFAULT NULL COMMENT '反馈图片意见',
`content` text COLLATE utf8mb4_unicode_ci COMMENT '内容',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除:o:未删除;1:已删除',
`is_handle` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否处理:o:未处理;1:已处理',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `uuid` (`uuid`),
KEY `IK_FEEDBACK_USER_UUID` (`user_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='意见反馈表';
-- ----------------------------
-- Table structure for push
-- ----------------------------
DROP TABLE IF EXISTS `push`;
CREATE TABLE `push` (
`uuid` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '推送 uuid',
`user_uuid` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户uuid',
`tags` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户所属组',
`title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '推送标题',
`content` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '推送内容',
`ico` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '推送图标',
`attribute` json DEFAULT NULL COMMENT '属性',
`type` tinyint(1) unsigned DEFAULT '0' COMMENT '推送类型:0:系统消息;1;other',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `uuid` (`uuid`),
KEY `IK_PUSH_USER_UUID` (`user_uuid`),
KEY `IK_PUSH_TAGS` (`tags`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='推送表';
-- ----------------------------
-- Table structure for questions
-- ----------------------------
DROP TABLE IF EXISTS `questions`;
CREATE TABLE `questions` (
`uuid` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '常见问题uuid',
`classify_uuid` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类 uuid',
`title` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标题',
`content` text COLLATE utf8mb4_unicode_ci COMMENT '内容',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除:o:未删除;1:已删除',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `uuid` (`uuid`),
KEY `IK_CLASSIFY_UUID` (`classify_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='常见问题表';
-- ----------------------------
-- Table structure for receiver
-- ----------------------------
DROP TABLE IF EXISTS `receiver`;
CREATE TABLE `receiver` (
`uuid` char(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '收件 uuid',
`user_uuid` char(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户uuid',
`address_uuid` char(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地址uuid',
`name` char(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '收件人名',
`mobile` char(15) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '手机号',
`is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否默认:o:默认;1:非默认',
`is_invalid` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否有效:o:有效;1:无效',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`uuid`),
UNIQUE KEY `uuid` (`uuid`),
KEY `IK_RECEIVER_USER_UUID` (`user_uuid`),
KEY `IK_RECEIVER_ADDRESS_UUID` (`address_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收件表';
-- ----------------------------
-- Table structure for search_term
-- ----------------------------
DROP TABLE IF EXISTS `search_term`;
CREATE TABLE `search_term` (
`uuid` char(32) NOT NULL,
`search_term` char(32) NOT NULL COMMENT '搜索词',
`create_time` datetime DEFAULT NULL,
`search_num` int(11) DEFAULT NULL COMMENT '搜索数量',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for token
-- ----------------------------
DROP TABLE IF EXISTS `token`;
CREATE TABLE `token` (
`uuid` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'uuid',
`user_uuid` char(32) NOT NULL COMMENT '用户uuid',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`access_token` char(32) NOT NULL,
`refresh_token` char(32) NOT NULL COMMENT '刷新token使用的token',
`expiry_time` datetime DEFAULT NULL,
PRIMARY KEY (`uuid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`uuid` char(32) NOT NULL,
`name` char(32) DEFAULT NULL,
`mobile` char(11) DEFAULT NULL,
`avatar` varchar(255) DEFAULT NULL,
`attribute` json DEFAULT NULL,
`create_time` datetime NOT NULL,
`password` varchar(45) DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SET FOREIGN_KEY_CHECKS = 1;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment