fastadmin
https://forum.fastadmin.net/thread/323
fa_admin”管理员表”
fa_admin_log”管理员日志表”
fa_attachment”附件表”
fa_auth_group”分组表”
fa_auth_group_access”权限分组表”
fa_auth_rule”节点表”
fa_category”分类表”
fa_config”系统配置”
fa_ems”邮箱验证码表”
fa_sms”短信验证码表”
fa_user”会员表”
fa_user_group”会员组表”
fa_user_money_log”会员余额变动表”
fa_user_rule”会员规则表”
fa_user_score_log”会员积分变动表”
fa_user_token”会员Token表”
fa_version”版本表”
post-body.bs.table
时间名称onPostBody jquery事件post-body.bs.table data 在表格体渲染完成,并在 DOM 中可见后触发
//在表格内容渲染完成后回调的事件 table.on('post-body.bs.table', function (e, json) { $("tbody tr[data-index]", this).each(function () { if (parseInt($("td:eq(1)", this).text()) == Config.admin.id) { $("input[type=checkbox]", this).prop("disabled", true); } }); }); $("input[type=checkbox]", this).prop("disabled", true); 禁用一个按钮 alert(JSON.stringify($.fn.bootstrapTable.defaults.extend)); {"index_url":"auth/admin/index","add_url":"auth/admin/add","edit_url":"auth/admin/edit","del_url":"auth/admin/del","import_url":"","multi_url":"auth/admin/multi","dragsort_url":"ajax/weigh"} Table.api.init({ extend: { index_url: 'auth/admin/index', add_url: 'auth/admin/add2', edit_url: 'auth/admin/edit', del_url: 'auth/admin/del', multi_url: 'auth/admin/multi', } }); Table.api.init会覆盖$.fn.bootstrapTable.defaults.extend的内容 // 初始化表格 field为字段名 table.bootstrapTable({ url: $.fn.bootstrapTable.defaults.extend.index_url, columns: [ [ {field: 'state', checkbox: true, }, //复选框 {field: 'id', title: 'ID'}, // {field: 'username', title: __('Username')}, {field: 'nickname', title: __('Nickname')}, {field: 'groups_text', title: __('Group'), operate:false, formatter: Table.api.formatter.label}, {field: 'email', title: __('Email')}, {field: 'status', title: __("Status"), formatter: Table.api.formatter.status}, {field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) { if(row.id == Config.admin.id){ return ''; } return Table.api.formatter.operate.call(this, value, row, index); }} ] ] }); {field: 'state', checkbox: true, } |
FastAdmin封装了许多常用的formatter方法,我们可以快速的调用即可。
> `Table.api.formatter.icon` 快速将字段渲染成一个按钮,仅支持Fontawesome按钮 > `Table.api.formatter.image` 快速将字段渲染成图片展示的形式 > `Table.api.formatter.images` 快速将字段渲染成多图片展示的形式,字段数据请以`,`进行分隔 > `Table.api.formatter.status` 快速将字段渲染成状态,默认`normal/hidden/deleted/locked`这四个状态 > `Table.api.formatter.url` 快速将字段渲染成URL框 > `Table.api.formatter.search` 快速将字段渲染成可搜索的链接,点击后将执行搜索 > `Table.api.formatter.addtabs` 快速将字段渲染成可添加到选项卡的链接,点击后将把链接添加到选项卡 > `Table.api.formatter.flag` 快速将字段渲染成标志,仅支持`index/hot/recommend/new`这四种标志 > `Table.api.formatter.label` 快速将字段渲染Label标签 > `Table.api.formatter.datetime` 快速时间戳数据渲染成日期时间数据 > `Table.api.formatter.operate` 操作栏固定按钮 > `Table.api.formatter.buttons` 快速生成多个按钮 > `Table.api.formatter.toggle` 快速生成切换按钮
flag格式化
{field: 'platform', title: __('platform'), formatter: Table.api.formatter.flag, custom: { 'Mp': 'info', 'MpShop': 'success'}, searchList: {'Mp': '用户端', 'MpShop': '商家端'} }, |
关联模型
data-source 请求的接口,数据源,可以根据data-params属性自定义请求参数
data-primary-key 列表选中后渲染的字段(value值)
data-field 列表显示读取的字段 option值
<input id="c-car_brand_id" data-rule="required" data-primary-key='Id' data-field="brandname" data-source="car/brand/index" class="form-control selectpage" name="row[car_brand_id]" type="text" value="{$row.car_brand_id}"> |
$("#c-type_name").data("params", function (obj) { return {custom: {classification_id:$('#c-type_id').val()}}; }); Controller.api.bindevent(); |
add: function () { $("#c-category_id").data("params", function (obj) { return {"custom": {"pid": $('#c-parent_category_id').val(), "type": "project_type"}} } ); Controller.api.bindevent(); }, |
更多参考:https://doc.fastadmin.net/docs/component.html
{:__(‘Car_brand_id’)} 在此控制器的语言配置文件中可以自定义
列表首页允许显示关联模型字段 在js文件columns中定义
foreach ($list as $row) { $row->getRelation('brand')->visible(['brandname']); } |
select单选框
<select id="c-type" data-rule="required" class="form-control selectpicker" name="row[type]"> {foreach name="typeList" item="vo"} <option value="{$key}" {in name="key" value=""}selected{/in}>{$vo}</option> {/foreach} </select> |
select多选框 multiple=””
<select id="c-flag" class="form-control selectpicker" multiple="" name="row[flag][]"> {foreach name="flagList" item="vo"} <option value="{$key}" {in name="key" value=""}selected{/in}>{$vo}</option> {/foreach} </select> |
开发示例
省市区联动(通过AJAX读取数据)
<form id="cxselectform"> <div class="form-inline" data-toggle="cxselect" data-selects="province,city,area"> <select class="province form-control" name="province" data-url="ajax/area"> <option value="1964" selected="">广东省</option> </select> <select class="city form-control" name="city" data-url="ajax/area"> <option value="1988" selected="">深圳市</option> </select> <select class="area form-control" name="area" data-url="ajax/area"> <option value="1991" selected="">南山区</option> </select> </div> </form> |
对应的js文件绑定
Form.api.bindevent($("form#cxselectform")); |
多表格示例
前端页面
<div class="panel panel-default panel-intro"> <div class="panel-heading"> <div class="panel-lead"><em>多表格(Multitable)</em>用于展示在一个页面展示多个表格数据,并且每次切换时刷新</div> <ul class="nav nav-tabs"> <li class="active"><a href="#first" data-toggle="tab">表格1</a></li> <li><a href="#second" data-toggle="tab">表格2</a></li> </ul> </div> <div class="panel-body"> <div id="myTabContent" class="tab-content"> <div class="tab-pane fade active in" id="first"> <div id="toolbar1" class="toolbar"> {:build_toolbar('refresh')} </div> <table id="table1" class="table table-striped table-bordered table-hover" width="100%"> </table> </div> <div class="tab-pane fade" id="second"> <div id="toolbar2" class="toolbar"> {:build_toolbar('refresh')} </div> <table id="table2" class="table table-striped table-bordered table-hover" width="100%"> </table> </div> </div> </div> </div> |
对应js
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { var Controller = { index: function () { // 初始化表格参数配置 Table.api.init(); //绑定事件 // shown.bs.tab为Bootstrap中Tab组件定义的事件 // 该事件在标签页显示时触发,但是必须在某个标签页已经显示之后 $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { var panel = $($(this).attr("href")); //$('#first')或者$('#second') if (panel.size() > 0) { Controller.table[panel.attr("id")].call(this); $(this).on('click', function (e) { $($(this).attr("href")).find(".btn-refresh").trigger("click"); }); } //移除绑定的事件 $(this).unbind('shown.bs.tab'); }); //必须默认触发shown.bs.tab事件 $('ul.nav-tabs li.active a[data-toggle="tab"]').trigger("shown.bs.tab"); }, table: { first: function () { // 表格1 var table1 = $("#table1"); table1.bootstrapTable({ url: 'example/multitable/table1', toolbar: '#toolbar1', sortName: 'id', search: false, columns: [ [ {field: 'state', checkbox: true, }, {field: 'id', title: 'ID'}, {field: 'url', title: __('Url'), formatter: Table.api.formatter.url}, {field: 'imagewidth', title: __('Imagewidth')}, {field: 'imageheight', title: __('Imageheight')}, {field: 'mimetype', title: __('Mimetype')}, {field: 'operate', title: __('Operate'), table: table1, events: Table.api.events.operate, formatter: Table.api.formatter.operate} ] ] }); // 为表格1绑定事件 Table.api.bindevent(table1); }, second: function () { // 表格2 var table2 = $("#table2"); table2.bootstrapTable({ url: 'example/multitable/table2', extend: { index_url: '', add_url: '', edit_url: '', del_url: '', multi_url: '', table: '', }, toolbar: '#toolbar2', sortName: 'id', search: false, columns: [ [ {field: 'id', title: 'ID'}, {field: 'title', title: __('Title')}, {field: 'url', title: __('Url'), align: 'left', formatter: Table.api.formatter.url}, {field: 'ip', title: __('ip')}, {field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, ] ] }); // 为表格2绑定事件 Table.api.bindevent(table2); } }, add: function () { Controller.api.bindevent(); }, edit: function () { Controller.api.bindevent(); }, api: { bindevent: function () { Form.api.bindevent($("form[role=form]")); }, } }; return Controller; }); |
动态调整弹窗高度,在初始化表格后,添加如下代码即可:
// 为表格绑定事件 Table.api.bindevent(table); table.on('post-body.bs.table', function (e, settings, json, xhr) { $(".btn-editone").data("area", ["600px", "250px"]); }); |
后台添加或者编辑图片上传
<div class="form-group"> <label class="control-label col-xs-12 col-sm-2">{:__('Payment_code')}:</label> <div class="col-xs-12 col-sm-8"> <div class="input-group"> <input id="c-image" data-rule="required" class="form-control" size="50" name="row[payment_code]" type="text" value="{$row.payment_code}"> <div class="input-group-addon no-border no-padding"> <span><button type="button" id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span> <span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span> </div> <span class="msg-box n-right" for="c-image"></span> </div> <ul class="row list-inline plupload-preview" id="p-image"></ul> </div> </div> |
编辑或者添加页状态
①模型赋值
public function statusList(){ return ['0' => __('未审核'),'1' => __('审核成功')]; } |
②控制器赋值
$this->assign('statusList',$this->model->statusList()); |
③html页面
<div class="form-group"> <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label> <div class="col-xs-12 col-sm-8"> <div class="radio"> {foreach name="statusList" item="vo"} <label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="$row.status"}checked{/in} /> {$vo}</label> {/foreach} </div> </div> </div> |
列表使用,出现获取不到ids情况 /index/multi/ids/undefined,修改require-table.js文件
toggle: function (value, row, index) { var options = $(table).bootstrapTable('getOptions'); // 1.新增这行 var color = typeof this.color !== 'undefined' ? this.color : 'success'; var yes = typeof this.yes !== 'undefined' ? this.yes : 1; var no = typeof this.no !== 'undefined' ? this.no : 0; var url = typeof this.url !== 'undefined' ? this.url : ''; var disable = false; if (typeof this.disable !== "undefined") { disable = typeof this.disable === "function" ? this.disable.call(this, value, row, index) : this.disable; } return "<a href='javascript:;' data-toggle='tooltip' title='" + __('Click to toggle') + "' class='btn-change " + (disable ? 'btn disabled' : '') + "' data-id='" + row[options.pk] + "' " + (url ? "data-url='" + url + "'" : "") + " data-params='" + this.field + "=" + (value == yes ? no : yes) + "'><i class='fa fa-toggle-on " + (value == yes ? 'text-' + color : 'fa-flip-horizontal text-gray') + " fa-2x'></i></a>"; // 2.row.id替换为row[options.pk] }, |
未更新任何行,如下,修改控制器文件
{"code":0,"msg":"未更新任何行","data":"","url":"","wait":3} |
protected $multiFields = 'state'; |
致命错误: Call to a member function visible() on null
//当前是否为关联查询 $this->relationSearch = true; $list = $this->model ->with(array('coursecategory')) ->where($where) ->order($sort, $order) ->limit($offset, $limit) ->select(); foreach ($list as $row) { $row->visible(['course_id','check_id','course_name','course_money','courate_image','courate_suo_image','course_amount','course_brief','createtime','updatetime','chu_state','state']); $row->visible(['coursecategory']); $row->getRelation('coursecategory')->visible(['category_name']); } 模型中设置 public function coursecategory() { return $this->belongsTo('CourseCategory', 'category_id', 'id', [], 'LEFT')->setEagerlyType(0); } |
1.首先检查表名字是否存在
2.检查字段是否存在
3.with关联,模型中定义的方法必须小写或者下划线
使用thinkphp的软删除功能
1.模型中引入 use traits\model\SoftDelete; 类
2.模型类中使用
use SoftDelete;
protected $deleteTime = ‘delete_time’;
3.创建软删除字段
上传文件限制设置
①设置文件/application/extra/upload.php
* 可上传的文件类型 */ 'mimetype' => 'jpg,png,bmp,jpeg,gif,zip,rar,xls,xlsx,doc,docx,pdf' |
②设置页面中控件
<span><button type="button" id="plupload-file" class="btn btn-danger plupload" data-input-id="c-file" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,application/pdf" data-multiple="false" data-preview-id="p-file"><i class="fa fa-upload"></i> 上传</button></span> |
③自定义控件的回调方法
jxupload:function(){ // 绩效文件上传 Controller.api.bindevent(); $('#plupload-file').data('upload-success',function(data){ console.log(data) console.log(data.file_name) $('#file_before_name').val(data.file_name) }) }, |
行为
fastadmin\application\index\controller\User.php
class User extends Frontend { public function _initialize() { parent::_initialize(); $auth = $this->auth; if (!Config::get('fastadmin.usercenter')) { $this->error(__('User center already closed')); } $ucenter = get_addon_info('ucenter'); if ($ucenter && $ucenter['state']) { include ADDON_PATH . 'ucenter' . DS . 'uc.php'; } //监听注册登录注销的事件 Hook::add('user_login_successed', function ($user) use ($auth) { $expire = input('post.keeplogin') ? 30 * 86400 : 0; Cookie::set('uid', $user->id, $expire); Cookie::set('token', $auth->getToken(), $expire); }); Hook::add('user_register_successed', function ($user) use ($auth) { Cookie::set('uid', $user->id); Cookie::set('token', $auth->getToken()); }); Hook::add('user_delete_successed', function ($user) use ($auth) { Cookie::delete('uid'); Cookie::delete('token'); }); Hook::add('user_logout_successed', function ($user) use ($auth) { Cookie::delete('uid'); Cookie::delete('token'); }); } |
fastadmin\application\common\library\Auth.php
/** * 注册用户 * * @param string $username 用户名 * @param string $password 密码 * @param string $email 邮箱 * @param string $mobile 手机号 * @param array $extend 扩展参数 * @return boolean */ public function register($username, $password, $email = '', $mobile = '', $extend = []) { // 检测用户名或邮箱、手机号是否存在 if (User::getByUsername($username)) { $this->setError('Username already exist'); return FALSE; } if ($email && User::getByEmail($email)) { $this->setError('Email already exist'); return FALSE; } if ($mobile && User::getByMobile($mobile)) { $this->setError('Mobile already exist'); return FALSE; } $ip = request()->ip(); $time = time(); $data = [ 'username' => $username, 'password' => $password, 'email' => $email, 'mobile' => $mobile, 'level' => 1, 'score' => 0, 'avatar' => '', ]; $params = array_merge($data, [ 'nickname' => $username, 'salt' => Random::alnum(), 'jointime' => $time, 'joinip' => $ip, 'logintime' => $time, 'loginip' => $ip, 'prevtime' => $time, 'status' => 'normal' ]); $params['password'] = $this->getEncryptPassword($password, $params['salt']); $params = array_merge($params, $extend); ////////////////同步到Ucenter//////////////// if (defined('UC_STATUS') && UC_STATUS) { $uc = new \addons\ucenter\library\client\Client(); $user_id = $uc->uc_user_register($username, $password, $email); // 如果小于0则说明发生错误 if ($user_id <= 0) { $this->setError($user_id > -4 ? 'Username is incorrect' : 'Email is incorrect'); return FALSE; } else { $params['id'] = $user_id; } } //账号注册时需要开启事务,避免出现垃圾数据 Db::startTrans(); try { $user = User::create($params); Db::commit(); // 此时的Model中只包含部分数据 $this->_user = User::get($user->id); //设置Token $this->_token = Random::uuid(); Token::set($this->_token, $user->id, $this->keeptime); //注册成功的事件 Hook::listen("user_register_successed", $this->_user); return TRUE; } catch (Exception $e) { $this->setError($e->getMessage()); Db::rollback(); return FALSE; } } |
重新刷新列表
table.bootstrapTable('refresh'); |
js文件接收控制器参数
控制器文件
$this->assignconfig('card_id',$cardId); |
js文件
add_url: 'card_attr/add?card_id='+Config.card_id |
固定列table.bootstrapTable配置如下
//启用固定列 fixedColumns: true, //固定右侧列数 fixedRightNumber: 1, //固定左侧列数 fixedNumber:3, |
bower安装layui
npm install -g bower bower help bower install layui |
\assets\js\require-backend.js配置
paths配置
'layui': '../libs/layui/dist/layui', // shim依赖配置 'layui': { deps: ['css!../libs/layui/dist/css/layui.css'], exports: "layui" } |
使用
define(['jquery', 'bootstrap', 'backend', 'table', 'form','layui'], function ($, undefined, Backend, Table, Form,layui){}) 生产模式下打包静态文件 //一键压缩打包后台的JS和CSS php think min -m backend -r all |
https://doc.fastadmin.net/doc/162.html
使用腾讯地图
addon.js引入
define([], function () { require.config({ paths: { 'async': '../addons/example/js/async', 'BMap': ['//api.map.baidu.com/api?v=2.0&ak=mXijumfojHnAaN2VxpBGoqHM'], 'TMap': ['//map.qq.com/api/gljs?v=1.exp&key=YUBBZ-752KR-2M3WC-W52Q2-L5FPS-CFB6D'], }, shim: { 'BMap': { deps: ['jquery'], exports: 'BMap' }, 'BMap': { exports: 'TMap' } } }); |
对应js使用
require(['TMap'], function () { //定义地图中心点坐标 var center = new TMap.LatLng(35.42492, 116.572507) }); |