mirror of
http://124.126.16.154:8888/singularity/hyperf-admin.git
synced 2026-01-15 03:35:07 +08:00
feat: hyperf-admin init
This commit is contained in:
0
docs/.nojekyll
Normal file
0
docs/.nojekyll
Normal file
34
docs/README.md
Normal file
34
docs/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
`hyperf-admin`是前后端分离的后台管理系统, 前端基于`vue`的 `vue-admin-template`, 针对后台业务`列表`, `表单`等场景封装了大量业务组件, 后端基于`hyperf`实现, 整体思路是后端定义页面渲染规则, 前端页面渲染时首先拉取配置, 然后组件根据具体配置完成页面渲染, 方便开发者仅做少量的配置工作就能完成常见的`CRUD`工作, 同时支持自定义组件和自定义页面, 以开发更为复杂的页面.
|
||||
|
||||

|
||||
|
||||
前端为`vue multiple page`多页模式, 可以按模块打包, 默认包含两个模块`default` 默认模块, `system`系统管理模块, 绝大部分业务组件在`src/components`目录, 前端文档详见 [这里](/frontend/)
|
||||
|
||||
后端为`composer包`模式, 目前包含组件
|
||||
|
||||
- 基础组件
|
||||
- `composer require hyperf-admin/base-utils` hyperf-admin的基础组件包, 脚手架主要功能封装
|
||||
- `composer require hyperf-admin/validation` 参数验证包, 对规则和参数提示做了较多优化
|
||||
- `composer require hyperf-admin/alert-manager` 企微/钉钉机器人报警包
|
||||
- `composer require hyperf-admin/rule-engine` 规则引擎
|
||||
- `composer require hyperf-admin/event-bus` mq/nsq/kafka消息派发器
|
||||
- `composer require hyperf-admin/process-manager` 进程管理组件
|
||||
- 业务组件 (业务组件为包含特定业务功能的包)
|
||||
- `composer require hyperf-admin/admin` 系统管理业务包
|
||||
- `composer require hyperf-admin/dev-tools` 开发者工具包, 主要是代码生成, 辅助开发
|
||||
- `composer require hyperf-admin/cron-center` 定时任务管理, 后台化管理任务
|
||||
- `composer require hyperf-admin/data-focus` 数据面板模块, 帮你快速制作数据大盘
|
||||
|
||||
后端的详细文档见[这里](/backend/)
|
||||
|
||||
## 依赖 & 参考
|
||||
|
||||
- 前端
|
||||
- [Vue](https://github.com/vuejs/vue)
|
||||
- [ElementUI](https://github.com/ElemeFE/element)
|
||||
- [FormCreate](http://www.form-create.com/v2/guide)
|
||||
- [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||
- [Vue 渲染函数 & JSX](https://cn.vuejs.org/v2/guide/render-function.html)
|
||||
- 后端
|
||||
- [Hyperf](http://hyperf.wiki/)
|
||||
- [Swoole](http://wiki.swoole.com)
|
||||
12
docs/_coverpage.md
Normal file
12
docs/_coverpage.md
Normal file
@@ -0,0 +1,12 @@
|
||||

|
||||
|
||||
# docsify
|
||||
|
||||
> A magical documentation site generator.
|
||||
|
||||
* Simple and lightweight (~12kb gzipped)
|
||||
* Multiple themes
|
||||
* Not build static html files
|
||||
|
||||
[GitHub](https://github.com/docsifyjs/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
0
docs/_navbar.md
Normal file
0
docs/_navbar.md
Normal file
21
docs/_sidebar.md
Normal file
21
docs/_sidebar.md
Normal file
@@ -0,0 +1,21 @@
|
||||
* 入门
|
||||
* [介绍](guide/desc.md)
|
||||
* [安装](guide/install.md)
|
||||
* [开发样例](guide/dev_example.md)
|
||||
* 后端
|
||||
* [脚手架](backend/scaffold.md)
|
||||
* [表单详解](backend/form.md)
|
||||
* [列表详解](backend/list.md)
|
||||
* [按钮详解](backend/super-button.md)
|
||||
* [通用配置](backend/common-config.md)
|
||||
* [辅助函数](backend/functions.md)
|
||||
* 业务组件
|
||||
* [DevTools-开发者工具](backend/components/dev-tools.md)
|
||||
* [DataFocus-数据面板](backend/components/data-focus.md)
|
||||
* [CronCenter-任务中心](backend/components/cron-center.md)
|
||||
* [开发一个业务组件](backend/make_component.md)
|
||||
* 前端
|
||||
* [表单](frontend/form.md)
|
||||
* [列表](frontend/list.md)
|
||||
* [图表](frontend/chart.md)
|
||||
|
||||
38
docs/backend/common-config.md
Normal file
38
docs/backend/common-config.md
Normal file
@@ -0,0 +1,38 @@
|
||||
通用配置在只需要使用表单搜集信息, 没有过多业务逻辑和校验规则时使用, 可以无需开发, 完成表单的定义和使用
|
||||
|
||||
1. 定义表单 http://localhost:9528/system/#/cconf/list, 此处表单规则同控制器中的form定义
|
||||
|
||||

|
||||
|
||||
2. 投放表单, 创建 `/***/cconf_{1中的表单名称}` 即可通过该路由访问
|
||||
|
||||

|
||||
|
||||
3. 访问 http://localhost:9528/hyperf/#/lucky/cconf_lucky_round
|
||||
|
||||

|
||||
|
||||
数据存储位置`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`获取相应的提交数据
|
||||
7
docs/backend/components/cron-center.md
Normal file
7
docs/backend/components/cron-center.md
Normal 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)
|
||||
97
docs/backend/components/data-focus.md
Normal file
97
docs/backend/components/data-focus.md
Normal 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
|
||||
11
docs/backend/components/dev-tools.md
Normal file
11
docs/backend/components/dev-tools.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## 代码自动生成工具
|
||||
|
||||
针对 数据库, `Model`, `Controller` 通用模型, 可以使用后台提供的`代码生成工具`来初始化大部分代码.
|
||||
|
||||

|
||||
|
||||
连接池对应`config.autoload.databases` 中配置的可用链接, 选择好`连接池`, `数据库`, `表` 后下方表单会根据表结构字段渲染, 完成具体字段的配置, 点击提交.
|
||||
|
||||

|
||||
|
||||
相应的`Modle`, `Controller` 便已创建成功.
|
||||
430
docs/backend/form.md
Normal file
430
docs/backend/form.md
Normal 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",
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
示例效果:
|
||||
|
||||

|
||||
|
||||
### 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,
|
||||
],
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
示例效果:
|
||||
|
||||

|
||||
|
||||
### 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
78
docs/backend/functions.md
Normal 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
571
docs/backend/list.md
Normal file
@@ -0,0 +1,571 @@
|
||||

|
||||
|
||||
```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"></i>
|
||||
|
||||
### image
|
||||
|
||||
**渲染条件**: `'type' => 'image'`,数据为数组时可以渲染多张图片
|
||||
|
||||
**效果展示**:
|
||||
|
||||
#### extrude
|
||||
|
||||
**用法**:
|
||||
|
||||
```php
|
||||
[
|
||||
"field" => "field_1",
|
||||
"type" => 'extrude',
|
||||
"render" => function($field_value, $row) {
|
||||
// return "<优惠券|balck|yellow>*****"; 单个
|
||||
// or 支持多个
|
||||
return [
|
||||
"<优惠券{replace_field}|balck|yellow>*****{replace_field}"
|
||||
]; // 格式 <文字|背景色|文字色>, 支持前端变量替换
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**效果展示**:
|
||||
|
||||
### tag
|
||||
|
||||
**用法**:
|
||||
|
||||
```php
|
||||
[
|
||||
"field" => "field_1",
|
||||
"options" => [
|
||||
0 => '禁用',
|
||||
1 => '启用',
|
||||
],
|
||||
"enum" => [ // tag 样式, 参见 https://element.eleme.io/#/zh-CN/component/tag
|
||||
0 => 'info',
|
||||
1 => 'success'
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
**效果展示**:
|
||||
|
||||
### 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"
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
**效果展示**:
|
||||
|
||||
### 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]
|
||||
]
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
**效果展示**:
|
||||
|
||||
### progress
|
||||
|
||||
**用法**:
|
||||
|
||||
```php
|
||||
[
|
||||
'field' => 'sync_progress',
|
||||
'title' => '同步进度',
|
||||
'type' => 'progress',
|
||||
// 'props' => []
|
||||
]
|
||||
```
|
||||
|
||||
> props里是progress组件的属性配置,请参考[Progress 进度条](https://element.eleme.cn/#/zh-CN/component/progress#attributes)
|
||||
|
||||
**效果展示**:
|
||||
|
||||
|
||||
## 搜索项
|
||||
|
||||
```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],
|
||||
],
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
**效果展示**:
|
||||
|
||||
## 操作按钮
|
||||
|
||||
支持 列操作按钮, 批量操作按钮, 列表页顶部按钮,前端组件为`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
408
docs/backend/scaffold.md
Normal 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;}
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
```
|
||||
132
docs/backend/super-button.md
Normal file
132
docs/backend/super-button.md
Normal 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 的结构改为数组形式即可
|
||||
BIN
docs/favicon.ico
Normal file
BIN
docs/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
1
docs/frontend/chart.md
Normal file
1
docs/frontend/chart.md
Normal file
@@ -0,0 +1 @@
|
||||
图表
|
||||
1
docs/frontend/form.md
Normal file
1
docs/frontend/form.md
Normal file
@@ -0,0 +1 @@
|
||||
表单
|
||||
1
docs/frontend/list.md
Normal file
1
docs/frontend/list.md
Normal file
@@ -0,0 +1 @@
|
||||
图表
|
||||
37
docs/guide/desc.md
Normal file
37
docs/guide/desc.md
Normal file
@@ -0,0 +1,37 @@
|
||||
`hyperf-admin`是前后端分离的后台管理系统, 前端基于`vue`的 `vue-admin-template`, 针对后台业务`列表`, `表单`等场景封装了大量业务组件, 后端基于`hyperf`实现, 整体思路是后端定义页面渲染规则, 前端页面渲染时首先拉取配置, 然后组件根据具体配置完成页面渲染, 方便开发者仅做少量的配置工作就能完成常见的`CRUD`工作, 同时支持自定义组件和自定义页面, 以开发更为复杂的页面.
|
||||
|
||||
### 架构
|
||||
|
||||

|
||||
|
||||
前端为`vue multiple page`多页模式, 可以按模块打包, 默认包含两个模块`default` 默认模块, `system`系统管理模块, 绝大部分业务组件在`src/components`目录, 前端文档详见 [这里](/frontend/)
|
||||
|
||||
后端为`composer包`模式, 目前包含组件
|
||||
|
||||
- 基础组件
|
||||
- `composer require hyperf-admin/base-utils` hyperf-admin的基础组件包, 脚手架主要功能封装
|
||||
- `composer require hyperf-admin/validation` 参数验证包, 对规则和参数提示做了较多优化
|
||||
- `composer require hyperf-admin/alert-manager` 企微/钉钉机器人报警包
|
||||
- `composer require hyperf-admin/rule-engine` 规则引擎
|
||||
- `composer require hyperf-admin/event-bus` mq/nsq/kafka消息派发器
|
||||
- `composer require hyperf-admin/process-manager` 进程管理组件
|
||||
- 业务组件 (业务组件为包含特定业务功能的包)
|
||||
- `composer require hyperf-admin/admin` 系统管理业务包
|
||||
- `composer require hyperf-admin/dev-tools` 开发者工具包, 主要是代码生成, 辅助开发
|
||||
- `composer require hyperf-admin/cron-center` 定时任务管理, 后台化管理任务
|
||||
- `composer require hyperf-admin/data-focus` 数据面板模块, 帮你快速制作数据大盘
|
||||
|
||||
后端的详细文档见[这里](/backend/)
|
||||
|
||||
### 依赖 & 参考
|
||||
|
||||
- 前端
|
||||
- [Vue](https://github.com/vuejs/vue)
|
||||
- [ElementUI](https://github.com/ElemeFE/element)
|
||||
- [FormCreate](http://www.form-create.com/v2/guide)
|
||||
- [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||
- [Vue 渲染函数 & JSX](https://cn.vuejs.org/v2/guide/render-function.html)
|
||||
- 后端
|
||||
- [Hyperf](http://hyperf.wiki/)
|
||||
- [Swoole](http://wiki.swoole.com)
|
||||
|
||||
119
docs/guide/dev_example.md
Normal file
119
docs/guide/dev_example.md
Normal file
@@ -0,0 +1,119 @@
|
||||
我们通过一个具体案例, 来看看如何应用`hyperf-admin`快速实现
|
||||
|
||||
### 1.需求描述
|
||||
|
||||
实现一个某校年级内各班级学生的各科成绩管理后台, 要求如下
|
||||
|
||||
1. 列表显示学生 年级,班级,学习,学科,成绩,时间,性别,年龄
|
||||
2. 可以按成绩 倒序/正序排列
|
||||
3. 可以批量导入/导出学生成绩
|
||||
4. 可以通过 年级,学生名称,班级 等条件筛选
|
||||
5. 最好列表可以分页签直接显示各科成绩
|
||||
6. 没有原型图
|
||||
|
||||
### 2. 数据库定义
|
||||
|
||||
这里不做太复杂的设计, 仅用一张表来完成此需求
|
||||
|
||||
```sql
|
||||
CREATE TABLE `student_score` (
|
||||
`id` int(12) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`grade` tinyint(4) unsigned NOT NULL COMMENT '年级',
|
||||
`class` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '班级',
|
||||
`subject` tinyint(4) unsigned NOT NULL COMMENT '学科',
|
||||
`score` int(12) unsigned NOT NULL DEFAULT '0' COMMENT '分数',
|
||||
`name` varchar(10) NOT NULL DEFAULT '' COMMENT '学生名称',
|
||||
`sex` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '性别, 0女生, 1难受',
|
||||
`create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
```
|
||||
|
||||
接下来在`MySql`中创建表
|
||||
|
||||
### 3.功能开发
|
||||
|
||||
1. `hyperf`中添加db信息
|
||||
|
||||
```php
|
||||
// config/autoload/databases.php
|
||||
'local' => db_complete([
|
||||
'host' => '127.0.0.1',
|
||||
'database' => 'test',
|
||||
'username' => 'root',
|
||||
'password' => 'root'
|
||||
])
|
||||
```
|
||||
|
||||
2. 通过`DevTools`开发者工具创建 `student_score` 相关的 `Model`, `Controller`
|
||||
|
||||

|
||||
|
||||
选择好相应的表后, 点击提交, 此时工具已经帮我们创建好相应的`app/Controller/StudentScoreController.php`和`app/Model/Test/StudentScore.php`
|
||||
|
||||
3. 添加目录和菜单
|
||||
|
||||

|
||||
|
||||
注册路由
|
||||
|
||||
```php
|
||||
// config/routes.php
|
||||
register_route('/student_score', StudentScoreController::class);
|
||||
```
|
||||
|
||||
此时我们也已经完成了基础的`CRUD`开发
|
||||
|
||||

|
||||
|
||||
哦对了, 还有各种筛选条件呢? 也很简单, 在 `scaffoldOptions` 中增加 `filter`配置即可
|
||||
|
||||
```php
|
||||
public function scaffoldOptions()
|
||||
{
|
||||
return [
|
||||
'filter' => [
|
||||
'grade', 'class', 'subject', 'name%',
|
||||
'score|分数' => [
|
||||
'type' => 'input-range',
|
||||
'select_type' => 'between'
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
还有, 大家别忘了, 需求中还要去可以按页签显示, 改怎么办呢, 这个ui可有点复杂啊, 不过在`hyperf-admin`里也同样简单
|
||||
|
||||
`scaffoldOptions` 中增加 `table.tabs`配置即可
|
||||
|
||||
```php
|
||||
public function scaffoldOptions()
|
||||
{
|
||||
return [
|
||||
'table' => [
|
||||
'tabs' => [
|
||||
[
|
||||
'label' => '语文',
|
||||
'value' => 1,
|
||||
'icon' => 'el-icon-s-grid',
|
||||
],
|
||||
[
|
||||
'label' => '数学',
|
||||
'value' => 2,
|
||||
'icon' => 'el-icon-s-grid',
|
||||
],
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
至此我们已经完成了绝大部分的功能开发, 如果使用熟练, 我们应该能在十分钟内完成整个功能的前后端开发, 而且还支持复杂的前端效果.
|
||||
|
||||
?> 当然`hyperf-admin`还支持更多复杂的功能, 快快用你明亮的眼睛去发现他吧.
|
||||
39
docs/guide/install.md
Normal file
39
docs/guide/install.md
Normal file
@@ -0,0 +1,39 @@
|
||||
?> `hyperf-admin`目前尚未开源, 敬请期待.
|
||||
|
||||
## 前端
|
||||
|
||||
```shell
|
||||
# 环境依赖
|
||||
# 1. node ^v11.2.0 https://nodejs.org/zh-cn/download/
|
||||
# 2. npm ^6.4.1
|
||||
git clone https://github.com/hyperf-admin/hyperf-admin-front.git
|
||||
cd hyperf-admin-front
|
||||
npm i
|
||||
npm run dev
|
||||
```
|
||||
|
||||
!> 请根据实际情况修改`vue.config.js`中的代理 `proxy.target`地址
|
||||
|
||||
```shell
|
||||
# 打包
|
||||
npm run build:prod
|
||||
npm run build:test
|
||||
```
|
||||
|
||||
## 后端
|
||||
|
||||
```shell
|
||||
# 环境依赖 php ^7.1 composer swoole
|
||||
# 下载demo项目
|
||||
git clone https://github.com/hyperf-admin/hyperf-admin-skeleton.git
|
||||
cd hyperf-admin-skeleton
|
||||
composer i
|
||||
# 启动
|
||||
composer watch
|
||||
```
|
||||
|
||||
## nginx配置
|
||||
|
||||
```nginx
|
||||
# conf
|
||||
```
|
||||
63
docs/index.html
Normal file
63
docs/index.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>hyperf-admin</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="description" content="Description">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
|
||||
<link rel="shortcut icon" type="image/icon" href="/favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
name: 'hyperf-admin',
|
||||
//logo: '/logo.png',
|
||||
repo: 'https://github.com/hyperf-admin',
|
||||
//coverpage: true, // 开启封面
|
||||
loadNavbar: true,
|
||||
loadSidebar: true,
|
||||
maxLevel: 4,
|
||||
subMaxLevel: 3,
|
||||
autoHeader: true,
|
||||
search: {
|
||||
maxAge: 86400000, // 过期时间,单位毫秒,默认一天
|
||||
paths: 'auto', // or 'auto'
|
||||
placeholder: 'Type to search'
|
||||
},
|
||||
plugins: [
|
||||
function (hook, vm) {
|
||||
hook.beforeEach(function (html) {
|
||||
if (/githubusercontent\.com/.test(vm.route.file)) {
|
||||
url = vm.route.file
|
||||
.replace('raw.githubusercontent.com', 'github.com')
|
||||
.replace(/\/master/, '/blob/master')
|
||||
} else {
|
||||
url = 'https://github.com/hyperf-admin/hyperf-admin.github.io/edit/master/' + vm.route.file
|
||||
}
|
||||
var editHtml = '[:memo: 编辑文档!](' + url + ') '
|
||||
|
||||
return html
|
||||
+ '\n\n----\n\n'
|
||||
+ editHtml
|
||||
+ '<a href="https://docsify.js.org" target="_blank" style="color: inherit; font-weight: normal; text-decoration: none;">Powered by docsify</a>'
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
if (typeof navigator.serviceWorker !== 'undefined') {
|
||||
navigator.serviceWorker.register('https://raw.githubusercontent.com/hyperf-admin/hyperf-admin.github.io/master/ws.js')
|
||||
}
|
||||
</script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-bash.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-php.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-json.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-sql.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
||||
<script src="//unpkg.com/docsify-copy-code"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/zoom-image.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/logo.png
Normal file
BIN
docs/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
83
docs/ws.js
Normal file
83
docs/ws.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/* ===========================================================
|
||||
* docsify sw.js
|
||||
* ===========================================================
|
||||
* Copyright 2016 @huxpro
|
||||
* Licensed under Apache 2.0
|
||||
* Register service worker.
|
||||
* ========================================================== */
|
||||
|
||||
const RUNTIME = 'docsify'
|
||||
const HOSTNAME_WHITELIST = [
|
||||
self.location.hostname,
|
||||
'fonts.gstatic.com',
|
||||
'fonts.googleapis.com',
|
||||
'cdn.jsdelivr.net'
|
||||
]
|
||||
|
||||
// The Util Function to hack URLs of intercepted requests
|
||||
const getFixedUrl = (req) => {
|
||||
var now = Date.now()
|
||||
var url = new URL(req.url)
|
||||
|
||||
// 1. fixed http URL
|
||||
// Just keep syncing with location.protocol
|
||||
// fetch(httpURL) belongs to active mixed content.
|
||||
// And fetch(httpRequest) is not supported yet.
|
||||
url.protocol = self.location.protocol
|
||||
|
||||
// 2. add query for caching-busting.
|
||||
// Github Pages served with Cache-Control: max-age=600
|
||||
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
|
||||
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
|
||||
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
|
||||
if (url.hostname === self.location.hostname) {
|
||||
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
|
||||
}
|
||||
return url.href
|
||||
}
|
||||
|
||||
/**
|
||||
* @Lifecycle Activate
|
||||
* New one activated when old isnt being used.
|
||||
*
|
||||
* waitUntil(): activating ====> activated
|
||||
*/
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(self.clients.claim())
|
||||
})
|
||||
|
||||
/**
|
||||
* @Functional Fetch
|
||||
* All network requests are being intercepted here.
|
||||
*
|
||||
* void respondWith(Promise<Response> r)
|
||||
*/
|
||||
self.addEventListener('fetch', event => {
|
||||
// Skip some of cross-origin requests, like those for Google Analytics.
|
||||
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
|
||||
// Stale-while-revalidate
|
||||
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
|
||||
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
|
||||
const cached = caches.match(event.request)
|
||||
const fixedUrl = getFixedUrl(event.request)
|
||||
const fetched = fetch(fixedUrl, { cache: 'no-store' })
|
||||
const fetchedCopy = fetched.then(resp => resp.clone())
|
||||
|
||||
// Call respondWith() with whatever we get first.
|
||||
// If the fetch fails (e.g disconnected), wait for the cache.
|
||||
// If there’s nothing in cache, wait for the fetch.
|
||||
// If neither yields a response, return offline pages.
|
||||
event.respondWith(
|
||||
Promise.race([fetched.catch(_ => cached), cached])
|
||||
.then(resp => resp || fetched)
|
||||
.catch(_ => { /* eat any errors */ })
|
||||
)
|
||||
|
||||
// Update the cache with the version we fetched (only for ok status)
|
||||
event.waitUntil(
|
||||
Promise.all([fetchedCopy, caches.open(RUNTIME)])
|
||||
.then(([response, cache]) => response.ok && cache.put(event.request, response))
|
||||
.catch(_ => { /* eat any errors */ })
|
||||
)
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user