Mr.chen的技术博客，发布一些常用的组件以及冷门知识，如有想知道的知识，请留言。
安装该扩展需要 PHP 7.1+ 和 ThinkPHP 6.0+，针对 TP 5.1 请使用 Think-Casbin .使用composer安装：composer require casbin/think-authz注册服务，在应用的全局公共文件service.php中加入：return [ // ... tauthz\TauthzService::class, ];发布配置文件和数据库迁移文件：php think tauthz:publish这将自动生成 config/tauthz-rbac-model.conf 和 config/tauthz.php 文件。执行迁移工具（确保数据库配置信息正确）：php think migrate:run这将创建名为 rules 的表。用法快速开始安装成功后，可以这样使用: use tauthz\facade\Enforcer; // adds permissions to a user Enforcer::addPermissionForUser('eve', 'articles', 'read'); // adds a role for a user. Enforcer::addRoleForUser('eve', 'writer'); // adds permissions to a rule Enforcer::addPolicy('writer', 'articles','edit'); 你可以检查一个用户是否拥有某个权限:// to check if a user has permission if (Enforcer::enforce("eve", "articles", "edit")) { // permit eve to edit articles } else { // deny the request, show an error } 使用 Enforcer Api它提供了非常丰富的 API，以促进对 Policy 的各种操作：获取所有角色:Enforcer::getAllRoles(); // ['writer', 'reader']获取所有的角色的授权规则：Enforcer::getPolicy();获取某个用户的所有角色：Enforcer::getRolesForUser('eve'); // ['writer']获取某个角色的所有用户：Enforcer::getUsersForRole('writer'); // ['eve']决定用户是否拥有某个角色：Enforcer::hasRoleForUser('eve', 'writer'); // true or false给用户添加角色：Enforcer::addRoleForUser('eve', 'writer');赋予权限给某个用户或角色：// to user Enforcer::addPermissionForUser('eve', 'articles', 'read'); // to role Enforcer::addPermissionForUser('writer', 'articles','edit');删除用户的角色：Enforcer::deleteRoleForUser('eve', 'writer');删除某个用户的所有角色：Enforcer::deleteRolesForUser('eve');删除单个角色：Enforcer::deleteRole('writer');删除某个权限：Enforcer::deletePermission('articles', 'read'); // returns false if the permission does not exist (aka not affected).删除某个用户或角色的权限：Enforcer::deletePermissionForUser('eve', 'articles', 'read');删除某个用户或角色的所有权限：// to user Enforcer::deletePermissionsForUser('eve'); // to role Enforcer::deletePermissionsForUser('writer');获取用户或角色的所有权限：Enforcer::getPermissionsForUser('eve'); // return array决定某个用户是否拥有某个权限Enforcer::hasPermissionForUser('eve', 'articles', 'read'); // true or false更多 API 参考 Casbin API 。使用中间件该扩展包带有一个 \tauthz\middleware\Basic::class 中间件:Route::get('news/:id','News/Show') ->middleware(\tauthz\middleware\Basic::class, ['news', 'read']);感谢Casbin，你可以查看全部文档在其 官网 上。LicenseThis project is licensed under the Apache 2.0 license.
ThinkLogViewer基于 Thinkphp5 开发的日志浏览组件。该组件为我们提供了一键浏览当前项目日志的功能。安装composer require qsnh/think-log-viewer使用在命令行输入：php think run之后打开浏览器，输入：http://127.0.0.1:8000/log可以看到：配置该扩展包默认注册了 /logs 路由，对应的控制器是 Qsnh\Think\Log\Controllers\LogViewerController@index 如果您因为权限原因或者路由路径问题等原因的话，请自己在 /route/route.php 文件中覆盖该路径。具体可以这样：Route::get('/logs', function () {}); Route::get('/backend/logs', 'Qsnh\Think\Log\Controllers\LogViewerController@index');请注意控制好权限！ 上面代码并不推荐在生产环境下使用，因为闭包无法进行路由缓存。AuthorQsnh
网页授权流程分为四步1、引导用户进入授权页面同意授权，获取code2、通过code换取网页授权access_token（与基础支持中的access_token不同）3、如果需要，开发者可以刷新网页授权access_token，避免过期4、通过网页授权access_token和openid获取用户基本信息（支持UnionID机制）第一步：在微信里面打开链接https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirectAPPID:公众号的appid REDIRECT_URI：返回地址 SCOPE: snsapi_userinfo（弹窗授权）或者snsapi_base（静默授权）第二步：用code换取openidhttps://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_codeAPPID:公众号的appid SECRET:公众号的SECRET CODE：第一步获取的CODE { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }第三步：获取access_token（如需刷新）access_token 作为微信接口全局访问的唯一调用凭据 ，公众号调用各个接口时候都需要使用access_token 。获取一次有效期2小时，一天有次数限制，一般来说，获取一次需要保存起来，两小时内可以无限使用于其他https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRETAPPID:公众号的appid SECRET:公众号的SECRET 返回{"access_token":"ACCESS_TOKEN","expires_in":7200}获取用户信息https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CNACCESS_TOKEN:第三步获取的access_token openid:第二步获取的openid 返回{ "openid":" OPENID", "nickname": NICKNAME, "sex":"1", "province":"PROVINCE", "city":"CITY", "country":"COUNTRY", "headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
function curl_get($url)//自定义函数,访问url返回结果 { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec($curl); if (curl_errno($curl)) { return 'ERROR' . curl_error($curl); } curl_close($curl); return $data; }function curl_post($url, $data) { $headers = array( "Content-Type: application/json;charset=utf-8" ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // POST数据 curl_setopt($ch, CURLOPT_POST, 1); // 把post的变量加上 curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $output = curl_exec($ch); curl_close($ch); return $output; }
/** * 加密 * @param $data * @param string $key * @return string */ function encrypt($data, $key = '112233') { $char = ''; $str = ''; $key = md5($key); $x = 0; $len = strlen($data); $l = strlen($key); for ($i = 0; $i < $len; $i++) { if ($x == $l) { $x = 0; } $char .= $key{$x}; $x++; } for ($i = 0; $i < $len; $i++) { $str .= chr(ord($data{$i}) + (ord($char{$i})) % 256); } return base64_encode($str); } /** * 解密 * @param $data * @param string $key * @return string */ function decrypt($data, $key = '112233') { $char = ''; $str = ''; $key = md5($key); $x = 0; $data = base64_decode($data); $len = strlen($data); $l = strlen($key); for ($i = 0; $i < $len; $i++) { if ($x == $l) { $x = 0; } $char .= substr($key, $x, 1); $x++; } for ($i = 0; $i < $len; $i++) { if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) { $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1))); } else { $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1))); } } return $str; }
引入css Html代码 引入组件js JS代码 组件JS (easyeditor.js/face.js 放在modules)在压缩包里面组件下载点击下载
组件效果Html代码 JS代码 //引入下面的组件JS 组件JS(xm-select.js 引入即可)点击打开
组件效果Html代码 JS代码layui.use(['inputTags'],function(){//非必要 var inputTags = layui.inputTags; inputTags.render({ elem:'#inputTags',//定义输入框input对象 content: ['标题一','标题二'],//默认标签 aldaBtn: true,//是否开启获取所有数据的按钮 done: function(value){ //回车后的回调 console.log(value) } }) })//非必要组件JS (inputTags.js 放在modules)/* * @Author: layui-2 * @Date: 2018-08-31 11:40:42 * @Last Modified by: layui-2 * @Last Modified time: 2018-09-04 14:44:38 */ layui.define(['jquery','layer'],function(exports){ "use strict"; var $ = layui.jquery,layer = layui.layer //外部接口 ,inputTags = { config: {} //设置全局项 ,set: function(options){ var that = this; that.config = $.extend({}, that.config, options); return that; } // 事件监听 ,on: function(events, callback){ return layui.onevent.call(this, MOD_NAME, events, callback) } } //操作当前实例 ,thisinputTags = function(){ var that = this ,options = that.config; return { config: options } } //字符常量 ,MOD_NAME = 'inputTags' // 构造器 ,Class = function(options){ var that = this; that.config = $.extend({}, that.config, inputTags.config, options); that.render(); }; //默认配置 Class.prototype.config = { close: false //默认:不开启关闭按钮 ,theme: '' //背景:颜色 ,content: [] //默认标签 ,aldaBtn: false //默认配置 }; // 初始化 Class.prototype.init = function(){ var that = this ,spans = '' ,options = that.config ,span = document.createElement("span"), spantext = $(span).text("获取全部数据").addClass('albtn'); if(options.aldaBtn){ $('body').append(spantext) } $.each(options.content,function(index,item){ spans +=''+item+' × '; // $(' '+ ELEM_TEXT +' '); }) options.elem.before(spans) that.events() } Class.prototype.render = function(){ var that = this ,options = that.config options.elem = $(options.elem); that.enter() }; // 回车生成标签 Class.prototype.enter = function(){ var that = this ,spans = '' ,options = that.config; options.elem.focus(); options.elem.keypress(function(event){ var keynum = (event.keyCode ? event.keyCode : event.which); if(keynum == '13'){ var $val = options.elem.val().trim(); if(!$val) return false; if(options.content.indexOf($val) == -1){ options.content.push($val) that.render() spans =''+$val+' × '; options.elem.before(spans) } options.done && typeof options.done === 'function' && options.done($val); options.elem.val(''); } }) }; //事件处理 Class.prototype.events = function(){ var that = this ,options = that.config; $('.albtn').on('click',function(){ console.log(options.content) }) $('#tags').on('click','.close',function(){ var Thisremov = $(this).parent('span').remove(), ThisText = $(Thisremov).find('em').text(); options.content.splice($.inArray(ThisText,options.content),1) }) }; //核心入口 inputTags.render = function(options){ var inst = new Class(options); inst.init(); return thisinputTags.call(inst); }; exports('inputTags',inputTags); }).link('./inputTags.css')