slowlyo / owl-admin Goto Github PK
View Code? Open in Web Editor NEW🎈 Owl Admin : 基于 laravel 和 amis 开发的后台框架, 友好的组件使用体验, 可轻松实现复杂页面, 内置代码生成器, 让开发者快速搭建后台管理系统
Home Page: https://owladmin.com
License: MIT License
🎈 Owl Admin : 基于 laravel 和 amis 开发的后台框架, 友好的组件使用体验, 可轻松实现复杂页面, 内置代码生成器, 让开发者快速搭建后台管理系统
Home Page: https://owladmin.com
License: MIT License
DiffEditor 组件比对失效(间接性)
最新
eg: Win + Docker
Mac + Sail
Linux + BT
{
"type": "page",
"body": [
{
"type": "form",
"body": [
{
"type": "diff-editor",
"name": "diff",
"label": "Diff-Editor",
"diffValue": "hello world",
"value": "hello1",
"id": "u:9058a8bec5a1"
}
],
"id": "u:5b06ea607670",
"actions": [
{
"type": "button",
"label": "提交",
"primary": "1",
"id": "u:f9d85e498ba5"
}
],
"feat": "Insert"
}
],
"id": "u:09957bfc1464"
}
安装完 laravel-debugbar 后,页面无法正常显示debug bar
v3.1.0 其它版本也有问题
Mac + Php Server
composer require barryvdh/laravel-debugbar --dev
我有三个表,老师, 班级 ,和学生表。学生有一个所属班级字段。
班级表有一个字段是管理老师,其实也对应的当前登录系统的用户。
我希望在编辑学生的时候,所属班级那里,显示为一个下拉。
同时,下拉列表里面,只展示当前用户管理的班级列表。
这种关联的操作,我不知道具体该如何配置,希望能在b站上多出一些教学视频
感谢
你好,有个问题请教下,前端重新用react写的考量是什么?以前的vue中嵌套amis有限制还是?
owl admin示例中左树右表需要当前页面刷新
// 按照 amis 示例, 这里应该是设置完 submitOnChange 和 target:window 之后就可以了
// 但是不生效, 曲线救国使用 onEvent 结合路径跳转实现
amis()
->TreeControl('tree')
->submitOnChange()
->options($this->service->tree())
->showIcon(false)
->onEvent([
// 当选中项发生变化时, 触发事件
'change' => [
'actions' => [
// 跳转到指定路径, 并且将选中项的值作为参数传递
[
'actionType' => 'url',
'args' => [
'url' => '/dev_example/left_tree_right_table?tree=${tree}',
],
],
],
],
])
),
其他做法,使用 change刷新另外一个表格组件,无需跳转 刷新组件请求
amis()->TreeControl('category_code')->className('maxWidthProcure')->initiallyOpen()->options($tree)->showIcon(false)
->onEvent([
'change' => [
'actions' => [
[
'actionType' => 'reload',
'componentId' => 'reload_service',
'data' => [
'categories_code' => '${category_code}'
]
]
],
],
])
因为我没办法实现 自定义新的富文本组件
想接入 aieditor:https://gitee.com/aieditor-team/aieditor
提供开箱即用的接入方案
但找不到: ERROR: View [mails.submit] not found. ,必须放在laravel 的resources/views 那个目录下吗?
这个怎么解决?
可以的话,尽可能提供截图或视频来补充描述你的问题...
你是在哪个版本的 owl-admin 上遇到的问题?
php8.3 & laravel: 10..
eg: Win + Docker
Mac + Sail
Linux + BT
请简单描述一下复现的操作步骤...
系统都是全新安装。
composer.json内容
"php": "^8.1",
"guzzlehttp/guzzle": "^7.2", 实际7.8.0
"laravel/framework": "^10.10", 实际10.31.0
"laravel/sanctum": "^3.3", 实际3.3.2
"laravel/tinker": "^2.8", 实际2.8.2
"maatwebsite/excel": "^3.1", 实际3.1.50
"slowlyo/owl-admin": "^3.0" 实际3.0.3
在vendor/slowlyo/owl-admin/src/Controllers/AdminUserController.php添加导出按钮
public function list(): Page
{
$crud = $this->baseCRUD()
->headerToolbar([
$this->createButton(true),
...$this->baseHeaderToolBar(),
$this->exportAction(), 此处添加
])
完成后,点击导出->全部
会直接打开一个网址而不是一个ajax请求: http://admin-api/_download_export?path=adminuser-20231113041732.xlsx
注:maatwebsite/excel 这个模块已经改名了。
最新版中在bootstrap中增加顶部菜不起作用
// file: App/Admin/bootstrap.php
DrawerAction() ->icon('fa fa-bell') ->className('mr-2 rounded-full') ->drawer( amis()->Drawer()->title('Message')->body('Message Content') ); // 一个按钮, 点击后跳转到百度 $urlBtn = amis() ->UrlAction() ->icon('fa fa-magnifying-glass') ->className('ml-2 rounded-full') ->url('https://www.baidu.com') ->blank(); // 追加到已有按钮前 \Slowlyo\OwlAdmin\Admin::prependNav($msgBtn); // 追加到已有按钮后 \Slowlyo\OwlAdmin\Admin::appendNav($urlBtn); // 或者你可以这么写, 效果是一样的 // \Slowlyo\OwlAdmin\Admin::prependNav($msgBtn)->appendNav($urlBtn);字段名存在 status 或 no , 与 amis
关键字冲突
#4055: form 表单 initApi,服务端返回的 data 中包含 no、status 字段时,客户端处理异常
属性修改器
列太多可以让重要的几列固定,可以配置固定在左侧还是右侧
rowActions列也能设置固定
升级到3.2.9,扩展多语言中AdminMenu并没有更新
https://github.com/slowlyo/owl-admin中的AdminMenu
升级到3.2.9后,本地的AdminMenu,并没有更新
你是在哪个版本的 owl-admin 上遇到的问题?
php8.3 & laravel: 10..
eg: Win + Docker
Mac + Sail
Linux + BT
请简单描述一下复现的操作步骤...
数据域污染
暂无解决方案
使用 status 组件时, 如果需要自定义 map / labelMap , 请用 mapping / tpl 代替
用的action download 但是按照amis说明配置了。接口返回看着应该是有word文档,但不知为何总是提示content-disposition不存在,在接口返回文件也配置了header,不起作用。大佬求指教
页面样式:
控制器下载生成表代码:
app/Admin/Controller/MatterController.php
amis()->Property()->title('办理事项')->className(['m-b','user-table'])->items([ amis()->TextControl('project_id', '办理事项')->content('${project_name}') ->span(3) ->static(), amis()->TextControl('apply_things', '申请事项')->content('${apply_things_str}') ->span(3) ->static(), amis()->TextControl('download', '其他')->content([ Button::make()->label('生成申请表') ->type('action') ->actionType('download') ->api([ 'method'=>'post', 'url'=>"/matters/word", 'data'=>[ 'matter_id'=>$id, ] ]), ]) ->span(3) ->static(), ])->labelStyle([ 'width'=>'120px' ]),
接口路由:
app/Admin/routes.php
`Route::group([
'domain' => config('admin.route.domain'),
'prefix' => config('admin.route.prefix'),
'middleware' => config('admin.route.middleware'),
], function (Router $router) {
$router->resource('dashboard', \App\Admin\Controllers\HomeController::class);
$router->resource('system/settings', \App\Admin\Controllers\SettingController::class);
$router->post("matter",[\App\Admin\Controllers\Api\MattersController::class,"store"]);
$router->post("matters/word",[\App\Admin\Controllers\Api\MattersController::class,"word"])
->withoutMiddleware([\App\Http\Middleware\AcceptHeader::class]);
});接口文件: app/Admin/Controllers/Api/MattersContrroller.php
class MattersController
{
public function word(Request $request)
{
$data = [
"data" => [],
"doNotDisplayToast" => 0,
"msg" => "",
"status" => 0
];
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$phpWord->setDefaultFontName('楷体');
$phpWord->setDefaultFontSize(12);
$headerStyle = ['size' => 20, 'name' => '宋体', 'bold' => true];
$phpWord->addParagraphStyle('pStyle',
['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]);
$headerSecondStyle = ['size' => 14];
$headerOtherStyle = ['size' => 12];
$section->addText('市残疾学生资助金申请表', $headerStyle, 'pStyle');
$section->addText('档案编号: 申请日期: 年 月 日', $headerSecondStyle);
$styleTable = ['borderSize' => 6, 'borderColor' => '999999'];
$cellStyleNormal = ['valign' => 'center'];
$cellHCentered = array('alignment' => Jc::CENTER); // 水平居中
$cellHEnd = array('alignment' => Jc::END); // 水平居中
$cellVCentered = array('valign' => 'center'); // 垂直居中
$phpWord->addTableStyle('Colspan Rowspan', $styleTable);
$table = $section->addTable('Colspan Rowspan');
$row = $table->addRow(800);
$row->addCell(600, $cellStyleNormal)->addTextRun($cellHCentered)->addText('姓名');
$row->addCell(1400, ['gridSpan' => 1, 'valign' => 'center'])->addTextRun($cellHCentered)->addText('');
$row->addCell(600, $cellStyleNormal)->addTextRun($cellHCentered)->addText('性别');
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('');
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('残疾人类别及等级');
$row->addCell(2000, ['gridSpan' => 3, 'valign' => 'center'])->addTextRun($cellHCentered)->addText('');
$row->addCell(2000, ['valign' => 'center', 'vMerge' => 'restart'])->addTextRun($cellHCentered)->addText('(一寸免冠照片)');
$row = $table->addRow(800);
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('家庭住址');
$row->addCell(1000, ['valign' => 'center', 'gridSpan' => 3])->addTextRun($cellHCentered)->addText('');
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('残疾人证号');
$row->addCell(2000, ['valign' => 'center', 'gridSpan' => 3])->addTextRun($cellHCentered)->addText('');
$row->addCell(2000, ['vMerge' => 'continue']);
$row = $table->addRow(800);
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('学校名称');
$row->addCell(1000, ['valign' => 'center', 'gridSpan' => 3])->addTextRun($cellHCentered)->addText('');
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('入学时间');
$row->addCell(2000, ['valign' => 'center', 'gridSpan' => 3])->addTextRun($cellHCentered)->addText('');
$row->addCell(2000, ['vMerge' => 'continue'])->addText('');
$row = $table->addRow(800);
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('学习专业');
$row->addCell(1000, ['valign' => 'center', 'gridSpan' => 3])->addTextRun($cellHCentered)->addText('');
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('学制');
$row->addCell(2000, ['valign' => 'center', 'gridSpan' => 3])->addTextRun($cellHCentered)->addText('');
$row->addCell(2000, ['vMerge' => 'continue'])->addText('');
$row = $table->addRow(800);
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('监护人姓名');
$row->addCell(1000, ['valign' => 'center', 'gridSpan' => 3])->addTextRun($cellHCentered)->addText('');
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('联系方式');
$row->addCell(1000, ['valign' => 'center', 'gridSpan' => 4])->addTextRun($cellHCentered)->addText('');
$row = $table->addRow(600);
$row->addCell(1000, ['valign' => 'center', 'vMerge' => 'restart'])
->addTextRun($cellHCentered)
->addText('义务教育');
//义务教育复选框
$ywjy_cell = $row->addCell(1000, ['valign' => 'center', 'vMerge' => 'restart']);
$ywjy_cell->addTextRun()
->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>小学</w:t></w:r>');
$ywjy_cell->addTextRun()
->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00FE"/><w:t>初中</w:t></w:r>');
$row->addCell(1000, ['valign' => 'center', 'vMerge' => 'restart'])
->addTextRun($cellHCentered)
->addText('中等教育');
//中等教育复选框
$zdjy_cell = $row->addCell(1000, ['valign' => 'center', 'vMerge' => 'restart']);
$zdjy_cell->addTextRun()
->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00FE"/><w:t>高中</w:t></w:r>');
$zdjy_cell->addTextRun()
->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>中职</w:t></w:r>');
$row->addCell(1000, ['valign' => 'center', 'vMerge' => 'restart'])->addTextRun($cellHCentered)->addText('高等教育');
//$row->addCell(1000, ['valign' => 'center', 'vMerge' => 'restart'])->addText('');
$row->addCell(1000, ['gridSpan' => 1,'valign' => 'center', 'vMerge' => 'restart'])
->addTextRun($cellHCentered)
->addText('统招');
//统招 复选框
$tz_cell = $row->addCell(2000, ['valign' => 'center', 'gridSpan' => 3]);
$tz_param_textrun = $tz_cell->addTextRun();
$tz_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>专科</w:t></w:r>');
$tz_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>本科</w:t></w:r>');
$tz_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>研究生</w:t></w:r>');
$tz_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>博士生</w:t></w:r>');
$row = $table->addRow(600);
$row->addCell(1000, ['vMerge' => 'continue']);
$row->addCell(1000, ['vMerge' => 'continue']);
$row->addCell(1000, ['vMerge' => 'continue']);
$row->addCell(1000, ['vMerge' => 'continue']);
$row->addCell(1000, ['vMerge' => 'continue']);
//$row->addCell(1000, ['vMerge' => 'continue']);
$row->addCell(1000, ['gridSpan' => 1,'valign' => 'center'])
->addTextRun($cellHCentered)
->addText('其他');
//其他 复选框
$qt_cell = $row->addCell(2000, ['valign' => 'center', 'gridSpan' => 3]);
$qt_param_textrun = $qt_cell->addTextRun();
$qt_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>专科</w:t></w:r>');
$qt_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>本科</w:t></w:r>');
$qt_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>研究生</w:t></w:r>');
$qt_param_textrun->addText('<w:r><w:rPr><w:rFonts w:hint="eastAsia"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:sym w:font="Wingdings" w:char="00A8"/><w:t>博士生</w:t></w:r>');
$row = $table->addRow(3000);
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('乡镇(街道)残联意见');
$xz_line_cell = $row->addCell(1000, ['gridSpan' => 8,'valign' => 'bottom']);
$xz_line_param = $xz_line_cell->addTextRun($cellHEnd);
$xz_line_param->addText('盖 章 ');
$xz_line_param->addTextBreak();
$xz_line_param->addText(' 年 月 日 ');
$xz_line_param->addText(' ');
//->addTextRun($textrun,['alignment' => Jc::END]);
$row = $table->addRow(3000);
$row->addCell(1000, $cellStyleNormal)->addTextRun($cellHCentered)->addText('县(市区)残联审核意见');
$x_line_cell = $row->addCell(1000, ['gridSpan' => 8,'valign' => 'bottom']);//->addText('盖章//r年 \\r月日');//->addText('经审核拟资助____元。');
$x_line_param = $x_line_cell->addTextRun($cellHEnd);
$x_line_param->addText('盖 章 ');
$x_line_param->addTextBreak();
$x_line_param->addText(' 年 月 日 ');
$x_line_cell->addTextRun($cellHCentered)->addText('经审核拟资助_______元');
$text = $section->addText('备注:本表一式两份,-份县(区)残联留存,一份乡镇 (街道)残联留存');
$objWriter = IOFactory::createWriter($phpWord, 'Word2007');
$files = $objWriter->save('helloWorld.docx');
$file_url = env('APP_URL')."helloWorld.docx";
$filename = "helloWorld.docx";
$data['data']['url'] = $file_url;
$true_path = storage_path('app/public/'."helloWorld.docx");
$res = response()->download($true_path, $filename, [
'Content-Disposition' => 'attachment; filename="' . $filename . '"',
'Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'Content-Length' => filesize($true_path),
"Access-Control-Expose-Headers"=> "Content-Disposition",
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type, Authorization,Content-Disposition ',
]);
return $res;
}
}`
amisMake()->Each()->name('children')->items([
amisMake()->Page()->body('${question_stem|truncate: 9999999999 }'),
amisMake()->Each()->name('children')->items([
amisMake()->Page()->body('${question_stem|truncate: 9999999999 }'),
])
]
使用行政区域地址递归子类,3层以上,名字相同,会出现重复渲染问题,主要是无法找到键值去循环数据
rt
你好。
`public function form($isEdit = false): Form
{
return $this->baseForm()->body([
amis()->TextControl('title', '名称'),
amis()->ImageControl('thumbnail', '图片')
->src([env('APP_URL'). Storage::url('${thumbnail}')]),
amis()->TextControl('order', '排序'),
amis()->SwitchControl('statu', '启用'),
]);
}`
这里使用了src修改图片默认显示url;
thumbnail数据库地址是:images/kxYbBLxSOxwn8O8v2lzYNj0BNaq4iANuzKo6M2tP.jpg
结果如上图,src的地址还是数据库的,没有变化;
同样的修改方式,list 和 detail 都没有问题;
求帮助
在实际使用中,尤其是开发API时,经常使用email、uuid、mobile,status等字段,目前AdminUser表中缺少这些字段,使用时要修改表结构,修改模型、修改控制器、修改Service等,而且创建用户时能够自动生成UUID。
利用Laravel Module生成的每个模块,每次都费力修改
如上:如果增加类似parent_id字段,实现同其它表关联更好
请简单描述其他你可以接受的效果...
本人修改过的实例:
迁移修改: app\database\migrations
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
if (!Schema::hasColumn('admin_users', 'uuid')) {
Schema::table('admin_users', function (Blueprint $table) {
$table->uuid()->index()->unique();
$table->integer('parent_id')->nullable();
$table->string('email')->index()->unique();
$table->string('mobile')->nullable();
$table->integer('status')->default(new Expression('0'));
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
if (!Schema::hasColumn('admin_users', 'uuid')) {
Schema::table('admin_users', function (Blueprint $table) {
$table->dropColumn('uuid');
$table->dropColumn('parent_id');
$table->dropColumn('email');
$table->dropColumn('mobile');
$table->dropColumn('status');
});
}
}
};
支持UUID:
<?php
namespace App\Support\Traits;
use Illuminate\Support\Str;
/**
* Class UuidScopeTrait.
*/
trait UuidScopeTrait
{
/**
* @param $query
* @param $uuid
* @return mixed
*/
public function scopeByUuid($query, $uuid): mixed
{
return $query->where('uuid', $uuid);
}
/**
* Boot the uuid scope trait for a model.
*
* @return void
*/
protected static function bootUuidScopeTrait(): void
{
static::creating(function ($model) {
if (empty($model->uuid)) {
$model->uuid = (string) Str::uuid();
}
});
}
}
模型修改:app\Models\AdminUser
<?php
namespace App\Models;
use App\Admin\Models\AdminOrg;
use App\Support\Traits\UuidScopeTrait;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AdminUser extends \Slowlyo\OwlAdmin\Models\AdminUser
{
use UuidScopeTrait;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'username',
'name',
'email',
'uuid',
'mobile',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
//与组织关联
public function org(): BelongsTo
{
return $this->belongsTo(AdminOrg::class, 'parent_id', 'id');
}
}
控制器修改:(完全个人习惯性编程)
<?php
namespace App\Http\Controllers;
use App\Services\AdminUserService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Slowlyo\OwlAdmin\Controllers\AdminController;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Renderers\Operation;
use Slowlyo\OwlAdmin\Renderers\Page;
use Slowlyo\OwlAdmin\Services\AdminRoleService;
/**
* @property AdminUserService $service
*/
class AdminUserController extends AdminController
{
protected string $serviceName = AdminUserService::class;
public function index(): JsonResponse|JsonResource
{
if ($this->actionOfGetData())
return $this->response()->success($this->service->list());
if ($this->actionOfExport()) {
return $this->export();
}
$page = amis()->Page()->body([
amis()->Flex()->items([$this->list()])
])->css([
'.cxd-Tree-itemArrowPlaceholder' => ['display' => 'none'],
'.cxd-Tree-itemLabel' => ['padding-left' => '0 !important'],
]);
return $this->response()->success($page);
}
public function list(): Page
{
$crud = $this->baseCRUD()
->filterTogglable()
->headerToolbar($this->getHeaderToolsBar())
->footerToolbar($this->getFooterToolbar())
->bulkActions($this->getBulkActions())
//->itemActions($this->getActions())
//->checkOnItemClick(true)
->columns($this->xList());
return $this->baseList($crud);
}
public function form($isEdit = false): Form
{
return $this->baseForm()
->autoFocus()
->body($this->xForm());
}
public function detail(): Form
{
return $this->baseDetail()->body($this->xView());
}
public function getHeaderToolsBar(): array
{
return [
$this->createButton(true, 'lg'),
amis()->SearchBox()
->name('keywords')
->clearable()
->clearAndSubmit()
->enhance()
->align('right')
->placeHolder($this->trans('options._search')),
amis('reload')->align('right'),
//amis('pagination')->align('right'),
'bulkActions',
];
}
public function getFooterToolbar(): array
{
return [
//加载更多
//‘load-more’
//统计
'statistics',
//跳转某页
'switch-per-page',
//分页
'pagination'
];
}
public function getActions(string $size = 'lg'): array
{
return [
//查看
amis()->DialogAction()
//->visibleOn('${action}')
->icon('fa fa-eye')
->level('primary')
->label(__('admin.show'))
->tooltip(__('admin.show'))
->dialog([
'title' => __('admin.show'),
'size' => $size,
'body' => [
amis()->Form()
->body($this->xView())
],
]),
//编辑
amis()->DialogAction()
//->visibleOn('${action}')
->icon('fa fa-pencil')
->level('primary')
->label(__('admin.edit'))
->dialog([
'title' => __('admin.edit'),
'size' => $size,
'body' => [
amis()->Form()
->api('/system/admin_users/${id}/edit?_action=getData')
->body($this->xForm())
],
]),
//删除
amis()->AjaxAction()
->visibleOn('${id != 1}')
->icon('fa fa-times')
->level('danger')
->label(__('admin.delete'))
//->tooltip(__('admin.delete'))
->confirmText(__('admin.confirm_delete'))
->api('delete:/system/admin_users/${id}')
];
}
public function getBulkActions(): array
{
return [];
}
public function trans($value): string|array
{
return __('users.' . $value) ?: '-';
}
public function xList(): array
{
return [
amis()->TableColumn('avatar', $this->trans('fields.avatar'))->type('avatar')->src('${avatar}'),
amis()->TableColumn('username', $this->trans('fields.username')),
amis()->TableColumn('name', $this->trans('fields.name')),
amis()->TableColumn('roles', $this->trans('fields.roles'))
->type('each')->items(
amis()->Tag()
->label('${name}')
->displayMode('rounded')
->color('#4096ff')
->className('my-1')
)
->className('noWrap'),
),
amis()->TableColumn('org.shortname', $this->trans('fields.parent_id')),
amis()->Operation()->label($this->trans('options._actions'))->buttons([
$this->rowEditButton(true, 'lg'),
$this->rowDeleteButton()->visibleOn('${id != 1}'),
]),
];
}
public function xForm(): array
{
return [
amis()->GroupControl()->body([
amis()->TextControl('username', $this->trans('fields.username'))->required(),
amis()->TextControl('name', $this->trans('fields.name'))->required(),
]),
amis()->GroupControl()->body([
amis()->TextControl('password', $this->trans('fields.password'))->type('input-password'),
amis()->TextControl('confirm_password', $this->trans('fields.confirm_password'))->type('input-password'),
]),
amis()->GroupControl()->body([
amis()->TreeSelectControl('parent_id', $this->trans('fields.parent_id'))->required()
->labelField('shortname')
->valueField('id')
->showIcon(false)
->source('/system/admin_org?_action=getData&v=1'),
amis()->SelectControl('roles', $this->trans('fields.roles'))
->searchable()
->multiple()
->labelField('name')
->valueField('id')
->joinValues(false)
->extractValue()
->options(AdminRoleService::make()->query()->get(['id', 'name'])),
]),
amis()->GroupControl()->body([
amis()->TextControl('email', $this->trans('fields.email'))->required(),
amis()->TextControl('mobile', $this->trans('fields.mobile'))
]),
];
}
public function xView(): array
{
return [
amis()->ImageControl('avatar', $this->trans('fields.avatar'))->type('avatar')->src('${avatar}'),
amis()->TextControl('username', $this->trans('fields.username'))->static(),
amis()->TextControl('name', $this->trans('fields.name'))->static(),
amis()->TextControl('email', $this->trans('fields.email'))->static(),
amis()->TextControl('mobile', $this->trans('fields.mobile'))->static(),
amis()->FormControl()->label($this->trans('fields.roles'))
->body(
amis('each')->name('roles')->items(
amis()->Tag()
->label('${name}')
->displayMode('rounded')
->color('#4096ff')
->className('my-1')
)
)
];
}
}
Service修改
<?php
namespace App\Services;
class AdminUserService extends \Slowlyo\OwlAdmin\Services\AdminUserService
{
public function list(): array
{
$query = $this->listQuery();
$items = (clone $query)->paginate(request()->input('perPage', 20))->items();
$total = (clone $query)->count();
return compact('items', 'total');
}
public function listQuery()
{
$keywords = request()->input('keywords') ?: null;
$orderBy = request()->input('orderBy') ?: null;
$orderDir = request()->input('orderDir') ?: null;
if ($keywords) $type = null;
$model = $this->getModel();
$query = $this->query()
->with(['roles', 'org'])
->select(['id', 'name', 'username', 'avatar', 'created_at', 'parent_id', 'email', 'mobile'])
//->orderByDesc($model->getUpdatedAtColumn())
->when($orderBy, fn($query) => $query->orderBy($orderBy, $orderDir))
->when($keywords, fn($query) => $query->where('username', 'like', "%{$keywords}%")->orWhere('name', 'like', "%$keywords%"));
$this->searchable($query);
return $query;
}
}
Lang修改:
<?php
return [
'labels' => [
'User' => '用户',
'user' => '用户',
],
'fields' => [
'uuid' => 'UUID',
'username' => '用户名',
'name' => '姓名',
'email' => '邮件',
'avatar'=>'头像',
'password' => '密码',
'old_password' => '旧密码',
'confirm_password' => '确认密码',
'mobile'=>'手机',
'status' => '状态',
'roles'=>'角色',
'parent_id' => '组织',
'created_at' => '创建时间',
'updated_at' => '更新时间',
'deleted_at' => '删除时间',
],
'options' => [
'_search' => '按名称搜索',
'_actions' => '操作',
'_show' => '正常',
'_hide' => '冻结',
'_status' => [
"0" => "<span class='label label-danger'>正常</span>",
"1" => "<span class='label label-success'>冻结</span>",
"*" => "无效"
],
],
];
Config修改:
'models' => [
'admin_user' => \App\Models\AdminUser::class,
'admin_role' => \Slowlyo\OwlAdmin\Models\AdminRole::class,
'admin_menu' => \Slowlyo\OwlAdmin\Models\AdminMenu::class,
'admin_permission' => \Slowlyo\OwlAdmin\Models\AdminPermission::class,
],
Route修改:
Route::resource('system/admin_users', \App\Http\Controllers\AdminUserController::class);
Route::post('system/admin_users/{id}/edit', [\App\Http\Controllers\AdminUserController::class,'update']);
描述问题:
在bootstrap中使用动态菜单,显示的时候总是三个点
bootstrap中的内容如下:
Admin::menu()->add([
[
'id' => 2000,
'parent_id' => 2,
'order' => 0,
'title' => __('menu.admin_org'),
'icon' => 'clarity:organization-solid',
'url' => '/system/admin_org',
'url_type' => 1,
'visible' => 1,
'is_home' => 0,
'component' => 'amis',
'is_full' => 0,
'extension' => null,
],
]);
Admin::menu()->add([
[
'id' => 10000,
'parent_id' => 0,
'order' => 0,
'title' => '测试',
'icon' => 'ph:test-tube-fill',
'url' => '/test',
'url_type' => 1,
'visible' => 1,
'is_home' => 0,
'component' => 'amis',
'is_full' => 0,
'extension' => null,
],
]);
$ticket = 1000;
Admin::menu()->add([
[
'id' => $ticket,
'parent_id' => 0,
'order' => 0,
'title' => __('ticket::ticket.menu.title'),
'icon' => 'ic:sharp-medical-services',
'url' => '/ticket',
'url_type' => 1,
'visible' => 1,
'is_home' => 0,
'component' => 'amis',
'is_full' => 0,
'extension' => null,
],
[
'id' => 2001,
'parent_id' => $ticket,
'order' => 0,
'title' => __('ticket::ticket.menu.incident'),
'icon' => 'ic:baseline-report-problem',
'url' => '/ticket/incident',
'url_type' => 1,
'visible' => 1,
'is_home' => 0,
'component' => 'amis',
'is_full' => 0,
'extension' => null,
],
[
'id' => 2002,
'parent_id' => $ticket,
'order' => 0,
'title' => __('ticket::ticket.menu.change'),
'icon' => 'material-symbols:question-exchange-rounded',
'url' => '/ticket/change',
'url_type' => 1,
'visible' => 1,
'is_home' => 0,
'component' => 'amis',
'is_full' => 0,
'extension' => null,
],
[
'id' => 2003,
'parent_id' => $ticket,
'order' => 0,
'title' => __('ticket::ticket.menu.guidance'),
'icon' => 'icon-park:coronavirus',
'url' => '/ticket/guidance',
'url_type' => 1,
'visible' => 1,
'is_home' => 0,
'component' => 'amis',
'is_full' => 0,
'extension' => null,
],
[
'id' => 2004,
'parent_id' => $ticket,
'order' => 0,
'title' => __('ticket::ticket.menu.navbar'),
'icon' => 'material-symbols:assistant-navigation',
'url' => '/ticket/navbar',
'url_type' => 1,
'visible' => 1,
'is_home' => 0,
'component' => 'amis',
'is_full' => 0,
'extension' => null,
],
]);
3.0.8
docker 安装的mysql8.0,php8.2、nginx
尝试了一下,如果parent_id == 0的情况下,有时5个的时候显示正常
部署各种问题, mac
如题,多谢
原来使用的nwidart/laravel-modules功能中有两个Provider,一个是RouteServiceProvider,一个是XXXServiceProvider
这些要自己写吗?文档太少,看不懂
$this->registerCommands();
$this->registerCommandSchedules();
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
可以的话,尽可能提供截图或视频来补充描述你的问题...
你是在哪个版本的 owl-admin 上遇到的问题?
php8.3 & laravel: 10..
eg: Win + Docker
Mac + Sail
Linux + BT
请简单描述一下复现的操作步骤...
最新的3.1.2中src/Console/Module/stubs/initCommand.php和UpdateCommand.php中的
if (is_file(public_path('admin/index.html'))) {
仍然是原来的,应该是if (is_file(public_path('admin-asset/index.html'))) {
模块中生成的config/admin.php中仍然是admin,而不是admin-asset
'logo' => '/admin/logo.png',
'default_avatar' => '/admin/default-avatar.png',
可以的话,尽可能提供截图或视频来补充描述你的问题...
你是在哪个版本的 owl-admin 上遇到的问题?
eg: Win + Docker
Mac + Sail
Linux + BT
请简单描述一下复现的操作步骤...
amisMake()->Page()->title('Hello world')->body([amisMake()->Grid()->columns([['body' => [],'id' => 'u:2dc45a289b0c',],['body' => [],'id' => 'u:1eac9b6bc5ff',],])->id('u:e8393964b69f'),amisMake()->Form()->title('表单')->body([amisMake()->TextControl()->label('文本框')->name('text')->id('u:43626c35f4e3'),])->id('u:ce4245bc3f1e')->actions([amisMake()->TagControl()->label('标签')->name('tag')->options(['0' => '红色','1' => '绿色','2' => '蓝色',])->id('u:39bcc8d9ebb4'),]),amisMake()->InputExcel()->label('Excel')->name('excel')->id('u:273029d76a40'),])->id('u:59f968412d70')
转换成了 php, 在那个地方使用这个代码生成界面呢?
初学者,不好意思,文档看了半天没看明白
辛苦大佬帮帮忙
可以支持laravel 10吗
RT,考虑升级下Amis的版本吗?新出了3.0版本
The route admin-api/api/upload/startChunk could not be found.
The nwidart/laravel-modules module has modified the directory structure, and when executed
PHP Artisan module: make Test
PHP Artisan management module: init -- module=Test
An error will occur.
默认的文件/图片上传处理方法, 返回的文件路径不包含域名, 导致回显失败
使用 属性修改器
:
// 你的文件/图片字段
public function image(): Attribute
{
return file_upload_handle();
}
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.