feat: hyperf-admin init

This commit is contained in:
daodao97
2020-06-16 22:33:55 +08:00
commit 8d89932c98
198 changed files with 20104 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
通用配置在只需要使用表单搜集信息, 没有过多业务逻辑和校验规则时使用, 可以无需开发, 完成表单的定义和使用
1. 定义表单 http://localhost:9528/system/#/cconf/list, 此处表单规则同控制器中的form定义
![](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/DGD103.png)
2. 投放表单, 创建 `/***/cconf_{1中的表单名称}` 即可通过该路由访问
![](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/b9Pw1z.png)
3. 访问 http://localhost:9528/hyperf/#/lucky/cconf_lucky_round
![](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/I3pgnz.png)
数据存储位置`hyperf_admin.common_config`
```mysql
CREATE TABLE `common_config` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`namespace` varchar(50) NOT NULL DEFAULT '' COMMENT '命名空间, 字母',
`name` varchar(100) NOT NULL COMMENT '配置名, 字母',
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '可读配置名',
`remark` varchar(100) NOT NULL DEFAULT '' COMMENT '备注',
`rules` text COMMENT '配置规则描述',
`value` text COMMENT '具体配置值 key:value',
`permissions` text COMMENT '权限',
`create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique` (`name`,`namespace`),
KEY `namespace` (`namespace`),
KEY `update_at` (`update_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='通用配置';
```
可以通过 http://localhost:9528/system/#/cconf/list 管理命名空间
系统中可以使用`Rcok\BaseUtils\Service\CommonConfig`获取相应的提交数据

View File

@@ -0,0 +1,7 @@
脚本作业的管理中心, 可以在代码中实现`class`类型, `command`类型的脚本作业, 在后台添加相关任务, 即可在相应脚本机上执行
可以对任务的入口, 执行规划, 执行节点, 执行参数 等进行配置, 也可在列表主动触发任务
作业必须基于`App\Util\CronCenter\ClassJobAbstract`, 或`App/Util/CronCenter/CommandJobAbstract.php`抽象类进行实现, 才可进行执行状态的跟踪
`CronCenter`的实现基于`hyperf-crontab`进行实现, 具体代码在`app/Util/CronCenter`, 更多细节可查看[文档](https://hyperf.wiki/#/zh-cn/crontab)

View File

@@ -0,0 +1,97 @@
数据大盘
DataFocus (焦点数据) 用途是帮助大家快速构建一个如下的数据面板, 对数据可视化做了大量封装, 让开发者只用关心数据来源和数据处理, 无需处理复杂的图标构建, 即可轻松制作出漂亮的看板, 为业务决策这提供更直观的参考.
数据面板的定义
数据面板中可以定义, `sql`, `json`, `php代码`, `markdown` , `html` 等级数据格式, 通过统一转换由相应前端组件渲染成`图标``列表`
目前支持的图标样式`LineChart`, `ColumnChart`, `PieChart`, `NumberPanel` 分别会渲染为`曲线图`, `柱状图`, `饼图`, `数字面板`, `列表`
### sql节点
1. 定义改节点的属性
1. id 节点名称, 必须, 不可重复
2. dsn sql 查询说使用的dsn, 可用dsn的范围是 hyperf/config/databaes 中 DataFocus Dsn 中定义的数据源
3. chart 图标类型, 格式为`图表名|X轴,Y轴1,Y轴2,…`, 图标名为必须
4. show_table 默认 `false`, 为`true`时除了渲染图表, 还会渲染数据列表
5. table_plugin 表级的插件, 可以对结果数据做二次干预, 可以调用 DataFocus/plugin_fucntion 中定义的全局插件, 也可在调用当前面板中自定义插件
1. 自定义插件为 当前页面的一段`php function`代码
2. 面板中的所有自定义`php`方法, 必须以`df_`开头
6. span 布局 总24的栅格布局, 具体参见
2. 节点内容, 填写构造数据的查询`sql`即可
1. 一个`<sql></slq>` 节点 只能定义一个`sql`语句
2. 只能使用`select`语句
下面的样例中定义的一个以日期`date``X轴`, 其他数据指标为`Y轴`的曲线图
```php
<sql id="近30日访问趋势" dsn="hyperf_admin" chart='LineChart|date' >
select
visitor_uv as "人数",
visitor_pv as "次数"
data_date as date
from
visitor_log
where
data_date >= {{ date('Y-m-d', strtotime('-30 day')) }}
group by date
</sql>
```
其他类型的图标也基本类似, 只用调整相应的`chart`数据即可, 比如下面的饼图
```php
<sql id="今日访问地区占比" dsn="rock_admin" chart="PieChart" table_plugin="df_list_transposition:地区,数量" span="12">
select
area as "地区",
count(1) as "数量"
from
visitor_log
where
data_date >= {{ date('Y-m-d', strtotime('-1 day')) }}
group by area
</sql>
```
3. 模板变量
细心的同学可能已经发现, 上面的`sql`内容中使用了`{{ date('Y-m-d', strtotime('-1 day')) }}`这样的变量定义,模板变量的定义类似 `twig` 语法, 本质上是把花括号的内容转换为`php`代码进行运算, 然后替换模板变量, 执行`sql`.
格式: `{{ func|pip1|pip2 }}`
`func` 为数据的产生源头, 是必须的. 后面`|` 竖线分隔的管道, 让会源头输出的结构做二次处理, 最终替换到模板中
次数模板替换时, 会默认给变量加引号, 比如上方的`sql` 最终会替换为 `data >= '2020-06-11'`, 若需要原样输出, 可只用 `raw` 管道
管道也可以是一个自定义`php` 方法
更多样例见`系统管理/DataFocus/数据面板` 菜单下
### json
节点属性同 sql
节点内容, 可以填入`json`格式数据
```php
<json>
{
"lable":"value"
}
</json>
```
### php
php并非一个单独节点, 而是可以作为一个片段, 迁移任意节点内
```php
<json>
<?php return json_encode(df_******());?>
</json>
```
### md
### html

View File

@@ -0,0 +1,11 @@
## 代码自动生成工具
针对 数据库, `Model`, `Controller` 通用模型, 可以使用后台提供的`代码生成工具`来初始化大部分代码.
![9fnAUL(1)](https://cdn.jsdelivr.net/gh/daodao97/FigureBed@master/uPic/9fnAUL%20%281%29.png)
连接池对应`config.autoload.databases` 中配置的可用链接, 选择好`连接池`, `数据库`, `表` 后下方表单会根据表结构字段渲染, 完成具体字段的配置, 点击提交.
![b4lL49](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/b4lL49.png)
相应的`Modle`, `Controller` 便已创建成功.

430
docs/backend/form.md Normal file
View File

@@ -0,0 +1,430 @@
## 字段规则
```php
'field|字段名称' => [
// 字段验证规则,
'rule' => 'required|max:',
// 请参考http://www.form-create.com/v2/element-ui/components/input.html
'type' => 'input',
// 表单默认值
'default' => '',
'info' => '字段备注',
// 只读属性,当编辑时有效
'readonly' => true,
// 表单选项只有支持options选项的组件设置才有效可以定义一个callback方法可以参考formOptionsConvert方法
'options' => [],
// 其他组件属性请参考具体组件的props的定义
'props' => [],
// 定义依赖项
'depend' => [
'field' => 'target_type',
'value' => [],
],
// col 布局规则 http://www.form-create.com/v2/element-ui/col.html
'col' => [
// 表单长度
'span' => 12,
// 标签宽度
'labelWidth' => 150,
],
// 动态修改其他字段规则 详见下方联动小节
'compute' => [
"will_set_field" => [
"when" => ['=', 1],
"set" => [
//
]
]
],
// 该字段规则回调方法,可以用于重置字段规则
'render' => function () {
},
// 是否虚拟字段虚拟字段在查询脚手架model时会忽略该字段
'virtual_field' => true,
// 该字段在表单中是否渲染默认true
'form' => false,
],
```
*rule: 后端字段验证规则*
rule完整支持 hyperf 原生的 validation 的校验[规则]([https://hyperf.wiki/#/zh-cn/validation?id=%e9%aa%8c%e8%af%81%e8%a7%84%e5%88%99](https://hyperf.wiki/#/zh-cn/validation?id=验证规则)), 且切封装了高度灵活的自定义校验 `app/Service/ValidationCustomRule.php` 其中定义的方法均可在`rule` 中直接使用, 还支持`cb_***` 调用定义在当前控制器中的自定义验证.
> 注意:目前还没有根据该规则生成前端的验证规则,前端目前只验证了是否必填的
## 内置组件
type表单项类型以下是支持的组件列表以下所有组件 props 均可支持原始文档中的所有属性
### 1. 普通输入框
[原始文档](http://www.form-create.com/v2/iview/components/input.html)
```php
[
"field_name|字段名" => "required|***"
// or
"field_name|字段名" => [
"type" => "input" // 可省略, 默认 input
"rule" => "required|***",
"default" => "默认值" // 非必须,
"info" => "字段提示文字",
"props" => [
"showCopy" => true, // 开启 copy 功能
]
]
]
```
### 2. 数字(整数)
[原始文档](http://www.form-create.com/v2/iview/components/input-number.html)
```php
[
"field_name|字段名" => [
"type" => "number"
]
]
```
### 3. 数字(两位小数)
[原始文档](http://www.form-create.com/v2/iview/components/input-number.html)
```php
[
"field_name|字段名" => [
"type" => "float",
"props" => [
"precision" => 2, // 小数保留位数, 默认2
]
]
]
```
### 4. 多行输入
[原始文档](http://www.form-create.com/v2/iview/components/input.html)
```php
[
"field_name|字段名" => [
"type" => "textarea",
"props" => [
"row" => 6, // 行数, 默认6
]
]
]
```
### 5. 开关(0/1)
[原始文档](http://www.form-create.com/v2/iview/components/switch.html)
```php
[
"field_name|字段名" => [
"type" => "switch"
]
]
```
### 6. 时间控件
[原始文档](http://www.form-create.com/v2/iview/components/date-picker.html)
```php
[
"field_name|字段名" => [
"type" => "datetime"
]
]
```
### 7. 时间区间
[原始文档](http://www.form-create.com/v2/iview/components/date-picker.html)
```php
[
"field_name|字段名" => [
"type" => "datetime_range",
"props" => [
"range" => [
"after" => date('Y-m-d'),
"before" => date('Y-m-d', strtotime('+6 days'))
],
// or 简写
"range" => "afterToday", // afterToday 今天之后, beforeToday 今天之前, 包含今天
]
]
]
```
### 8. 日期
[原始文档](http://www.form-create.com/v2/iview/components/date-picker.html)
```php
[
"field_name|字段名" => [
"type" => "date"
]
]
```
### 9. 日期区间
[原始文档](http://www.form-create.com/v2/iview/components/date-picker.html)
```php
[
"field_name|字段名" => [
"type" => "date_range"
]
]
```
### 10. 下拉选择框
[原始文档](http://www.form-create.com/v2/iview/components/select.html)
```php
[
"field_name|字段名" => [
"type" => "select",
"options" => [ // 远程搜索是无需 支持回调函数 function() { return 备选项; }
1 => "lable1",
2 => "lable2",
],
"props" => [
"selectApi" => "/coupon/act", // 远程搜索模式
"multiple" => true, // 是否多选, 默认false
"multipleLimit" => 10, // 多选时的上限
]
]
]
```
### 11. 上传图片
[原始文档](http://www.form-create.com/v2/iview/components/upload.html)
```php
[
"field_name|字段名" => [
"type" => "image",
"props" => [
// 上传张数上线, 默认1单个
"limit" => 1,
//支持下载
"downloadable" => true,
// 限制上传文件的后缀名
"format " => ['jpg', 'jpeg', 'png', 'gif'],
// 限制上传文件的大小 单位是 kb
"maxSize" => 200,
// 上传的目标 bucket
'bucket' => 'aliyuncs',
// 是否为私有
'private' => true,
]
]
]
```
### 12. 上传文件
[原始文档](http://www.form-create.com/v2/iview/components/upload.html)
```php
[
"field_name|字段名" => [
"type" => "file",
"props" => [
// 上传张数上线, 默认1单个
"limit" => 1,
//支持下载
"downloadable" => true,
// 限制上传文件的后缀名
"format " => ['doc', 'exl', 'ppt'],
// 限制上传文件的大小 单位是 kb
"maxSize" => 200,
]
]
]
```
### 13. 级联选择器
```php
[
"field_name|字段名" => [
"type" => "cascader",
"props" => [
"limit" => 1, // 上传张数上线, 默认1单个
]
]
]
```
### 14. json 组件
```php
[
"field_name|字段名" => [
"type" => "json",
]
]
```
### 15. 富文本
```php
[
"field_name|字段名" => [
"type" => "html",
]
]
```
### 16. 图标选择器
```php
[
"field_name|字段名" => [
"type" => "icon-select",
]
]
```
示例效果:
![icon](http://qupinapptest.oss-cn-beijing.aliyuncs.com/1/202005/9e62be2e0affafc0cdee8bc7fba3c0fd.png)
### 17. 嵌套表单 SubForm
```php
'test|嵌套表单' => [
'type' => 'sub-form',
'children' => [ // 子表单的规则, 同一级规则
'test_sub|嵌套1' => 'required',
'test_sub1|嵌套2' => 'required',
],
'repeat' => true, // 是否可动态添加
'default' => [ // 默认值
[
'test_sub' => 1,
'test_sub1' => 1,
],
[
'test_sub' => 1,
'test_sub1' => 1,
],
],
],
```
示例效果:
![subForm](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/Snipaste_2020-02-21_19-29-35.png)
### 18. 区域输入框
[前端文档](http://localhost:8080/hyperfdoc/frontend/components/3_InputRange.html)
```php
'test|区域输入框' => [
'type' => 'inputRange',
// value值 type Array or String
// - Array例如[1, 10], 返回结果也将是数组
// - String例如1,10, 返回结果也将是字符串
'value' => [1, 10] or '1,10',
'props' => {
// 是否允许清除
'clearable': true,
// 可控制item宽度等样式 默认宽度300px
'style': 'width: 300px',
// 开始值和结束值的placeholder
'placeholder': ['min', 'max']
},
],
```
## 组件联动
```php
// depend
[
"field_1" => "",
"field_2" => [
"depend" => [
"field" => "field_1", // 依赖字段
"value" => '1' // 当 field_1 = 1 时 field_2 此项才会显示
]
]
]
// hidden
[
"field_1" => "",
"field_2" => [
"hidden" => [
"field" => "field_1", // 影响字段
"value" => '1' // 当 field_2 = 1 时 field_1 项会隐藏
]
]
]
// 备选项 条件控制
[
"field_1" => [
"type" => "select",
"options" => [
[
"value" => 1,
"lable" => ""
],
[
"value" => 0,
"lable" => "",
// 当 disabled_when 条件运算结果, 即为 disabled 的值
"disabled_when" => [
"field_1", '=', 0
],
// or
"disabled_when" => [
["field_2", '=', 0],
["field_3", '!=', 4],
],
]
]
]
]
// 进阶用法 compute 动态计算
[
"field" => [
"compute" => [
"when" => ['=', 1], // 注意这里只有个 比较操作符 和 比较值
// set 操作项
"set" => [
"field_2" => [
// 此处支持控件除 type 外, 完整属性设置
"value" => 1,
// 此处支持 值为 callable
"value" => function() { return time();},
// 重写rule
"rule" => "required"
"props" => [
// ...
]
],
// ... "field_3"
],
// append 项, 尚未实现
// remove 项, 尚未实现
]
]
]
```

78
docs/backend/functions.md Normal file
View File

@@ -0,0 +1,78 @@
## 数组函数
#### array_group_k2k
#### array_group_by
#### array_node_append
#### array_map_recursive
#### array_copy
#### array_sort_by_key_length
#### array_sort_by_value_length
#### array_to_kv
#### array_flat
#### array_depth
#### array_merge_node
#### array_change_v2k
#### array_group
#### array_last
#### array_split
#### array_get_by_keys
#### array_remove
#### array_get_node
#### array_remove_keys_not_in
#### array_remove_keys
#### mt_array_merge
## 系统函数
#### server
#### swoole_server
#### dispatcher
#### register_route
#### move_local_file_to_oss
#### oss_private_url
#### call_self_api
#### select_options
#### process_list_filter
#### get_sub_dir
#### db_complete
#### format_exception
## 内置常量
`DAY`, `HOUR`, `MINUTE`, `YES`, `NO`

571
docs/backend/list.md Normal file
View File

@@ -0,0 +1,571 @@
![](http://km.innotechx.com/download/attachments/82253382/image2020-5-8_17-43-53.png?version=1&modificationDate=1588931034077&api=v2)
```php
return [
......
// 列表定义
'table' => [
// 树型结构列表默认false
"is_tree" => true
// tree 节点为非必须, 默认pid的名称为pid, 不同时需要重写
"tree" => [
"pid" => "pid"
],
// tabs 列表页分页签
'tabs' => [],
// 定义渲染列表, 未定义则获取 form 中所有
'columns' => [],
// 订单行操作按钮
'rowActions' => [],
// 列表上方批量操作的按钮
'batchButtons' => [],
// 页面上方操作按钮
'topActions' => [],
],
];
```
## 列定义
`columns`中定义列表中显示的字段与表头,具体配置如下:
```php
'columns' => [ // 非必须项, 无则从form转义
'字段', // 简写模式, 直接从form配置转义
// or
[
'field' => 'mall_name',
'title' => '店铺',
// 是否显示该字段默认false
'hidden' => true,
// 字段渲染规则,默认为空, 详见列渲染
'type' => '',
// 是否虚拟字段虚拟字段在查询脚手架model时会忽略该字段
'virtual_field' => true,
// 设置Popover提示信息其中
'popover' => [
'messages' => [
'原因:{remark}',
],
'when' => [
['status', '=', Activity::STATUS_OFF]
]
],
// 表头说明
'info' => '括号内为商家承担',
// 定义该字段显示在哪些tab选项中
'depend' => [
'tab' => [(string)Coupon::TYPE_MALL_MONEY_OFF],
],
// 按字段升降查询功能
'sortable' => true,
// 是否允许编辑,调用*/rowchange/:id接口
'edit' => true,
// 允许编辑的条件
'when' => [
['status', '=', Activity::STATUS_OFF]
],
// 枚举值可以options中的数据转换成Tag显示效果https://element.eleme.cn/#/zh-CN/component/tag
'options' => [],
'enum' => [ // tag 的 type 类型, 参见 element 标签
0 => 'info',
1 => 'success',
],
// 列宽设置,默认为均分模式,不支持百分比
'width': '100px',
],
],
```
## when用法
### 使用说明
```php
'when' => ["field_1", ">", 1],
// or 多个条件时为"与"判断
'when' => [
["field_1", ">", 1],
["field_2", "=", 1]
]
```
::: warning 注意
操作符支持`=``>``>=``<``<=``!=``in``not_in`,多个条件时为"与"判断,且注意参数的数据类型是否一致。
:::
- 可以控制行操作及批量按钮是否显示;
- 可以控制批量操作的过滤掉不满足条件的行;
```
'batchButtons' => [
[
.....
// 控制根据条件显示这里的条件字段来源为queryString
'when'=> [
[字段, 操作符, 值]
],
// 为区别控制显示的when关键字这里使用`selectFilter`
'selectFilter' => [
[字段, 操作符, 值]
]
]
]
```
- 控制列表行的某一列的编辑状态
- 控制列渲染的popover模式下的启用状态
### 查看源码
```javascript
export function whereFilter(obj, where, fakeKey) {
if (!where) {
return true
}
let ret = true
let real_where = where
if (where[0] && typeof where[0] === 'string') {
real_where = [where]
}
for (let i = 0; i < real_where.length; i++) {
const item = real_where[i]
const key = fakeKey ? item[0].replace('.', '-') : item[0]
if (item[1] === '=') {
ret = obj[key] === item[2]
}
if (item[1] === '>') {
ret = obj[key] > item[2]
}
if (item[1] === '<') {
ret = obj[key] < item[2]
}
if (item[1] === '>=') {
ret = obj[key] >= item[2]
}
if (item[1] === '<=') {
ret = obj[key] <= item[2]
}
if (item[1] === '!=') {
ret = obj[key] !== item[2]
}
if (item[1] === 'in') {
ret = item[2].indexOf(obj[key]) !== -1
}
if (item[1] === 'not_in') {
ret = item[2].indexOf(obj[key]) === -1
}
if (!ret) {
return false
}
}
return ret
}
```
## 列渲染
渲染类型:
- `number``switch``input`
- `icon``image``extrude``tag``link``iframe``html`
### number
**渲染条件** `'edit' => true` 且 满足when中定义的条件
**用法**
```php
'type' => 'number',
'edit' => true`,
'when' => [
['status', '=', Activity::STATUS_OFF]
],
```
### switch
**渲染条件** `'edit' => true` 且 满足when中定义的条件
**用法**
```php
'type' => 'switch',
'edit' => true`,
'when' => [
['status', '=', Activity::STATUS_OFF]
],
```
### input
**渲染条件** `'edit' => true` 且 满足when中定义的条件
**用法**
```php
'edit' => true`,
'when' => [
['status', '=', Activity::STATUS_OFF]
],
```
::: warning 注意
目前行编辑的表单组件只支持以上三种类型且不能定义该组件的props
:::
### icon
**渲染条件** `'type' => 'icon'`
**效果展示**<i class="omsfont">&#xe65d;</i>
### image
**渲染条件** `'type' => 'image'`,数据为数组时可以渲染多张图片
**效果展示**![u](http://km.innotechx.com/download/attachments/82253382/image2020-5-8_14-6-56.png?version=1&modificationDate=1588918016653&api=v2)
#### extrude
**用法**
```php
[
"field" => "field_1",
"type" => 'extrude',
"render" => function($field_value, $row) {
// return "<优惠券|balck|yellow>*****"; 单个
// or 支持多个
return [
"<优惠券{replace_field}|balck|yellow>*****{replace_field}"
]; // 格式 <文字|背景色|文字色>, 支持前端变量替换
}
]
```
**效果展示**![o](http://km.innotechx.com/download/attachments/47482497/Snipaste_2020-02-20_09-19-03.png?version=1&modificationDate=1582161564093&api=v2)
### tag
**用法**
```php
[
"field" => "field_1",
"options" => [
0 => '禁用',
1 => '启用',
],
"enum" => [ // tag 样式, 参见 https://element.eleme.io/#/zh-CN/component/tag
0 => 'info',
1 => 'success'
]
]
```
**效果展示**![p](http://km.innotechx.com/download/attachments/47482497/Snipaste_2020-02-20_09-27-03.png?version=1&modificationDate=1582162039284&api=v2)
### link
**用法**
```php
[
"field" => "field_1",
"href" => "http://hyperfadmin.com/page/{id}"
]
// or
[
"field" => "field_1",
"href" => [
"href" => "http://hyperfadmin.com/page/{id}",
"type" => "primary",
"target" => "_blank"
]
]
```
**效果展示**![p](http://km.innotechx.com/download/attachments/47482497/Snipaste_2020-02-20_09-22-39.png?version=1&modificationDate=1582161776808&api=v2)
### iframe
**用法**
```php
[
'field' => 'state_info',
'title' => '运行状态',
'type' => 'iframe',
// 列以button形式显示style控制按钮type, [info|success|primary|danger|warning]
'style' => 'primary',
// 弹出窗口宽度,默认500px
'width' => '500px',
// 弹出窗口高度,默认600px
'height' => '600px'
"render" => function($field_value, $row) {
return "url";// 返回 iframe的src路径
}
]
```
### html
**用法**
```php
[
'field' => 'state_info',
'title' => '运行状态',
'type' => 'html',
"render" => function($field_value, $row) {
return '<p>xxxxxxx<br>xxxxx</p>'; //
}
]
```
### supperButton
**用法**
```php
[
'field' => 'field',
'type' => 'supperButton',
// supperButton的配置信息 必须有
// 配置文档详见supperButton部分
'config' => {
}
]
```
### popover弹出框
支持以上除编辑模式下的列渲染类型
**用法**
```php
[
'field' => 'state_info',
'title' => '运行状态',
'popover' => [
'messages' => [
'上线时间: {state.start_time}',
'最后活跃时间: {state.last_time}',
'运行次数: {state.counter}',
],
'when' => ["field_1", ">", 1],
// or
'when' => [
["field_1", ">", 1],
["field_2", "=", 1]
]
]
]
```
**效果展示**![popover弹出框](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/Snipaste_2020-02-21_18-06-06.png)
### progress
**用法**
```php
[
'field' => 'sync_progress',
'title' => '同步进度',
'type' => 'progress',
// 'props' => []
]
```
> props里是progress组件的属性配置请参考[Progress 进度条](https://element.eleme.cn/#/zh-CN/component/progress#attributes)
**效果展示**![Progress 进度条](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/Snipaste_2020-02-21_18-06-06.png)
## 搜索项
```php
[
......
// 搜索条件, 前端页面会根据此处配置渲染搜索条件,可以像表单一样配置规则
// 搜索条件中支持模糊搜索也很简单 %field_name%, field_name%, %field_name, 如此定义字段即可
'filter' => [
'id',
'username%',
'create_at|创建时间' => [
'type' => 'date_range',
'search_type' => 'between',
'default' => [date('Y-m-d', time() - DAY * 7), date('Y-m-d', time() + DAY)]
]
],
]
```
## tab切换
```php
'tabs' => [
[
'label' => '平台券',
'value' => (string) Coupon::TYPE_PLATFORM_MONEY_OFF,
'icon' => 'el-icon-s-grid',
],
[
'label' => '店铺券',
'value' => (string) Coupon::TYPE_MALL_MONEY_OFF,
'icon' => 'el-icon-s-grid',
],
],
'columns' => [
[
'field' => 'state_info',
'title' => '运行状态',
// 定义该字段显示在哪些tab选项中
'depend' => [
'tab' => [(string)Coupon::TYPE_MALL_MONEY_OFF],
],
]
]
```
**效果展示**![](http://qupinapptest.oss-cn-beijing.aliyuncs.com/img/Snipaste_2020-02-21_19-46-14.png)
## 操作按钮
支持 列操作按钮, 批量操作按钮, 列表页顶部按钮,前端组件为`SuperButton`
### 基础属性
```php
[
"text" => "", //按钮文案,支持参数替换
"type" => "jump", // 按钮类型 默认 jump, 可选 form, api
"target" => "", // 动作目标 本地路由, 网址, 后端api支持参数替换
"props" => [ // 按钮属性, 更多可见 https://element.eleme.io/#/zh-CN/component/button
"icon" => "", // 按钮图标 默认无
"circle" => false, // 圆角 默认false
"size" => "small", // 默认 small, 可选 medium / small / mini
"type" => "info", //默认text, primary / success / warning / danger / info / text
],
"when" => [ // 当前按钮的显示条件, 默认无
["field_1", "=", 1] // filter过滤的比对数据为当前行 或者 当前页面基础数据
]
]
// 除以上基础属性外, 根据按钮类型, 也会有其他额外属性, 具体见下面
```
### 普通跳转按钮
```javascript
[
"text" => "编辑",
"target" => "/user/12"
]
// or
[
"text" => "文档",
"target" => "http://hyperf.wiki"
]
```
### 动作按钮(请求后端API)
点击按钮后, 提示二次确认, 确认后请求后端api
```javascript
[
"text" => "删除",
"target" => "/user/12",
"method" => "POST", // 请求api的方式, 默认POST
]
```
### 表单型按钮
点击按钮后将以弹窗形式渲染指定表单, 然后搜集后端数据请求到指定api
```javascript
[
"text" => "审核通过",
"target" => "/user/12",
"method" => "POST", // 请求api的方式, 默认POST
"rules" => [ // 表单的rule规则具体参见表单部分
"reason|原因" => [
"rule" => "required"
]
]
]
// 有联动时
[
"text" => "审核通过",
"target" => "/user/12",
"method" => "POST", // 请求api的方式, 默认POST
"rules" => [
// 待补充
]
]
// or
[
"text" => "审核通过",
"target" => "/user/form", // get 方式拉取表单配置, post 方式保存数据
"method" => "POST", // 请求api的方式, 默认POST
]
```
### 列表型按钮
点击按钮后将以弹窗的形式渲染指定列表
```php
[
'type' => 'table', // 调用 src/components/Scaffold/tablist.vue 渲染
'target' => '', // target 留空
'props' => [
'listApi' => '/merchantlog/list?merchant_id={id}', // 列表数据拉取接口
'infoApi' => '/merchantlog/info', // 列表 配置拉取接口
'options' => [ // 表单的配置项
'showFilter' => false,
'createAble' => false
]
],
'text' => '招商记录',
]
```
### 抽屉型按钮
点击按钮后将打开抽屉, 抽屉内部指定动态调用指定组件
```php
[
'type' => 'drawer',
'target' => '', // target 留空
'text' => '查看日志',
'props' => [
'component' => 'SocketList', // 需动态调用的组件 src/components/Common 下
'componentProps' => [ // 组件的 props
'url' => env('OMS_WEBSOCKET_URL') . '/cronlog?name={name}'
],
// drawer** 为抽屉属性的定义
// 详见 https://element.eleme.io/#/zh-CN/component/drawer
'drawerWithHeader' => false,
'drawerSize' => '80%',
'drawerTitle' => '{title}日志',
'drawerDirection' => 'ttb'
]
]
```
### 下拉按钮
上面 SuperButton 的结构改为数组形式即可

408
docs/backend/scaffold.md Normal file
View File

@@ -0,0 +1,408 @@
## 路由注册
一个独立的业务模块需要在`config/routes/`下添加业务的路由文件,在该文件内完成业务模块所有的路由定义。可以使用`register_route`方法来定义您的路由。
```php
<?php
use Hyperf\HttpServer\Router\Router;
use App\Controller\IndexController;
register_route('/index', IndexController::class, function ($controller) {
// 其他路由的定义
Router::get('/hello-hyperf', [$controller, 'hello']);
});
```
!> 如果完全是自定义的前端页面,建议不使用`register_route`注册路由,`register_route`内部会注册一些脚手架路由
**脚手架路由**
| uri | 请求方式 | 控制器方法 | 说明 |
| :----------------------------------------------------------- | :------- | :---------------- | :---------------------------------------------- |
| `path`/list.json<br>`path`/info | GET | info | 下发列表页的配置 |
| `path`/form.json<br>`path`/form<br>`path`/{id:\d+}.json<br>`path`/{id:\d+} | GET | form、edit | 下发表单配置 |
| `path`/list | GET | list | 下发列表数据 |
| `path`/form | POST | save | 新增时数据保存接口 |
| `path`/{id:\d+} | POST | save | 编辑时数据保存接口 |
| `path`/delete | POST | delete | 删除接口 |
| `path`/batchdel | POST | batchDelete | 批量删除接口 |
| `path`/rowchange/{id:\d+} | POST | rowChange | 行编辑数据保存接口 |
| `path`/childs/{id:\d+} | GET | getTreeNodeChilds | 树结构的列表页动态获取子节点的接口 |
| `path`/newversion/{id:\d+}/{last_ver_id:\d+} | GET | newVersion | 表单编辑时或数据对象的版本信息接口 |
| `path`/export | POST | export | 导出任务接口 |
| `path`/act | GET | act | 可用于当前model提供select组件远程搜索的数据接口 |
| `path`/import | POST | import | 导入接口 |
## 脚手架概览
在编写控制器时需`继承`脚手架的抽象类`AbstractController`,并在`scaffoldOptions`方法中定义页面的配置。
```php
<?php
declare(strict_types=1);
namespace App\Controller;
use Hyperf\Admin\Controller\AdminAbstractController;
class IndexController extends AdminAbstractController
{
// 操作的 model 对象
public $model_class = User::class;
// 操作的entity
// entity 为脚手架抽象出的一个实体, 包含对象的 curd 操作
// 目前支持 mysql/es/mongo/api
// model 和 entity 任选其一即可
public $entity_class = UserEntity::class;
// 脚手架核心配置
public function scaffoldOptions()
{
return [
// 自定义创建按钮的跳转路由, 默认 /user/form
'form_path' => '/custom/path',
// 是否允许创建, 默认 true, false怎隐藏页面列表上方的新建按钮
'createAble' => false,
// 是否允许删除, 默认 true
'deleteAble' => true,
// 是否开启通知查询功能,开启后在页面路由发生变化时,会根据当前页面参数查询页面有没有通知消息
'noticeAble' => true,
// 是否需要分页器 默认true
'paginationEnable' => true,
// 是否显示导出按钮, 默认true
'exportAble' => true,
// 列表页是否默认执行查询, 默认执行查询
'defaultList' => false,
// 搜索条件, 前端页面会根据此处配置渲染搜索条件,可以像表单一样配置规则
// 搜索条件中支持模糊搜索也很简单 %field_name%, field_name%, %field_name, 如此定义字段即可
'filter' => ['id', 'username%', 'create_at'],
// 列表的基础筛选条件, 列表的查询均会携带上此处的条件, 详情请查看where2query方法
'where' => [
'type' => User::STATUS_ON,
],
// 筛选条件是否同步到地址栏
"filterSyncToQuery" => false,
// 列表的排序
'order_by' => 'id desc',
// 表单页面的UI配置, 详参 http://form-create.com/v2/iview/global.html
'formUI' => [
'form' => [
'lableWidth' => '300px'
],
'submitBtn' => [
'innerText' => '这是提交按钮'
]
],
// form表单的定义, 核心配置, 不可或缺,请求请查看表单页配置
'form' => [
'field|字段名称' => [
// 字段验证规则
'rule' => 'required|max',
'type' => 'input',
'info' => '字段备注',
],
],
// 页面提示
'notices' => [
[
'type' => 'warning',
'message' => '提示信息',
'actionsPlacement' => 'right',
'closable' => true,
'actions' => [
[
'props' => [
'size' => 'mini',
'type' => 'success',
],
// 勿动!! 选品页面是监听点击事件同当前 text 比对.
'text' => '点我更新',
'type' => 'native',
]
],
'when' => function($filters) { return true;}
]
],
// 第三方数据补充, 子项定义规范, 详见下方列表第三方数据补充部分
'hasOne' => [
'mt_oms.mt_oms.user_role:user_id,role_id'
],
// 列表定义
'table' => [
// tabs 列表页分页签
'tabs' => [],
// 定义渲染列表, 未定义则获取 form 中所有
'columns' => [],
// 订单行操作按钮
'rowActions' => [],
// 列表上方批量操作的按钮
'batchButtons' => [],
// 页面上方操作按钮
'topActions' => [],
],
];
}
}
```
## 内置钩子
```php
// 列表页下发配置接口的前置钩子
public function beforeInfo(&$info) {}
// 列表页执行搜索前的钩子, 可用于修改 where 条件
public function beforeListQuery(&$conditions) {}
// 列表数据响应前的钩子, 可用于补充额外数据
public function beforeListResponse(&$list) {}
// form 规则下发前的干预钩子
public function meddleFormRule($id, &$form_rule) {}
// form 响应前的钩子
public function beforeFormResponse($id, &$record) {}
// 表单保存前端钩子函数
public function beforeSave($pk_val, &$data) {}
// 表单保存后的钩子函数
public function afterSave($pk_val, &$data) {}
// 删除前的回调钩子
public function beforeDelete($pk_val) {}
// 删除后的回调钩子
public function afterDelete($pk_val, $deleted) {}
```
## 表单定义
```php
public function scaffoldOptions()
{
return [
....
// 表单配置
'form' => [
// 字段验证规则
// 请参考 https://hyperf.wiki/#/zh-cn/validation?id=%e9%aa%8c%e8%af%81%e8%a7%84%e5%88%99
'rule' => 'required|max:10',
// 请参考 http://www.form-create.com/v2/element-ui/components/input.html
'type' => 'input',
// 表单默认值
'default' => '',
'info' => '字段备注',
// 只读属性,当编辑时有效
'readonly' => true,
// 表单选项只有支持options选项的组件设置才有效可以定义一个callback方法可以参考formOptionsConvert方法
'options' => [],
// 其他组件属性请参考具体组件的props的定义
'props' => [],
// 定义依赖项
'depend' => [
'field' => 'target_type',
'value' => [],
],
// col 布局规则 http://www.form-create.com/v2/element-ui/col.html
'col' => [
// 表单长度
'span' => 12,
// 标签宽度
'labelWidth' => 150,
],
// 动态修改其他字段规则 详见下方联动小节
'compute' => [
"will_set_field" => [
"when" => ['=', 1],
"set" => [
//
]
]
],
// 该字段规则回调方法,可以用于重置字段规则
'render' => function () {
},
// 开启input框的复制功能
'copy_show' => true,
],
];
}
```
## 列表定义
```php
public function scaffoldOptions()
{
return [
....
// 非必须项, 没有定义则从form转义
'columns' => [
'字段名', // 简写模式, 直接从form配置转义
[
'field' => 'mall_name',
'title' => '店铺',
// 字段渲染规则,默认为空
'type' => '',
// 是否虚拟字段虚拟字段在查询脚手架model时会忽略该字段
'virtual_field' => true,
// 表头说明
'info' => '括号内为商家承担',
// 定义该字段显示在哪些tab选项中
'depend' => [
'tab' => [(string)Coupon::TYPE_MALL_MONEY_OFF],
],
// 按字段升降查询功能
'sortable' => true,
// 是否允许编辑,调用*/rowchange/:id接口
'edit' => true,
// 枚举值可以options中的数据转换成Tag显示效果https://element.eleme.cn/#/zh-CN/component/tag
'options' => [],
'enum' => [ // tag 的 type 类型, 参见 element 标签
0 => 'info',
1 => 'success',
],
// 单独处理某个字段
'render' => function($val, $row) { return $val;}
],
],
];
}
```
## 按钮
`rowActions`, `topButtons`, `topActions`, `notices.*.actions` 的节点定义
1. 页面跳转
```php
[
'type' => 'jump',
'target' => '/crontab/{id}', // 本地路由或三方地址
'text' => '编辑',
'props' => [] // element el-button 的属性
]
```
2. 请求后端api
```php
[
'type' => 'api',
'target' => '/resource/delete', // 支持变量替换
'text' => '删除',
'method' => 'POST', // 默认POST
'props' => [
'type' => 'danger',
],
// 当前按钮可以定义依赖条件, 动态显示
'when' => [
['gid', '=', Resource::RESOURCE_ROOT_ID]
]
],
```
3. model弹窗表单
```php
// 直接定义表单规则 rules
[
'action' => 'module',
'target' => '/user/test/{id}',
'text' => '弹窗',
// rules 的定义同 form rule
'rules' => [
'file|视频' => [
'type' => 'file',
],
],
]
// 调用其他Controller form表单
[
'action' => 'module',
// 若没有rules节点则自定调用 target 接口拉取表单配置
'target' => '/user/form',
'text' => '弹窗',
]
// 调用其他 Controller 的列表
[
'type' => 'table',
'target' => '',
'props' => [
'listApi' => '/role/list?id={id}',
'infoApi' => '/role/info',
'options' => [
'showFilter' => false,
'createAble' => false
]
],
'text' => '**记录',
]
```
按钮较多时均可调整为按钮组
```php
[
[
$action_conf1,
$action_conf2
]
]
```
## 关联数据
```php
public function scaffoldOptions()
{
return [
....
// 一对一关系
'hasOne' => [
// 此处定义了补充的第三方数据是什么, 从哪里取
// [pool.]db.table:[local_key->]foreign_key,other_key
'hyperf_admin.hyperf_admin.user_role:id->user_id,role_id', // 完整定义
'hyperf_admin.user_role:id->user_id,role_id', // 缺省 pool
'hyperf_admin.user_role:user_id,role_id', // 缺省 pool,local_key
'hyperf_admin.user_role:user_id,role_id as rid', // 补充字段使用别名, 避免覆盖list中同名字段
],
// 一对多或多对多关系
'hasMany' => [
'hyperf_admin.hyperf_admin.operator_log:id->user_id,username'
]
];
}
```
`[pool.]db.table:[local_key->]foreign_key,other_key`
分别对应`连接池`(非必须, 默认dfault), `库名`, `表名`, `本地关联字段`(非必须, 默认id), `逻辑外键`, `其他要补充的字段`, 若系统为查询到第三方数据, 相应的补充字段将初始为 `null`
## 页面提示
```php
public function scaffoldOptions()
{
return [
....
// 页面提示信息
'notices' => [
[
'type' => 'warning',
'message' => '提示信息',
'actionsPlacement' => 'right',
'closable' => true,
'actions' => [], // 按钮
'when' => function($filters) { return true;}
]
]
];
}
```

View File

@@ -0,0 +1,132 @@
支持 列操作按钮, 批量操作按钮, 列表页顶部按钮
### 基础属性
```php
[
"text" => "", //按钮文案
"type" => "jump", // 按钮类型 默认 jump, 可选 form, api
"target" => "", // 动作目标 本地路由, 网址, 后端api
"props" => [ // 按钮属性, 更多可见 https://element.eleme.io/#/zh-CN/component/button
"icon" => "", // 按钮图标 默认无
"circle" => false, // 圆角 默认false
"size" => "small", // 默认 small, 可选 medium / small / mini
"type" => "info", //默认text, primary / success / warning / danger / info / text
],
"when" => [ // 当前按钮的显示条件, 默认无
["field_1", "=", 1] // filter过滤的比对数据为当前行 或者 当前页面基础数据
]
]
// 除以上基础属性外, 根据按钮类型, 也会有其他额外属性, 具体见下面
```
#### 普通跳转按钮
```javascript
[
"text" => "编辑",
"target" => "/user/12"
]
// or
[
"text" => "文档",
"target" => "http://hyperf.wiki"
]
```
#### 动作按钮(请求后端API)
点击按钮后, 提示二次确认, 确认后请求后端api
```javascript
[
"text" => "删除",
"target" => "/user/12",
"method" => "POST", // 请求api的方式, 默认POST
]
```
#### 表单型按钮
点击按钮后将以弹窗形式渲染指定表单, 然后搜集后端数据请求到指定api
```javascript
[
"text" => "审核通过",
"target" => "/user/12",
"method" => "POST", // 请求api的方式, 默认POST
"rules" => [ // 表单的rule规则具体参见表单部分
"reason|原因" => [
"rule" => "required"
]
]
]
// 有联动时
[
"text" => "审核通过",
"target" => "/user/12",
"method" => "POST", // 请求api的方式, 默认POST
"rules" => [
// 待补充
]
]
// or
[
"text" => "审核通过",
"target" => "/user/form", // get 方式拉取表单配置, post 方式保存数据
"method" => "POST", // 请求api的方式, 默认POST
]
```
#### 列表型按钮
点击按钮后将以弹窗的形式渲染指定列表
```php
[
'type' => 'table', // 调用 src/components/Scaffold/tablist.vue 渲染
'target' => '', // target 留空
'props' => [
'listApi' => '/merchantlog/list?merchant_id={id}', // 列表数据拉取接口
'infoApi' => '/merchantlog/info', // 列表 配置拉取接口
'options' => [ // 表单的配置项
'showFilter' => false,
'createAble' => false
]
],
'text' => '招商记录',
]
```
抽屉型按钮
点击按钮后将打开抽屉, 抽屉内部指定动态调用指定组件
```php
[
'type' => 'drawer',
'target' => '', // target 留空
'text' => '查看日志',
'props' => [
'component' => 'SocketList', // 需动态调用的组件 src/components/Common 下
'componentProps' => [ // 组件的 props
'url' => env('OMS_WEBSOCKET_URL') . '/cronlog?name={name}'
],
// drawer** 为抽屉属性的定义
// 详见 https://element.eleme.io/#/zh-CN/component/drawer
'drawerWithHeader' => false,
'drawerSize' => '80%',
'drawerTitle' => '{title}日志',
'drawerDirection' => 'ttb'
]
]
```
### SuperButtonGroup 下拉按钮
上面 SuperButton 的结构改为数组形式即可