jqhph / dcat-admin Goto Github PK
View Code? Open in Web Editor NEW🔥 基于 Laravel 的后台系统构建工具 (Laravel Admin),使用很少的代码快速构建一个功能完善的高颜值后台系统,内置丰富的后台常用组件,开箱即用,让开发者告别冗杂的HTML代码
Home Page: http://www.dcatadmin.com
License: MIT License
🔥 基于 Laravel 的后台系统构建工具 (Laravel Admin),使用很少的代码快速构建一个功能完善的高颜值后台系统,内置丰富的后台常用组件,开箱即用,让开发者告别冗杂的HTML代码
Home Page: http://www.dcatadmin.com
License: MIT License
因為editor的渲染會先remove掉,所以如果一個表單有多個editor的話就只會顯示最後一個editor
Dcat\Admin\Form\Field\Editor
public function render()
{
$this->script = <<<JS
tinymce.remove(); // here
tinymce.init({$this->formatOptions()})
JS;
return parent::render();
}
使用$form->hasMany时保存的时候出现Undefined index: remove
Form\NestedForm 235 if ($record[static::REMOVE_FLAG_NAME] == 1)
Migration file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAdminConfigsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('admin_configs', function(Blueprint $table)
{
$table->increments('id');
$table->string('name', 255)->nullable();
$table->string('config_key', 255)->nullable();
$table->text('config_value');
$table->string('type', 255)->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('admin_configs');
}
}
AdminConfigController
<?php
namespace App\Admin\Controllers;
use App\Models\AdminConfig;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Show;
use Dcat\Admin\Controllers\AdminController;
use Illuminate\Support\Carbon;
class AdminConfigController extends AdminController
{
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Grid::make(new AdminConfig(), function (Grid $grid) {
$grid->id->sortable()->responsive();
$grid->name->responsive();
$grid->config_key->responsive();
$grid->type->display(function ($type) {
switch ($type) {
case 'string':
return '字符串';
case 'image':
return '图片';
case 'switch':
return '开关';
case 'text':
return '富文本';
case 'readonly':
return '唯读配置';
}
})->responsive();
$grid->config_value->display(function () {
if ($this->type == 'image') {
return sprintf('<img src="%s" style="max-width:200px;max-height:200px;" class="img img-thumbnail">', $this->config_value);
// return $this->config_value->image('http://xxxxx');
} else {
return $this->config_value;
}
})->responsive();
$grid->created_at->display(function ($created_at) {
return Carbon::parse($created_at)->format('Y-m-d');
})->responsive();
$grid->updated_at->display(function ($updated_at) {
return Carbon::parse($updated_at)->format('Y-m-d');
})->sortable()->responsive();
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('id');
})->responsive();
$grid->withBorder();
});
}
/**
* Make a show builder.
*
* @param mixed $id
*
* @return Show
*/
protected function detail($id)
{
return Show::make($id, new AdminConfig(), function (Show $show) {
$show->id;
$show->name;
$show->config_key;
$show->type;
$show->config_value;
$show->created_at;
$show->updated_at;
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Form::make(new AdminConfig(), function (Form $form) {
$form->display('id');
$form->text('name');
$form->text('config_key');
$form->select('type')->options(['string' => '字符串',
'image' => '图片',
'switch' => '开关',
'text' => '富文本',
'readonly' => '唯读配置',
]);
$form->text('config_value');
// if ($request->get('type') == 'image') {
// $form->image('config_value');
// } else {
// $form->text('config_value');
// }
$form->display('created_at');
$form->display('updated_at');
});
}
}
$grid->config_value->display(function () {
if ($this->type == 'image') {
return sprintf('<img src="%s" style="max-width:200px;max-height:200px;" class="img img-thumbnail">', $this->config_value);
// return $this->config_value->image('http://xxxxx');
} else {
return $this->config_value;
}
})->responsive();
能在 display()
中继据操作 $grid
达到类似注解的 $this->config_value->image()
方式吗?
$grid->config_value->image()
方法若不带域名参数就无法显示图片是正确的吗?
在 function form()
中, 能否支持动态改变表单内容, 例如将下拉选单的 type
切换为 image
后, $form->text('config_value');
动态改变为 $form->image('config_value');
, 类似上述代码注解想表达的字段形态变动, 或是联动开启/隐藏另一个字段. (问题应该跟 #55 是关联的)
if ($request->get('type') == 'image') {
$form->image('config_value');
} else {
$form->text('config_value');
}
再麻凡大神拨冗解惑, 或是给个范本参考做法, 谢谢
请问如何实现表单布局?现在表单内容有点多,想实现左右两列布局
里面的get
方法不知道如何使用, 我如下使用会报错
public function get(Grid\Model $model)
{
return [
['id' => 1],
];
}
// productController.php
use App\Admin\Repositories\Products;
protected function grid()
{
return Grid::make(new Products(), function (Grid $grid) {
$grid->id->sortable();
}
}
错误
Argument 2 passed to Illuminate\Auth\SessionGuard::__construct() must implement interface Illuminate\Contracts\Auth\UserProvider, null given,
为了在表单中实现更灵活的操作,表单中需要实现在对某个组件点击时(比如checkbox),判断其值,然后显示另一个表单组件(比如图片上传)的功能。希望作者能实现此功能或者提供自定义JS的用例,十分感谢!
建议你把这个前段改成用vue的,这样就更完美了,我查了一下,有vue版本的这个admin 模板。
目前参照文档使用范例中 len 的自订义前端验证 JS报错会出现
http://www.dcatadmin.com/docs/master/model-form-validation.html
TypeError: Dcat.extendValidator is not a function
at HTMLDocument. (create:787)
at e (eval at (vendors.min.js:2), :1:29453)
at t (eval at (vendors.min.js:2), :1:29755)
原码无更动 请问是什麽原因呢?
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See.....
你好:我想问一下:上传图片的时候我想把图片地址先保存到一张专门放图片的数据表,然后再把得到的 img_id 保存到其他数据表。这种操作在 您这个框架里 怎么实现呀
CREATE TABLE `common_files` (
`file_id` int(11) NOT NULL AUTO_INCREMENT,
`files_path` varchar(255) NOT NULL DEFAULT '' COMMENT '附件地址(相对地址)',
`filesize` int(11) NOT NULL DEFAULT '0' COMMENT '文件大小(单位字节)',
`suffix` varchar(20) NOT NULL DEFAULT '' COMMENT '文件格式后缀(如:.txt)',
`realname` varchar(50) NOT NULL DEFAULT '' COMMENT '文件真实名字',
`ctime` int(10) NOT NULL DEFAULT '0' COMMENT '上传时间',
PRIMARY KEY (`file_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=371259 DEFAULT CHARSET=utf8 COMMENT='公共附件表';
感谢开源这么牛x的扩展包,使用过程中遇到一个问题,\Dcat\Admin\Admin::guard()->loginUsingId()
和\Dcat\Admin\Admin::guard()->onceUsingId()
等方法无效,是不是我姿势不对?附代码:
use Dcat\Admin\Admin;
Route::get('/test', function () {
// Admin::guard()->loginUsingId(1);
Admin::guard()->onceUsingId(1);
return redirect('/admin');
});
求解答,非常感谢!
Ɖ�机号码
1_1 ____ ____
Ǝ�荐人
0
Ǧ�分
0
VIP到期时间
输入 VIP到期时间
Ɲ�源
新增的时候,由代码工具生成的中文字是乱码
在编辑模式下 table 组件下 select下拉框 数据来源为json格式 但是 select不能联动成功 只能联动json下第一个元素的选项:
对应json:
[{"sort": "10", "classify_id": "28"}, {"sort": "11", "classify_id": "27"}]
classify_id:28关联实体类name为:卖货宣传
classify_id:27关联实体类name为:引流专用
如题
在线预览的DEMO
全选的勾选不能自动跟随下面的勾选进行显示
i am unable to access the model object of the Grid with RowAction
class Duplicate extends RowAction
{
public $title;
public function __construct()
{
parent::__construct();
$this->title = trans('admin.duplicate');
}
public function handle(Request $request)
{
dd($request->all());
when inspected i only get
array:3 [
"_token" => "eIsFYmN8qXBEUSnhmsmN2MwbWeD9Bwvw5pzmls5z"
"_action" => "App_Admin_Actions_Shipment_Duplicate"
"_key" => "63"
]
i suggest _model
to be included to the request
array:3 [
"_token" => "eIsFYmN8qXBEUSnhmsmN2MwbWeD9Bwvw5pzmls5z"
"_action" => "App_Admin_Actions_Shipment_Duplicate"
"_key" => "63",
"_model" => "App_Models_Shipment"
]
根据用户输入的内容 调用接口 填充 其它组件 目前好像只是看到下拉框有这个
上传图片组件 换成接口上传 图片可以正常传上去。但是提交表单后又会走一遍本地的上传。是我用错了方法还是怎么回事
还有saving里 写 redirect 如果有上传图片的组件 就必须要先把图片传上去后才可以
// upload/image 是接口 已经可以正常拿到图片了
$form->multipleImage('covers', '图片')->url('upload/image');
我个人有一个想法想把Laravel-admin 改成用vue,然后再加上你这个界面风格,拿你这个来学习了。
The Menu Scroll bar does not display on mouseover but will starting working properly when i use mouse scroll bar
The Menu Scroll bar should display immediately on mouseover when the page have fully loaded
i tried using $this->destination()
to call a method from the grid but it return array of all attributes from the model .
$grid->column('destinationdd', trans('admin.destination'))->display(function () {
return $this->destination(); // a method in a model
});
a Model method
```
public function destination()
{
return optional(Country::find($this->d_country_id))->name . ' | ' . $this->d_state;
}
### Steps To Reproduce:
在使用scaffold 创建migrations 时,报错:
ArgumentCountError:` Too few arguments to function Illuminate\Database\Migrations\MigrationCreator::__construct(), 1 passed in E:\php\gift-branch\gift_branch_backstage\vendor\dcat\laravel-admin\src\Controllers\ScaffoldController.php on line 119 and exactly 2 expected in file E:\php\gift-branch\gift_branch_backstage\vendor\laravel\framework\src\Illuminate\Database\Migrations\MigrationCreator.php on line 40
传参数量不一致
在使用SortableTrait时,如果列表倒序
$grid->model()->orderBy('order', 'desc');
$grid->order->orderable();
此时点击上移按钮,会执行eloquent-sortable
的moveOrderUp
方法,但此时由于列表本身倒序,所以在逻辑上本应该对应moveOrderDown
方法。
可能需要对 Displayers\Orderable
的 display
方法中的html代码部分 ,根据当前model的排序,设置对应的data-direction
值
如:
<a href="javascript:void(0)" class=" font-14 {$this->grid->getRowName()}-orderable" data-id="{$this->getKey()}" data-direction="{$this->grid->model()->getQueries()
->where('method', '=', 'orderBy')
->where('arguments.0', 'order')
->where('arguments.1', 'desc')
->count()}">
</a>
或增加 data-order
等数据,传递到 Dcat\Admin\Form
的 handleOrderable
方法后再判断执行 moveOrderUp
还是 moveOrderDown
方法:
protected function handleOrderable(array $input = [])
{
if (array_key_exists('_orderable', $input)) {
$updated = $input['_orderable'] == 1 && $input['_order'] == 'asc' // <-------------
? $this->repository->moveOrderUp()
: $this->repository->moveOrderDown();
return $updated
? $this->ajaxResponse(__('admin.update_succeeded'))
: $this->error(__('admin.nothing_updated'));
}
}
当然,我没有实际尝试处理此问题,又或者只是我不会用而已。希望能先给个反馈,如果确实是问题,我会进一步看一下,也希望能尽快完善;如果是我文档没有阅读充分,还请指出,谢谢!
card 当数据为0时不显示
$row->column(4, Card::make('xx', 0));
即可
会一直维护下去吗,swoft-admin不继续了?挺好的项目
vendor/dcat/laravel-admin/src/Widgets/Form.php
引用的这个Trait Dcat\EasyExcel\Support\Traits\Macroable不存在呢,是还没更新吗
下拉选框联动选择后没有接口请求
查看了源码
将请求方式从
一个主表,一个从表,主表里存附件id,从表里存附件地址、附件大小,编辑主表时,怎么编辑这个附件啊?
I have an app with laravel-admin https://laravel-admin.org/docs/ can I update to that?
Congratulations, the app is awesome!
exception: "ErrorException"
file: "/Users/ray/shoes-manage/vendor/dcat/laravel-admin/src/Form/Field/Table.php"
line: 73
message: "Undefined index: _remove_"
$form->table('item', function (Form\NestedForm $table) {
$table->select('item_id', '所属分类')->options(function ($id) {
$item = Item::find($id);
if ($item) {
return [$item->id => $item->name];
}
})->ajax('api/item')->required();
$table->decimal('price', '价格')->required();
});
public function item(): BelongsToMany
{
$pivotTable = 'order_item'; // 中间表
$relatedModel = Item::class; // 关联模型类名
return $this->belongsToMany($relatedModel, $pivotTable, 'order_id', 'item_id');
}
public function order(): BelongsToMany
{
$pivotTable = 'order_item'; // 中间表
$relatedModel = Order::class; // 关联模型类名
return $this->belongsToMany($relatedModel, $pivotTable, 'item_id', 'order_id');
}
Do you have english version of docs? http://www.dcatadmin.com/docs/master/introduction.html
请问如何实现数据表格回收站功能呢?
相关页面: http://www.dcatadmin.com/docs/master/model-grid.html
多了一个冒号
php artisan admin::ide-helper
php artisan admin:ide-helper
run : php artisan admin:publish
outcome: There are no commands defined in the "admin" namespace.
使用多个modal弹出框的时候,第一个modal返回的内容会覆盖下面所有modal的内容
代码:
$grid->classify('classify')->display('海报分类')->modal('分类详情', function () {
$json = $this->classify;
$str = '';
foreach ($json as $item) {
$c = PlacardClassifyModel::find($item['classify_id']);
if ($c) {
$str .= "<p>" . $c->title . "</p>";
}
}
return $str;
});
$grid->home_classify->display('首页分类')->modal('分类详情', function () {
$json = $this->home_classify;
$str = '';
foreach ($json as $item) {
$c = PlacardHomeClassifyModel::find($item['classify_id']);
if ($c) {
$str .= "<p>" . $c->title . "</p>";
}
}
return $str;
});
我用$form->checkbox('t_id','推荐位')->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);
点击保存时,提示"Array to string conversion",求解决方法
How to customize the views?
seem not to work for dcat-admin
app('view')->prependNamespace('admin', resource_path('views/admin'));
按照文档里表单一对多编写代码可以显示关联模型字段内容,但是无法更新关联模型字段值
能否提供 direction 配置以支持 rtl 语言国际化
看文件似乎hasMany暂不支持图片和文件上传表单
目前有需求是否有其他方法可以做到一对多可以上传?
我一个类继承自chat 如果重写里面的handle方法就会报错,注释掉handle方法就好了
报错信息如下:
"message": "Array to string conversion",
"exception": "ErrorException",
"file": "cartAdmin/vendor/dcat/laravel-admin/src/Widgets/ApexCharts/Chart.php",
"line": 337,
"trace": [
{
"file": "cartAdmin/vendor/dcat/laravel-admin/src/Widgets/ApexCharts/Chart.php",
"line": 337,
"function": "handleError",
"class": "Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
"type": "->"
},
代码如下
<?php
namespace Dcat\Admin\Widgets\ApexCharts;
use Dcat\Admin\Support\Helper;
use Dcat\Admin\Support\JavaScript;
use Dcat\Admin\Traits\InteractsWithApi;
use Dcat\Admin\Widgets\Widget;
use Illuminate\Support\Str;
/**
* Class Chart.
*
*
* @see https://apexcharts.com/
*/
class Chart extends Widget
{
use InteractsWithApi;
public static $js = [
'@apex-charts',
];
protected $containerSelector;
protected $options = [];
protected $built = false;
protected $scripts = [
'extend' => 'return options',
];
public function __construct($containerSelector = null, $options = [])
{
if ($containerSelector && ! is_string($containerSelector)) {
$options = $containerSelector;
$containerSelector = null;
}
$this->selector($containerSelector);
$this->options($options);
}
/**
* 设置或获取图表容器选择器.
*
* @param string|null $selector
*
* @return $this|string|null
*/
public function selector(?string $selector = null)
{
if ($selector === null) {
return $this->containerSelector;
}
$this->containerSelector = $selector;
if ($selector && ! $this->built) {
$this->autoRender();
}
return $this;
}
/**
* @param string|array $title
*
* @return $this
*/
public function title($title)
{
if (is_string($title)) {
$options = ['text' => $title];
} else {
$options = Helper::array($title);
}
$this->options['title'] = $options;
return $this;
}
/**
* @param array $series
*
* @return $this
*/
public function series($series)
{
$this->options['series'] = Helper::array($series);
return $this;
}
/**
* @param array $value
*
* @return $this
*/
public function labels($value)
{
$this->options['labels'] = Helper::array($value);
return $this;
}
/**
* @param string|array $colors
*
* @return $this
*/
public function colors($colors)
{
$this->options['colors'] = Helper::array($colors);
return $this;
}
/**
* @param array $value
*
* @return $this
*/
public function stroke($value)
{
$this->options['stroke'] = Helper::array($value);
return $this;
}
/**
* @param array $value
*
* @return $this
*/
public function xaxis($value)
{
$this->options['xaxis'] = Helper::array($value);
return $this;
}
/**
* @param array $value
*
* @return $this
*/
public function tooltip($value)
{
$this->options['tooltip'] = Helper::array($value);
return $this;
}
/**
* @param array $value
*
* @return $this
*/
public function yaxis($value)
{
$this->options['yaxis'] = Helper::array($value);
return $this;
}
/**
* @param array $value
*
* @return $this
*/
public function fill($value)
{
$this->options['fill'] = Helper::array($value);
return $this;
}
/**
* @param array $value
*
* @return $this
*/
public function chart($value)
{
$this->options['chart'] = Helper::array($value);
return $this;
}
/**
* @param array|bool $value
*
* @return $this
*/
public function dataLabels($value)
{
if (is_bool($value)) {
$value = ['enabled' => $value];
}
$this->options['dataLabels'] = Helper::array($value);
return $this;
}
/**
* @param string|\Closure $script
*
* @return $this
*/
public function extendOptions($script)
{
$this->scripts['extend'] = value($script);
return $this;
}
/**
* @return string
*/
protected function buildDefaultScript()
{
$options = JavaScript::format($this->options);
return <<<JS
(function () {
var options = {$options};
var chart = new ApexCharts(
$("{$this->containerSelector}")[0],
options
);
chart.render();
})();
JS;
}
/**
* @return string
*/
public function script()
{
if (! $this->allowBuildRequest()) {
return $this->buildDefaultScript();
}
$this->fetched(
<<<JS
if (! response.status) {
return Dcat.error(response.message || 'Server internal error.');
}
var chartBox = $(response.selector || '{$this->containerSelector}');
if (chartBox.length) {
chartBox.html('');
if (typeof response.options === 'string') {
eval(response.options);
}
setTimeout(function () {
new ApexCharts(chartBox[0], response.options).render();
}, 50);
}
JS
);
return $this->buildRequestScript();
}
/**
* @return string
*/
public function render()
{
if ($this->built) {
return;
}
$this->built = true;
$hasSelector = $this->containerSelector ? true : false;
if (! $hasSelector) {
// 没有指定ID,需要自动生成
$id = $this->generateId();
$this->selector('#'.$id);
}
$this->script = $this->script();
$this->collectAssets();
if ($hasSelector) {
return;
}
// 没有指定容器选择器,则需自动生成
$this->setHtmlAttribute([
'id' => $id,
]);
return <<<HTML
<div {$this->formatHtmlAttributes()}></div>
HTML;
}
/**
* 返回API请求结果.
*
* @return array
*/
public function valueResult()
{
return [
'status' => 1,
'selector' => $this->containerSelector,
'options' => $this->formatScriptOptions(),
];
}
/**
* 配置选项转化为JS可执行代码.
*
* @return string
*/
protected function formatScriptOptions()
{
$code = JavaScript::format($this->options);
return "response.options = {$code}";
}
/**
* 生成唯一ID.
*
* @return string
*/
protected function generateId()
{
return 'apex-chart-'.Str::random(8);
}
}
#使用该类
$mychart = YqqChart::make(null,$options)
->fetching('$("#my-box").loading()') // 设置loading效果
->fetched('$("#my-box").loading(false)') // 移除loading效果
->click('.switch-bar');
$box = Box::make('详情图表', $mychart)
->id('my-box') // 设置盒子的ID
->tool($dropdown); // 设置下拉菜单按钮
$row->column(12, $box);
执行php artisan admin:publish 提示there are no commands defined in the "admin" namespace.### Steps To Reproduce:
1.表单一对多创建保存报错,提示Undefined index: remove。注释掉此行代码是创建保存成功了,但不过不知道为什么要unset,注释掉后很有可能会影响其他代码。
protected function prepareToSave($input)
{
$form = $this->buildNestedForm($this->column, $this->builder);
return array_values(
collect($form->setOriginal($this->original, $this->getKeyName())->prepare($input))
->reject(function ($item) {
return $item[NestedForm::REMOVE_FLAG_NAME] == 1;
})
->map(function ($item) {
unset($item[NestedForm::REMOVE_FLAG_NAME]);//注释掉
return $item;
})
->toArray()
);
}
2.表单一对多创建成功后进入编辑模式,看不到新增对应“多”的模型数据,并没有添加到field里面,只有“一”的模型数据,setFieldValue没有看到关联模型的信息。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.