Appearance
MgrApp
前后端分离的项目包
安装
后端需要添加包 poppy/mgr-app
当前版本是开发版, 版本是 4.0.x-dev
, 因为授权返回的地址是有此包支持, 所以需要添加此扩展包
前端访问
mgr-app 文件内置在 mgr-page 包的 resources 目录下, 当前是属于开发过程中, 包放置在 GitHub Release
nginx 进行如下配置
mgr-app.conf
server {
listen 9101;
server_name localhost;
index index.html;
root /path/of/mgr-app;
location / {
add_header Cache-Control "public, max-age=0, must-revalidate";
try_files $uri $uri/ /index.html?$query_string;
}
access_log off;
error_log off;
}
domain.conf
server {
# ...
location /mgr-app {
rewrite "mgr-app/(.*)" /$1 break;
proxy_pass http://127.0.0.1:9101;
}
# ...
}
如果需要自定义目录, 从源码编译并自行配置包目录即可
开发
数据准备
# demo 集成
$ php artisan poppy:migrate module.demo
# 创建数据
$ php artisan poppy:seed module.demo --class='\Demo\Database\Seeds\DemoWebappDatabaseSeeder'
$ php artisan poppy:seed module.demo --class='\Demo\Database\Seeds\DemoUserDatabaseSeeder'
# 还原数据
$ php artisan poppy:migrate:rollback
路径配置
路径是生成前端所用导航的入口文件, 告诉前端如何加载数据, 渲染页面, 文件位于 modules/{module}/configurations/path.yaml
yaml
# [1]
backend:
# [2]
default:
title: 菜单
# [3]
icon: picture-rounded
# [4]
children:
- title: 分组
children:
- title: 链接
# {type}/{route}/{route_params|explode by ,}/{query|gen_key}
path: form/demo:api.mgr_app.form/field-textarea
[1]类型 backend 代表和用户类型想匹配的定义, 分为 user/develop/backend 三种
[2]注入 这里的 KEY 作为注入项目 module.demo/backend||default, 可以将配置注入到这个地方, 例如在 mgr-page 模块下存在 key backend.setting
这个 key, 我们使用 injection 可以将模块配置注入到另外一个模块中达到不同的导航菜单的功能, 对于模块之间的顺序, 我们可以通过模块 manifest.json
文件中的 order
字段来进行定义, 按照从小到大的顺序进行排列
yaml
backend:
area:
title: 地区管理
# 将当前模块下所有 children 追加到指定key 的 children 中
injection: "poppy.mgr-app/backend||setting"
children:
- title: 地区管理
children:
- title: 地区管理
path: grid/py-area:api-backend.content.index
permission: "backend:py-area.main.manage"
[3]图标
图标我们使用 element-plus 图标库, 图标名称格式支持 kebab-case
和 CamelCase
命名, 例如 CircleCheck
图标, 我们也可以写为 circle-check
[4]菜单 对于以上层级我们进行如下定义
导航 : 在顶部作为主导航
分组 : 对链接进行分组
链接 : 可以更改路由地址的链接
[5]链接
链接的组成规范
form / demo:api.mgr_app.form / field-textarea / name|my
{type} / {route} / {route_params} / {query}
- type : 链接支持的格式, form : 表单, setting : 设置, grid : 列表
- route : 路由, 通过 Laravel 定义的路由
- route_params : 路由参数, 使用 , 分隔
- query : 使用
\Poppy\Framework\Helper\ArrayHelper::genKey()
方式把字串解析成数组
Action
项目中的操作项, 操作可分为 request(请求)
, page(页面)
, copy(复制)
, progress(进度)
, ``
基本样式
php
$action
// 弹出确认弹窗
->confirm()
// 设置图标
// 完整图标地址 : https://element-plus.org/zh-CN/component/icon.html#图标集合
->icon('Close') // 设置图标名称
->only() // 设置是否仅仅显示图标
// 设置风格
->primary() // 主题样式
->default() // 默认
->success() // 成功
->info() // 信息
->warning() // 警告
->danger() // 危险
->disabled() // 禁用
// 朴素样式
->plain()
// 文本样式
->link()
// 圆形图标
->circle()
图标
对于操作的图标,我们支持两种类型
使用 ElementUI 的图标需要填入指定的名称即可
php
$action->icon('Bell')
使用 Material 图标, 需要选择 MaterialSymbols 图标, 为了样式实现简约, 只能使用 Outline 样式图标, 为了区分不同的图标库, 需要在图标前加上前缀 mu:
这里的图标名称需要填写图标的蛇形写法, 在图标详情中可以查询到
php
$action->icon('mu:notifications')
使用场景
Grid 表格
php
class GridTableActions extends GridBase
{
public function table(TablePlugin $table)
{
// 添加 Action
$table->add('handle', '操作')->asAction(function (GridActions $actions) {
// 获取单行数据
$row = $actions->getRow();
$actions->request('错误', route('demo:api.mgr_app.grid_request', ['error']));
$actions->page('页面', route('demo:api.mgr_app.grid_form', ['detail']), 'form');
$actions->copy('复制', '复制自定义的内容' . $row['id']);
});
}
}
Grid 操作
php
class GridLayout extends GridBase
{
public string $title = '布局';
public function quick(Interactions $actions)
{
$actions->page('快捷操作', route('demo:api.mgr_app.grid_form', ['detail']), 'form')->icon('Plus');
}
public function batch(Interactions $actions)
{
$actions->request('批量操作', route('demo:api.mgr_app.grid_request', ['success']));
}
}
request
Ajax 请求
对服务器发起一个 ajax 请求, 并根据服务端返回内容进行前端页面的操作, 这里根据服务端的返回触发全局 Motion, 操作返回的 data 的数据作为 Motion 数据
php
$actions->request('成功', route('demo:api.mgr_app.grid_request', ['success']));
page
以内部页面方式打开指定类型数据
使用侧边栏方式打开一个页面, 当前支持 form
, grid
两种数据内容
php
$actions->page('页面', route('demo:api.mgr_app.grid_form', ['detail']), 'form');
dialog
使用对话框的形式来打开一个页面, 当前支持 form
, grid
两种数据内容
php
$actions->dialog('页面', route('demo:api.mgr_app.grid_form', ['detail']), 'form');
copy
复制自定义数据
复制按钮, 点击此按钮可已复制自定义的数据
php
$actions->copy('复制', '复制自定义的内容' . $row['id']);
target
在新窗口打开链接
新窗口打开, 打开自定义的链接地址
php
$actions->target('Target(百度)', 'https://www.baidu.com');
iframe
在当前窗口打开对话框, 对话框中展示允许嵌入的 iframe
php
$actions->iframe('Iframe', 'https://poppy-framework.com/');
Dashboard
Dashboard 意思是仪表盘, 目的是集中多个部分放到一个页面中进行展示, 可用于不同 scope
之间的配置和主页仪表盘
类之间的关系如下
Dashboard
是仪表板, Panel
定义为仪表盘的部件
使用
定义路径
这里的 url 类型是 dashboard
yaml
- title: 表单仪表盘
path: dashboard/demo:api.mgr_app.dashboard/form
定义控制器
php
class DashboardController {
public function form()
{
$dashboard = new DashboardForm();
return $dashboard->resp();
}
}
定义仪表盘
php
/**
* 表单仪表盘
*/
class DashboardForm extends DashboardWidget
{
// 标题
public string $title = '仪表盘';
public function __construct()
{
parent::__construct();
// 定义 Scope
$this->scope('test', 'TEST');
$this->scope('mark', 'Mark');
}
// 定义仪表盘面板
public function panels(): array
{
// 获取当前的Scope
$scope = $this->getCurrentScope();
// 定义面板
$form1 = (new PanelForm('site', 12))->form(function (FormPlugin $form) use ($scope) {
$form->text($scope->value . ':Title', $scope->label . '标题')->rules([
Rule::required(),
]);
})->handle(function ($data) {
return Resp::success('返回成功' . var_export($data, true));
});
return [$form1];
}
}
Scope
Scope 定义为 Dashboard 分类, 根据不同的类型区分不同的仪表盘的数据展示, 这里引用的是 trait \Poppy\MgrApp\Classes\Traits\UseScopes
, 提供的方法有
php
trait UseScopes
{
/**
* 添加全局范围, 在添加全局范围之后, 如果不传入 Scope, 则默认为第一个 Scope
*/
public function scope(string $key, string $label)
/**
* 范围结构
* @return Collection
*/
public function getScopesStruct(): Collection
/**
* 获取当前的Scope,
* 支持未传入
*/
public function getCurrentScope(): ?Scope
}
PanelForm
表单面板, 定义为表单提交类型
php
// 定义标题以及宽度
(new PanelForm('site', 12))
// 定义表单项目, 这里的类型和 Form 一致
->form(function (FormPlugin $form) {
$form->text('Title', '标题')->rules([
Rule::required(),
]);
})
// 定义表单数据接收的处理方式
->handle(function ($data) {
return Resp::success('返回成功' . var_export($data, true));
});
Setting
设置用于支持分组的配置
Motion
Motion 用于触发全局的动作, 使用后端返回内容来用于前端的不同操作
编写: Motion 使用 Resp 返回 Motion 格式如下, 如果使用 Resp 返回, 则也可使用 kv 方式来编写 motion|grid:reload;time|200
解析之后的对象如下所示
javascript
{
motion: "grid:reload";
time: 200;
path: "";
}
设置用于在表单中加入操作, 在 Grid 渲染中加入操作, 批处理, 表单的快速操作
参数说明
motion : 全局操作
grid:reload
加载当前请求条件下的数据grid:reset
请求搜索条件并重置到第一页grid:filter
更新请求条件window:reload
刷新当前页面
time : 等待时长来执行函数, 单位(ms) path : 匹配路径 当页面中存在多个组件的时候, 组件的请求地址是不同的, 可以根据请求路径的 path 来判定是否允许更新, path 不存在时候不进行限制
为了项目中方便使用, 已经对 Motion 进行了封装
php
Motion::windowReload()
Motion::gridFilter()
Motion::gridReset()
Motion::gridReload()