├── .babelrc ├── .gitignore ├── .styleci.yml ├── LICENSE ├── changelog.md ├── composer.json ├── config └── admin.php ├── contributing.md ├── database └── migrations │ └── 2020_01_14_173148_create_admin_tables.php ├── docs ├── .nojekyll ├── 1.x │ ├── form │ │ ├── component.md │ │ ├── index.md │ │ └── item.md │ ├── grid │ │ ├── actions.md │ │ ├── batchActions.md │ │ ├── column.md │ │ ├── display.md │ │ ├── filters.md │ │ ├── index.md │ │ ├── quickSearch.md │ │ ├── relevance.md │ │ ├── tools.md │ │ └── treeGrid.md │ ├── index.md │ ├── installation.md │ ├── overview.md │ └── update.md ├── README.assets │ ├── image-20200313103804881.png │ ├── image-20200313105015399.png │ ├── image-20200313112129545.png │ ├── laravel-vue-admin-logo.png │ ├── logo-1584436939847.png │ └── logo.png ├── README.md ├── _sidebar.md ├── assets │ ├── image-20200509104115665.png │ └── image-20200509104203063.png ├── components.assets │ ├── image-20200313102505193.png │ ├── image-20200330135556270.png │ ├── image-20200330135622182.png │ ├── image-20200330151604231.png │ ├── image-20200330154928558.png │ ├── image-20200330154940875.png │ ├── image-20200330161859300.png │ ├── image-20200330162019246.png │ ├── image-20200331141335210.png │ ├── image-20200331142220245.png │ ├── image-20200331154059916.png │ └── image-20200331154547211.png ├── components.md ├── content.md ├── custom.assets │ ├── image-20200313100328876.png │ ├── image-20200313101225595.png │ └── image-20200402153922198.png ├── custom.md ├── form.md ├── frontend.md ├── grid.assets │ ├── image-20200313093443485.png │ └── image-20200313093513048.png ├── grid.md ├── index.html └── thirdparty.md ├── mix-manifest.json ├── package-lock.json ├── package.json ├── phpunit.xml ├── public ├── 0.js ├── 0.js.LICENSE.txt ├── 1.js ├── 10.js ├── 11.js ├── 2.js ├── 3.js ├── 4.js ├── 5.js ├── 6.js ├── 7.js ├── 8.js ├── 9.js ├── app.js ├── app.js.LICENSE.txt ├── fonts │ └── vendor │ │ ├── element-ui │ │ └── lib │ │ │ └── theme-chalk │ │ │ ├── element-icons.ttf │ │ │ └── element-icons.woff │ │ └── mavon-editor │ │ └── dist │ │ ├── fontello.eot │ │ ├── fontello.svg │ │ ├── fontello.ttf │ │ ├── fontello.woff │ │ └── fontello.woff2 ├── images │ ├── 404.png │ ├── logo-light.svg │ ├── logo-mini-light.svg │ ├── logo-mini.svg │ ├── logo.svg │ ├── menu-dark.svg │ ├── menu-light.svg │ ├── nav-dark.svg │ └── nav-light.svg ├── manifest.js ├── mix-manifest.json ├── vendor.js └── vendor.js.LICENSE.txt ├── readme.md ├── resources ├── js │ ├── Admin.js │ ├── app.js │ ├── assets │ │ ├── 404.png │ │ ├── logo-light.svg │ │ ├── logo-mini-light.svg │ │ ├── logo-mini.svg │ │ ├── logo.svg │ │ ├── menu-dark.svg │ │ ├── menu-light.svg │ │ ├── nav-dark.svg │ │ └── nav-light.svg │ ├── components.js │ ├── components │ │ ├── 404.vue │ │ ├── Login.vue │ │ ├── Root.vue │ │ ├── antv │ │ │ ├── AntvArea.vue │ │ │ ├── AntvColumn.vue │ │ │ ├── AntvLine.vue │ │ │ └── AntvStepLine.vue │ │ ├── form │ │ │ ├── BaseForm.vue │ │ │ ├── Form.vue │ │ │ ├── FormItem.vue │ │ │ ├── ItemDisplay.vue │ │ │ └── ItemIf.vue │ │ ├── grid │ │ │ ├── Actions │ │ │ │ ├── Action.vue │ │ │ │ ├── Index.vue │ │ │ │ └── TreeAction.vue │ │ │ ├── BatchActions │ │ │ │ └── Index.vue │ │ │ ├── Column.vue │ │ │ ├── ColumnDisplay.vue │ │ │ ├── DialogForm.vue │ │ │ ├── Table.vue │ │ │ ├── Tree.vue │ │ │ └── TreeColumnDisplay.vue │ │ ├── layout │ │ │ ├── Base.vue │ │ │ ├── Column.vue │ │ │ ├── Content.vue │ │ │ ├── MenuItem.vue │ │ │ └── Row.vue │ │ └── widgets │ │ │ ├── Actions │ │ │ ├── ActionButton.vue │ │ │ ├── DeleteAction.vue │ │ │ ├── EditAction.vue │ │ │ └── VueRouteAction.vue │ │ │ ├── Base │ │ │ ├── Alert.vue │ │ │ ├── Badge.vue │ │ │ ├── Button.vue │ │ │ ├── Card.vue │ │ │ ├── DialogButton.vue │ │ │ ├── Divider.vue │ │ │ ├── Html.vue │ │ │ ├── Markdown.vue │ │ │ ├── Steps.vue │ │ │ ├── Text.vue │ │ │ └── Tooltip.vue │ │ │ ├── BatchActions │ │ │ └── BatchAction.vue │ │ │ ├── Form │ │ │ ├── Cascader.vue │ │ │ ├── Checkbox.vue │ │ │ ├── CheckboxGroup.vue │ │ │ ├── ColorPicker.vue │ │ │ ├── DatePicker.vue │ │ │ ├── DateTimePicker.vue │ │ │ ├── IconChoose.vue │ │ │ ├── Input.vue │ │ │ ├── InputNumber.vue │ │ │ ├── ItemSelect.vue │ │ │ ├── RadioGroup.vue │ │ │ ├── Rate.vue │ │ │ ├── Select.vue │ │ │ ├── Slider.vue │ │ │ ├── Switch.vue │ │ │ ├── TimePicker.vue │ │ │ ├── Transfer.vue │ │ │ ├── Upload.vue │ │ │ └── WangEditor.vue │ │ │ ├── Grid │ │ │ ├── Avatar.vue │ │ │ ├── Boole.vue │ │ │ ├── GridRoute.vue │ │ │ ├── Icon.vue │ │ │ ├── Image.vue │ │ │ ├── Link.vue │ │ │ └── Tag.vue │ │ │ ├── Tools │ │ │ ├── Create.vue │ │ │ └── ToolButton.vue │ │ │ └── common │ │ │ └── affix.vue │ ├── mixins.js │ ├── router │ │ ├── index.js │ │ └── routes.js │ ├── settings.js │ ├── store │ │ ├── getters.js │ │ ├── index.js │ │ └── modules │ │ │ ├── app.js │ │ │ └── settings.js │ ├── styles │ │ ├── admin.scss │ │ ├── base.scss │ │ ├── element-ui.scss │ │ ├── mixin.scss │ │ ├── sidebar.scss │ │ ├── transition.scss │ │ └── variables.scss │ ├── util │ │ ├── axios.js │ │ ├── dom.js │ │ └── validate.js │ └── utils.js ├── lang │ ├── en │ │ └── admin.php │ └── zh-CN │ │ └── admin.php └── views │ ├── content.blade.php │ ├── form │ └── base-form.blade.php │ ├── grid │ └── table.blade.php │ ├── layouts │ └── base.blade.php │ ├── login.blade.php │ ├── partials │ └── css.blade.php │ └── root.blade.php ├── routes └── route.php ├── src ├── Actions │ ├── BaseAction.php │ └── BaseRowAction.php ├── Admin.php ├── AdminServiceProvider.php ├── Auth │ ├── Database │ │ ├── AdminTablesSeeder.php │ │ ├── Administrator.php │ │ ├── HasPermissions.php │ │ ├── Menu.php │ │ ├── OperationLog.php │ │ ├── Permission.php │ │ └── Role.php │ └── Permission.php ├── Components │ ├── Antv │ │ ├── Area.php │ │ ├── Column.php │ │ ├── Line.php │ │ └── StepLine.php │ ├── Attrs │ │ ├── Button.php │ │ ├── CascaderOption.php │ │ ├── CascaderProps.php │ │ ├── Depend.php │ │ ├── ElDialog.php │ │ ├── ElLink.php │ │ ├── SelectOption.php │ │ ├── Step.php │ │ └── TransferData.php │ ├── Component.php │ ├── Form │ │ ├── CSwitch.php │ │ ├── Cascader.php │ │ ├── Checkbox.php │ │ ├── CheckboxGroup.php │ │ ├── ColorPicker.php │ │ ├── DatePicker.php │ │ ├── DateTimePicker.php │ │ ├── IconChoose.php │ │ ├── Input.php │ │ ├── InputNumber.php │ │ ├── ItemSelect.php │ │ ├── Radio.php │ │ ├── RadioGroup.php │ │ ├── Rate.php │ │ ├── Select.php │ │ ├── Slider.php │ │ ├── TimePicker.php │ │ ├── Transfer.php │ │ ├── Upload.php │ │ └── WangEditor.php │ ├── Grid │ │ ├── Avatar.php │ │ ├── Boole.php │ │ ├── Icon.php │ │ ├── Image.php │ │ ├── Link.php │ │ ├── Route.php │ │ └── Tag.php │ ├── GridComponent.php │ └── Widgets │ │ ├── Alert.php │ │ ├── Badge.php │ │ ├── BaseForm.php │ │ ├── Button.php │ │ ├── Card.php │ │ ├── Dialog.php │ │ ├── DialogButton.php │ │ ├── Divider.php │ │ ├── Html.php │ │ ├── Markdown.php │ │ ├── Steps.php │ │ ├── Text.php │ │ └── Tooltip.php ├── Console │ ├── AcceptsNameAndVendor.php │ ├── ExtendCommand.php │ ├── FormItemCommand.php │ ├── InstallCommand.php │ ├── extend-stubs │ │ ├── .gitignore │ │ ├── composer.json │ │ ├── package.json │ │ ├── resources │ │ │ ├── js │ │ │ │ └── extend.js │ │ │ └── sass │ │ │ │ └── extend.scss │ │ ├── routes │ │ │ └── route.php │ │ ├── src │ │ │ └── ExtendServiceProvider.stub │ │ └── webpack.mix.js │ ├── form-item-stubs │ │ ├── .gitignore │ │ ├── composer.json │ │ ├── package.json │ │ ├── resources │ │ │ ├── js │ │ │ │ ├── components │ │ │ │ │ └── FormItem.vue │ │ │ │ └── form-item.js │ │ │ └── sass │ │ │ │ └── form-item.scss │ │ ├── src │ │ │ ├── FormItem.stub │ │ │ └── FormItemServiceProvider.stub │ │ └── webpack.mix.js │ └── stubs │ │ ├── AuthController.stub │ │ ├── HomeController.stub │ │ ├── bootstrap.stub │ │ └── routes.stub ├── Controllers │ ├── AdminController.php │ ├── AdminResource.php │ ├── AuthController.php │ ├── HandleController.php │ ├── HasResourceActions.php │ ├── LogController.php │ ├── MenuController.php │ ├── PermissionController.php │ ├── RoleController.php │ ├── RootController.php │ ├── ScriptController.php │ ├── StyleController.php │ └── UserController.php ├── Facades │ └── Admin.php ├── Form.php ├── Form │ ├── FormActions.php │ ├── FormAttrs.php │ ├── FormItem.php │ ├── FormTab.php │ ├── HasHooks.php │ ├── HasRef.php │ ├── Model.php │ ├── TraitFormAttrs.php │ └── Utils │ │ └── VIfEval.php ├── Grid.php ├── Grid │ ├── Actions.php │ ├── Actions │ │ ├── ActionButton.php │ │ ├── ActionLink.php │ │ ├── DeleteAction.php │ │ ├── EditAction.php │ │ └── VueRouteAction.php │ ├── BatchActions.php │ ├── BatchActions │ │ ├── BatchAction.php │ │ └── DeleteAction.php │ ├── Column.php │ ├── Column │ │ └── Attributes.php │ ├── Concerns │ │ ├── HasActions.php │ │ ├── HasColumnAttributes.php │ │ ├── HasDefaultSort.php │ │ ├── HasDialog.php │ │ ├── HasFilter.php │ │ ├── HasGridAttributes.php │ │ ├── HasPageAttributes.php │ │ └── HasQuickSearch.php │ ├── Filter.php │ ├── Filter │ │ ├── AbstractFilter.php │ │ ├── Between.php │ │ ├── Date.php │ │ ├── Day.php │ │ ├── EndsWith.php │ │ ├── Equal.php │ │ ├── Gt.php │ │ ├── Ilike.php │ │ ├── In.php │ │ ├── Like.php │ │ ├── Lt.php │ │ ├── Month.php │ │ ├── NotEqual.php │ │ ├── NotIn.php │ │ ├── Scope.php │ │ ├── StartsWith.php │ │ ├── Where.php │ │ └── Year.php │ ├── Model.php │ ├── Table │ │ └── Attributes.php │ ├── Toolbars.php │ └── Tools │ │ ├── CreateButton.php │ │ ├── QuickSearch.php │ │ └── ToolButton.php ├── Layout │ ├── Buildable.php │ ├── Column.php │ ├── Content.php │ └── Row.php ├── Middleware │ ├── Authenticate.php │ ├── Bootstrap.php │ ├── LogOperation.php │ ├── Permission.php │ └── Session.php ├── Traits │ ├── AdminBuilder.php │ ├── AdminJsonBuilder.php │ ├── HasAssets.php │ ├── ModelTree.php │ ├── Resizable.php │ └── ShouldSnakeAttributes.php └── helpers.php └── webpack.mix.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-syntax-dynamic-import" 4 | ] 5 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | node_modules/ 3 | npm-debug.log 4 | yarn-error.log 5 | 6 | # Laravel 4 specific 7 | bootstrap/compiled.php 8 | app/storage/ 9 | 10 | # Laravel 5 & Lumen specific 11 | public/storage 12 | public/hot 13 | 14 | # Laravel 5 & Lumen specific with changed public path 15 | public_html/storage 16 | public_html/hot 17 | 18 | storage/*.key 19 | .env 20 | Homestead.yaml 21 | Homestead.json 22 | /.vagrant 23 | /.vscode 24 | .phpunit.result.cache 25 | 26 | .idea/ 27 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: laravel -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 WeiZhang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `Admin` will be documented in this file. 4 | 5 | ## Version 1.0 6 | 7 | ### Added 8 | - Everything 9 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smallruraldog/laravel-vue-admin", 3 | "description": "开箱即用的Laravel后台扩展", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "zhang wei", 8 | "email": "thinktb@qq.com" 9 | } 10 | ], 11 | "homepage": "https://github.com/smallruraldog/admin", 12 | "keywords": [ 13 | "Laravel", 14 | "Admin", 15 | "Vue" 16 | ], 17 | "require": { 18 | "illuminate/support": "~5|~6|~7|~8" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "^8.0", 22 | "mockery/mockery": "^1.1", 23 | "orchestra/testbench": "~3|~4", 24 | "sempro/phpunit-pretty-print": "^1.0" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "SmallRuralDog\\Admin\\": "src/" 29 | }, 30 | "files": [ 31 | "src/helpers.php" 32 | ] 33 | }, 34 | "autoload-dev": { 35 | "psr-4": { 36 | "SmallRuralDog\\Admin\\Tests\\": "tests" 37 | } 38 | }, 39 | "extra": { 40 | "laravel": { 41 | "providers": [ 42 | "SmallRuralDog\\Admin\\AdminServiceProvider" 43 | ], 44 | "aliases": { 45 | "Admin": "SmallRuralDog\\Admin\\Facades\\Admin" 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are welcome and will be fully credited. 4 | 5 | Contributions are accepted via Pull Requests on [Github](https://github.com/smallruraldog/admin). 6 | 7 | # Things you could do 8 | If you want to contribute but do not know where to start, this list provides some starting points. 9 | - Add license text 10 | - Remove rewriteRules.php 11 | - Set up TravisCI, StyleCI, ScrutinizerCI 12 | - Write a comprehensive ReadMe 13 | 14 | ## Pull Requests 15 | 16 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests. 17 | 18 | - **Document any change in behaviour** - Make sure the `readme.md` and any other relevant documentation are kept up-to-date. 19 | 20 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. 21 | 22 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 23 | 24 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. 25 | 26 | 27 | **Happy coding**! 28 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/.nojekyll -------------------------------------------------------------------------------- /docs/1.x/form/component.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/1.x/form/component.md -------------------------------------------------------------------------------- /docs/1.x/grid/quickSearch.md: -------------------------------------------------------------------------------- 1 | ## 快捷搜索 2 | 快捷搜索是除了`filter`之外的另一个表格数据搜索方式,用来快速过滤你想要的数据,开启方式如下: 3 | 4 | ```php 5 | $grid->quickSearch(); 6 | ``` 7 | 这样表头会出现一个搜索框 8 | 9 | 通过给`quickSearch`方法传入不同的参数,来设置不同的搜索方式,有下面几种使用方法 10 | ### Like搜索 11 | 通过设置字段名称来进行简单的`like`查询 12 | ```php 13 | $grid->quickSearch('title'); 14 | // 提交后模型会执行下面的查询 15 | $model->where('title', 'like', "%{$input}%"); 16 | ``` 17 | 多个字段 18 | ```php 19 | $grid->quickSearch('title', 'desc', 'content'); 20 | 21 | // 提交后模型会执行下面的查询 22 | 23 | $model->where('title', 'like', "%{$input}%") 24 | ->orWhere('desc', 'like', "%{$input}%") 25 | ->orWhere('content', 'like', "%{$input}%"); 26 | ``` 27 | 更多用法可查看 [laravel-admin](https://laravel-admin.org/docs/zh/model-grid-quick-search) 28 | 29 | ### 设置搜索框占位符 30 | ```php 31 | $grid->quickSearchPlaceholder("占位符文字"); 32 | ``` -------------------------------------------------------------------------------- /docs/1.x/grid/relevance.md: -------------------------------------------------------------------------------- 1 | ## 关联模型 2 | 3 | 4 | 要显示关联模型的值,使用`.`来获取关联模型的值 5 | ### 一对一 6 | ```php 7 | $grid->column('permissions.name'); 8 | ``` 9 | ### 一对多 10 | 一对多最终得到的是数组,前端会自动循环展示,文本建议使用`Tag`组件,图片建议使用`Avatar`或`Image`组件 11 | ```php 12 | $grid->column('permissions.name')->component(Tag::make()->type('info')); 13 | ``` -------------------------------------------------------------------------------- /docs/1.x/grid/tools.md: -------------------------------------------------------------------------------- 1 | - [工具栏](#工具栏) 2 | - [创建按钮](#创建按钮) 3 | - [获取按钮对象](#获取按钮对象) 4 | - [隐藏创建按钮](#隐藏创建按钮) 5 | - [添加自定义工具](#添加自定义工具) 6 | - [组件](#组件) 7 | - [ToolButton](#toolbutton) 8 | 9 | 10 | ## 工具栏 11 | 12 | ```php 13 | $grid->toolbars(function (Grid\Toolbars $toolbars) { 14 | $toolbars->hideCreateButton(); 15 | $toolbars->createButton()->content("添加商品");//获取创建组件实例,修改属性 16 | }); 17 | ``` 18 | ## 创建按钮 19 | ### 获取按钮对象 20 | 详细属性请查看 [ui-button](https://element.eleme.cn/#/zh-CN/component/button) 组件 21 | ```php 22 | $toolbars->createButton(); 23 | $toolbars->createButton()->message("确认操作提示信息"); 24 | $toolbars->createButton()->tooltip("按钮气泡信息"); 25 | ``` 26 | ### 隐藏创建按钮 27 | ```php 28 | $toolbars->hideCreateButton() 29 | ``` 30 | 31 | ## 添加自定义工具 32 | 33 | ```php 34 | $toolbars->addLeft(ToolButton::make("自定义按钮"));//添加在左侧 35 | $toolbars->addRight(ToolButton::make("自定义按钮"));//添加在右侧 36 | ``` 37 | 38 | ## 组件 39 | 系统默认提供的操作组件 40 | ### ToolButton 41 | 详细属性请查看 [ui-button](https://element.eleme.cn/#/zh-CN/component/button) 组件 -------------------------------------------------------------------------------- /docs/1.x/grid/treeGrid.md: -------------------------------------------------------------------------------- 1 | ## 树形列表 2 | 3 | >用清晰的层级结构展示信息,可展开或折叠。 4 | 5 | 此功能必须满足以下几点才能正常使用,暂不支持分页,所以不建议展示大量的数据,后期会加入异步加载 6 | 7 | 定义一个 `hasMany`管理,名称为`children`,并预加载所有`children`,设置好排序 8 | 9 | ## 模型的定义 10 | ```php 11 | public function children() { 12 | return $this->hasMany(get_class($this), 'parent_id' )->orderBy('order')->with( 'children' ); 13 | } 14 | ``` 15 | ## 以下代码开启树形展示模式 16 | ```php 17 | $grid->model()->where('parent_id', 0);//设置查询条件 18 | $grid->tree();//启动树形表格 19 | $grid->rowKey('id');//设置rowKey,必须存在,默认为ID,如果你的Grid没有定义ID字段就要重新设置其他字段 20 | $grid->defaultExpandAll();//默认展开所有行 21 | ``` -------------------------------------------------------------------------------- /docs/1.x/index.md: -------------------------------------------------------------------------------- 1 | - ## 开始使用 2 | - [概述](/{{route}}/{{version}}/overview) 3 | - [安装](/{{route}}/{{version}}/installation) 4 | - [版本升级](/{{route}}/{{version}}/update) 5 | 6 | - ## 模型表格 7 | - [基本使用](/{{route}}/{{version}}/grid/index) 8 | - [列的使用](/{{route}}/{{version}}/grid/column) 9 | - [列的显示](/{{route}}/{{version}}/grid/display) 10 | - [查询过滤](/{{route}}/{{version}}/grid/filters) 11 | - [快捷搜索](/{{route}}/{{version}}/grid/quickSearch) 12 | - [数据行操作](/{{route}}/{{version}}/grid/actions) 13 | - [批量操作](/{{route}}/{{version}}/grid/batchActions) 14 | - [工具栏](/{{route}}/{{version}}/grid/tools) 15 | - [树形列表](/{{route}}/{{version}}/grid/treeGrid) 16 | - [模型关联](/{{route}}/{{version}}/grid/relevance) 17 | - ## 模型表单 18 | - [基本使用](/{{route}}/{{version}}/form/index) 19 | - [字段使用](/{{route}}/{{version}}/form/item) 20 | - [字段显示](/{{route}}/{{version}}/form/component) 21 | - [事件回调](/{{route}}/{{version}}/form/component) 22 | - [关联模型](/{{route}}/{{version}}/form/component) 23 | - ## 开发扩展 24 | - ## 页面组件 25 | - ## 权限控制 26 | - ## 其他 -------------------------------------------------------------------------------- /docs/1.x/installation.md: -------------------------------------------------------------------------------- 1 | # 安装 2 | --- 3 | - [安装环境](#1) 4 | - [开始安装](#2) 5 | 6 | 7 | ## 安装环境 8 | 9 | - PHP >= 7.1 10 | - Mysql >= 5.7 11 | - Laravel 5.5.0 ~ 7.* 12 | - Fileinfo PHP Extension 13 | 14 | 15 | ## 开始安装 16 | >{warning} 如果安装过程中出现composer下载过慢或安装失败的情况,请运行命令`composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/`把composer镜像更换为阿里云镜像。 17 | 18 | 首先需要安装`laravel`,如已安装可以跳过此步骤 19 | ```shell script 20 | composer create-project --prefer-dist laravel/laravel 项目名称 7.* 21 | # 或 22 | composer create-project --prefer-dist laravel/laravel 项目名称 23 | ``` 24 | 25 | 安装完laravel之后需要设置数据库连接设置正确 26 | ```shell script 27 | composer require smallruraldog/laravel-vue-admin 28 | ``` 29 | 然后运行下面的命令来发布资源: 30 | ```shell script 31 | php artisan vendor:publish --provider="SmallRuralDog\Admin\AdminServiceProvider" 32 | ``` 33 | 在该命令会生成配置文件`config/admin.php`,可以在里面修改安装的地址、数据库连接、以及表名,建议都是用默认配置不修改。 34 | 35 | 然后运行下面的命令完成安装: 36 | ```shell script 37 | php artisan admin:install 38 | ``` 39 | 启动服务后,在浏览器打开 `http://localhost/admin/` ,使用用户名 `admin` 和密码 `admin`登陆. -------------------------------------------------------------------------------- /docs/1.x/overview.md: -------------------------------------------------------------------------------- 1 | # Laravel-Vue-Admin 2 | 3 | --- 4 | Laravel-Vue-Admin 是一个开箱即用的Laravel后台扩展 5 | 6 | 前后端分离,后端控制前端组件,无需编写vue即可创建一个`vue` `vuex` `vue-route` `elment-ui` `laravel`的项目 7 | 8 | 丰富的表单 表格组件,强大的自定义组件功能。 9 | 10 | ## 加入我们 11 | 交流群 ID: 1048383034 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/1.x/update.md: -------------------------------------------------------------------------------- 1 | # 版本升级 2 | --- 3 | 4 | ## 更新命令 5 | ```shell script 6 | composer update smallruraldog/laravel-vue-admin 7 | ``` 8 | > {danger} 由于扩展是前后端分离模式,所以升级成功后必须重新发布前端静态资源,并且需要清空浏览器的缓存,如出现前端js报错,可以使用浏览器无痕模式 9 | 10 | ```shell script 11 | # 更新静态资源命令 12 | php artisan vendor:publish --tag=laravel-vue-admin-assets --force 13 | ``` 14 | 15 | 更新语言包 16 | ```shell script 17 | php artisan vendor:publish --tag=laravel-vue-admin-lang --force 18 | ``` 19 | 20 | 清理视图缓存 21 | ```shell script 22 | php artisan view:clear 23 | ``` 24 | 25 | 不要忘记清理浏览器缓存 -------------------------------------------------------------------------------- /docs/README.assets/image-20200313103804881.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/README.assets/image-20200313103804881.png -------------------------------------------------------------------------------- /docs/README.assets/image-20200313105015399.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/README.assets/image-20200313105015399.png -------------------------------------------------------------------------------- /docs/README.assets/image-20200313112129545.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/README.assets/image-20200313112129545.png -------------------------------------------------------------------------------- /docs/README.assets/laravel-vue-admin-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/README.assets/laravel-vue-admin-logo.png -------------------------------------------------------------------------------- /docs/README.assets/logo-1584436939847.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/README.assets/logo-1584436939847.png -------------------------------------------------------------------------------- /docs/README.assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/README.assets/logo.png -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | - [ 入门](/) 2 | - [模型表格](/grid) 3 | - [模型表单](/form) 4 | - [内置组件](/components) 5 | - [自定义组件](/custom) 6 | - [CSS/Javascript](/frontend) 7 | - [第三方扩展](/thirdparty) 8 | -------------------------------------------------------------------------------- /docs/assets/image-20200509104115665.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/assets/image-20200509104115665.png -------------------------------------------------------------------------------- /docs/assets/image-20200509104203063.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/assets/image-20200509104203063.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200313102505193.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200313102505193.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200330135556270.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200330135556270.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200330135622182.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200330135622182.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200330151604231.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200330151604231.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200330154928558.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200330154928558.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200330154940875.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200330154940875.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200330161859300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200330161859300.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200330162019246.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200330162019246.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200331141335210.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200331141335210.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200331142220245.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200331142220245.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200331154059916.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200331154059916.png -------------------------------------------------------------------------------- /docs/components.assets/image-20200331154547211.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/components.assets/image-20200331154547211.png -------------------------------------------------------------------------------- /docs/content.md: -------------------------------------------------------------------------------- 1 | # 布局 2 | 3 | ## Content 4 | 5 | 用于布局的容器组件,方便快速搭建页面的基本结构: 6 | 7 | ```php 8 | Content::make()->row(); 9 | ``` 10 | 11 | -------------------------------------------------------------------------------- /docs/custom.assets/image-20200313100328876.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/custom.assets/image-20200313100328876.png -------------------------------------------------------------------------------- /docs/custom.assets/image-20200313101225595.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/custom.assets/image-20200313101225595.png -------------------------------------------------------------------------------- /docs/custom.assets/image-20200402153922198.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/custom.assets/image-20200402153922198.png -------------------------------------------------------------------------------- /docs/frontend.md: -------------------------------------------------------------------------------- 1 | # CSS / JavaScript 2 | 3 | 4 | 5 | ## 引入CSS文件 6 | 7 | 如果你需要引入CSS文件,可以在`app/Admin/bootstrap.php`加入下面的代码: 8 | 9 | >注意,如果老版本没有`bootstrap.php`,需要手动创建这个文件 10 | 11 | ```php 12 | Admin::css('/your/css/path/style.css'); 13 | 14 | Admin::css('https://unpkg.com/element-ui/lib/theme-chalk/index.css'); 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /docs/grid.assets/image-20200313093443485.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/grid.assets/image-20200313093443485.png -------------------------------------------------------------------------------- /docs/grid.assets/image-20200313093513048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/docs/grid.assets/image-20200313093513048.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document — laravel-vue-admin 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 |
16 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/thirdparty.md: -------------------------------------------------------------------------------- 1 | # 第三方扩展列表 2 | 一个强大的后台,离不开各种丰富的扩展。欢迎大家踊跃提交~~~ 3 | 4 | ## From组件 5 | * [wangeditor](https://github.com/SmallRuralDog/wangeditor) 轻量级 web 富文本编辑器,配置方便,使用简单。支持 IE10+ 浏览器。 6 | 7 | ## Grid组件 8 | 9 | ## Action组件 10 | 11 | ## 全局组件 12 | 13 | ## 其它扩展 14 | * [AuthApi](https://github.com/osindex/laravel-auth-api)基于`laravel/sanctum`的API认证方案,支持多用户。 15 | -------------------------------------------------------------------------------- /mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/resources/js/app.js": "/resources/js/app.js", 3 | "/resources/js/manifest.js": "/resources/js/manifest.js", 4 | "/resources/js/vendor.js": "/resources/js/vendor.js" 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "@antv/g2plot": "^1.1.6", 14 | "@chenfengyuan/vue-qrcode": "^1.0.2", 15 | "axios": "^0.19.2", 16 | "babel-plugin-component": "^1.1.1", 17 | "babel-plugin-import": "^1.13.0", 18 | "cross-env": "^5.1", 19 | "element-ui": "^2.13.2", 20 | "laravel-mix": "^5.0.4", 21 | "lodash": "^4.17.19", 22 | "nprogress": "^0.2.0", 23 | "popper.js": "^1.16.1", 24 | "resolve-url-loader": "^2.3.1", 25 | "sass": "^1.26.8", 26 | "sass-loader": "7.*", 27 | "url-loader": "^3.0.0", 28 | "vue": "^2.6.11", 29 | "vue-bus": "^1.2.1", 30 | "vue-clipboard2": "^0.3.1", 31 | "vue-dplayer": "0.0.10", 32 | "vue-happy-scroll": "^2.1.1", 33 | "vue-nprogress": "^0.1.5", 34 | "vue-template-compiler": "^2.6.10", 35 | "vue-waterfall2": "^1.9.6", 36 | "vuex": "^3.4.0", 37 | "wangeditor": "^3.1.1" 38 | }, 39 | "dependencies": { 40 | "flat": "^5.0.0", 41 | "js-cookie": "^2.2.1", 42 | "mavon-editor": "^2.9.0", 43 | "vue-progressbar": "^0.7.5", 44 | "vue-router": "^3.0.7" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/0.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * wordcloud2.js 3 | * http://timdream.org/wordcloud2.js/ 4 | * 5 | * Copyright 2011 - 2013 Tim Chien 6 | * Released under the MIT license 7 | */ 8 | 9 | /*! ***************************************************************************** 10 | Copyright (c) Microsoft Corporation. 11 | 12 | Permission to use, copy, modify, and/or distribute this software for any 13 | purpose with or without fee is hereby granted. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 16 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 17 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 18 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 19 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 | PERFORMANCE OF THIS SOFTWARE. 22 | ***************************************************************************** */ 23 | 24 | /*! ***************************************************************************** 25 | Copyright (c) Microsoft Corporation. All rights reserved. 26 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 27 | this file except in compliance with the License. You may obtain a copy of the 28 | License at http://www.apache.org/licenses/LICENSE-2.0 29 | 30 | THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 31 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 32 | WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 33 | MERCHANTABLITY OR NON-INFRINGEMENT. 34 | 35 | See the Apache Version 2.0 License for specific language governing permissions 36 | and limitations under the License. 37 | ***************************************************************************** */ 38 | -------------------------------------------------------------------------------- /public/10.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[10],{A09R:function(t,s,e){"use strict";e.r(s);var a=e("stgD"),n=e("b3nO"),o=(e("ZOF2"),{components:{MavonEditor:a.mavonEditor},mixins:[n.a],props:{attrs:Object}}),l=e("KHd+"),r=Object(l.a)(o,(function(){var t=this.$createElement;return(this._self._c||t)("mavon-editor",{class:this.attrs.className,style:this.attrs.style,attrs:{value:this.attrs.content,editable:!1,subfield:!1,defaultOpen:"preview",toolbarsFlag:!1,boxShadow:!1}})}),[],!1,null,null,null);s.default=r.exports}}]); -------------------------------------------------------------------------------- /public/5.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[5],{BdhI:function(t,o,e){"use strict";e.r(o);var i=e("GguQ"),a=e.n(i),s={mixins:[e("b3nO").b],data:function(){return{editor:null,initHtml:!1,defaultValue:""}},mounted:function(){var t=this;this.defaultValue=this._.cloneDeep(this.attrs.componentValue),this.editor=new a.a(this.$refs.toolbar,this.$refs.editor),this.editor.customConfig.menus=this.attrs.menus,this.editor.customConfig.zIndex=this.attrs.zIndex,this.editor.customConfig.uploadImgShowBase64=this.attrs.uploadImgShowBase64,this.attrs.uploadImgServer&&(this.editor.customConfig.uploadImgServer=this.attrs.uploadImgServer,this.editor.customConfig.uploadImgParams={_token:Admin.token}),this.attrs.uploadFileName&&(this.editor.customConfig.uploadFileName=this.attrs.uploadFileName),this.attrs.uploadImgHeaders&&(this.editor.customConfig.uploadImgHeaders=this.attrs.uploadImgHeaders),this.editor.customConfig.onchange=function(o){t.onChange(o)},this.$nextTick((function(){t.editor.create(),t.editor.txt.html(t.defaultValue)})),this.$bus.on("EditDataLoadingCompleted",(function(){t.editor&&t.editor.txt.html(t.value)}))},destroyed:function(){try{this.$bus.off("EditDataLoadingCompleted")}catch(t){}}},n=(e("T+Gg"),e("KHd+")),r=Object(n.a)(s,(function(){var t=this,o=t.$createElement,e=t._self._c||o;return e("div",{staticClass:"wangeditor-main flex-sub"},[e("div",{ref:"toolbar",staticClass:"toolbar"}),t._v(" "),t.attrs.component?e("div",[e(t.attrs.component.componentName,{tag:"component",attrs:{attrs:t.attrs.component,editor:t.editor},on:{"update:editor":function(o){t.editor=o}}})],1):t._e(),t._v(" "),e("div",{ref:"editor",class:t.attrs.className,style:t.attrs.style})])}),[],!1,null,"474f0b14",null);o.default=r.exports},FAQ0:function(t,o,e){var i=e("XCIp");"string"==typeof i&&(i=[[t.i,i,""]]);var a={hmr:!0,transform:void 0,insertInto:void 0};e("aET+")(i,a);i.locals&&(t.exports=i.locals)},"T+Gg":function(t,o,e){"use strict";var i=e("FAQ0");e.n(i).a},XCIp:function(t,o,e){(t.exports=e("I1BE")(!1)).push([t.i,".wangeditor-main[data-v-474f0b14]{border:1px solid #dcdcdc}.wangeditor-main .toolbar[data-v-474f0b14]{background:#f7f7f7}",""])}}]); -------------------------------------------------------------------------------- /public/6.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[6],{"2+Mu":function(t,e,r){"use strict";r.r(e);var n=r("ma/q");function a(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,n)}return r}function c(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var i={props:{attrs:Object},data:function(){return{antv:null}},mounted:function(){this.antv=new n.a(this.attrs.canvasId,function(t){for(var e=1;e 5 | * @license MIT 6 | */ 7 | 8 | /*! 9 | * JavaScript Cookie v2.2.1 10 | * https://github.com/js-cookie/js-cookie 11 | * 12 | * Copyright 2006, 2015 Klaus Hartl & Fagner Brack 13 | * Released under the MIT license 14 | */ 15 | 16 | /*! 17 | * vue-bus v1.2.1 18 | * https://github.com/yangmingshan/vue-bus 19 | * @license MIT 20 | */ 21 | 22 | /** 23 | * @license 24 | * Lodash 25 | * Copyright OpenJS Foundation and other contributors 26 | * Released under MIT license 27 | * Based on Underscore.js 1.8.3 28 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 29 | */ 30 | 31 | /** 32 | * Checks if an event is supported in the current execution environment. 33 | * 34 | * NOTE: This will not work correctly for non-generic events such as `change`, 35 | * `reset`, `load`, `error`, and `select`. 36 | * 37 | * Borrows from Modernizr. 38 | * 39 | * @param {string} eventNameSuffix Event name, e.g. "click". 40 | * @param {?boolean} capture Check if the capture phase is supported. 41 | * @return {boolean} True if the event is supported. 42 | * @internal 43 | * @license Modernizr 3.0.0pre (Custom Build) | MIT 44 | */ 45 | -------------------------------------------------------------------------------- /public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.ttf -------------------------------------------------------------------------------- /public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.woff -------------------------------------------------------------------------------- /public/fonts/vendor/mavon-editor/dist/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/public/fonts/vendor/mavon-editor/dist/fontello.eot -------------------------------------------------------------------------------- /public/fonts/vendor/mavon-editor/dist/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/public/fonts/vendor/mavon-editor/dist/fontello.ttf -------------------------------------------------------------------------------- /public/fonts/vendor/mavon-editor/dist/fontello.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/public/fonts/vendor/mavon-editor/dist/fontello.woff -------------------------------------------------------------------------------- /public/fonts/vendor/mavon-editor/dist/fontello.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/public/fonts/vendor/mavon-editor/dist/fontello.woff2 -------------------------------------------------------------------------------- /public/images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/public/images/404.png -------------------------------------------------------------------------------- /public/manifest.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,a,i=r[0],l=r[1],c=r[2],p=0,s=[];p 由于目前的组件封装的比较弱,不再维护更新,新开发一个基于amis的后台 [amis-admin](https://github.com/SmallRuralDog/amis-admin) 5 | ## 介绍 6 | Laravel-Vue-Admin 是一个开箱即用的Laravel后台扩展 7 | 8 | 前后端分离,简单的几行代码即可创建一个`vue`+`vuex`+`vue-route`+`elment-ui`+`laravel`的项目 9 | 10 | 内置了丰富的`表单` `表格`组件 11 | 12 | 最核心的是强大的自定义组件功能 13 | 14 | 15 | 16 | [开发者文档](https://www.yuque.com/smallruraldog/laravel-vue-admin/overview) 17 | ## 安装 18 | 首先确保安装好了laravel,并且数据库连接设置正确。 19 | 20 | ``` bash 21 | composer require smallruraldog/laravel-vue-admin 22 | ``` 23 | 24 | 然后运行下面的命令来发布资源: 25 | ``` bash 26 | php artisan vendor:publish --provider="SmallRuralDog\Admin\AdminServiceProvider" 27 | ``` 28 | 在该命令会生成配置文件`config/admin.php`,可以在里面修改安装的地址、数据库连接、以及表名,建议都是用默认配置不修改。 29 | 然后运行下面的命令完成安装: 30 | ``` bash 31 | php artisan admin:install 32 | ``` 33 | 启动服务后,在浏览器打开 `/admin` ,使用用户名 admin 和密码 admin登录. 34 | 35 | ## 版本升级 36 | 37 | 查看当前版本 38 | ```bash 39 | composer show smallruraldog/laravel-vue-admin --latest 40 | ``` 41 | 更新到最新版 42 | ```bash 43 | composer require smallruraldog/laravel-vue-admin 44 | ``` 45 | 更新到开发版 46 | ```bash 47 | composer require smallruraldog/laravel-vue-admin:dev-master 48 | ``` 49 | 更新资源文件 50 | 51 | 发布静态资源文件(必须) 52 | ```bash 53 | php artisan vendor:publish --tag=laravel-vue-admin-assets --force 54 | ``` 55 | ```bash 56 | // 发布语言包文件 57 | php artisan vendor:publish --tag=laravel-vue-admin-lang --force 58 | 59 | // 清理视图缓存 60 | php artisan view:clear 61 | ``` 62 | 最后不要忘记清理浏览器缓存,如果有CDN也要更新CDN的缓存 63 | 64 | # 感谢 65 | 66 | - [ZFont找字体](http://zfont.cn) 67 | 68 | 69 | 70 | # 交流 71 | 72 | ![image-20200313103804881](./docs/README.assets/image-20200313103804881.png) 73 | 74 | # 支持 75 | 76 | 如果你觉得 Laravel-Vue-Admin 节省了你的开发时间,让你少加班,让你能更早的回家陪女友或者打游戏,能让你更快速的挣到钱,那么请支持我,让我能继续的将 Laravel-Vue-Admin 做好,做下去! 77 | -------------------------------------------------------------------------------- /resources/js/Admin.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueBus from 'vue-bus'; 3 | import axios from './util/axios' 4 | import lodash from 'lodash' 5 | import router from '@/router' 6 | import store from '@/store' 7 | 8 | 9 | import ElementUI from 'element-ui'; 10 | import 'element-ui/lib/theme-chalk/index.css'; 11 | Vue.use(ElementUI, { size: 'small' }); 12 | 13 | import VueProgressBar from 'vue-progressbar' 14 | 15 | const options = { 16 | color: "#409EFF", 17 | failedColor:"#F56C6C", 18 | thickness: '4px', 19 | autoFinish:false, 20 | } 21 | 22 | Vue.use(VueProgressBar, options); 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Vue.prototype.$http = axios; 31 | Vue.prototype.axios = axios; 32 | Vue.prototype._ = lodash; 33 | window._ = lodash; 34 | Vue.use(VueBus); 35 | 36 | 37 | 38 | export default class VueAdmin { 39 | constructor(config) { 40 | this.bootingCallbacks = []; 41 | this.config = config 42 | } 43 | 44 | booting(callback) { 45 | this.bootingCallbacks.push(callback) 46 | } 47 | 48 | boot() { 49 | this.bootingCallbacks.forEach(callback => callback(Vue, router)); 50 | this.bootingCallbacks = [] 51 | } 52 | 53 | liftOff() { 54 | let _this = this; 55 | this.boot(); 56 | this.app = new Vue({ 57 | el: '#app', 58 | store, 59 | router 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Admin from "./Admin"; 3 | import "./components.js"; 4 | 5 | import "./styles/admin.scss"; 6 | (function() { 7 | this.CreateVueAdmin = function(config) { 8 | return new Admin(config); 9 | }; 10 | }.call(window)); 11 | -------------------------------------------------------------------------------- /resources/js/assets/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallRuralDog/laravel-vue-admin/d0c7fbf3fbfad8dffdd6a49c252fce3107dba181/resources/js/assets/404.png -------------------------------------------------------------------------------- /resources/js/components/404.vue: -------------------------------------------------------------------------------- 1 | 6 | 18 | -------------------------------------------------------------------------------- /resources/js/components/antv/AntvArea.vue: -------------------------------------------------------------------------------- 1 | 4 | 31 | -------------------------------------------------------------------------------- /resources/js/components/antv/AntvColumn.vue: -------------------------------------------------------------------------------- 1 | 4 | 30 | -------------------------------------------------------------------------------- /resources/js/components/antv/AntvLine.vue: -------------------------------------------------------------------------------- 1 | 4 | 30 | -------------------------------------------------------------------------------- /resources/js/components/antv/AntvStepLine.vue: -------------------------------------------------------------------------------- 1 | 4 | 30 | -------------------------------------------------------------------------------- /resources/js/components/form/FormItem.vue: -------------------------------------------------------------------------------- 1 | 43 | 60 | -------------------------------------------------------------------------------- /resources/js/components/form/ItemIf.vue: -------------------------------------------------------------------------------- 1 | 6 | 52 | -------------------------------------------------------------------------------- /resources/js/components/grid/Actions/Index.vue: -------------------------------------------------------------------------------- 1 | 14 | 45 | 56 | -------------------------------------------------------------------------------- /resources/js/components/grid/Actions/TreeAction.vue: -------------------------------------------------------------------------------- 1 | 15 | 30 | 40 | -------------------------------------------------------------------------------- /resources/js/components/grid/BatchActions/Index.vue: -------------------------------------------------------------------------------- 1 | 18 | 38 | -------------------------------------------------------------------------------- /resources/js/components/grid/Column.vue: -------------------------------------------------------------------------------- 1 | 12 | 50 | -------------------------------------------------------------------------------- /resources/js/components/grid/ColumnDisplay.vue: -------------------------------------------------------------------------------- 1 | 13 | 59 | 74 | -------------------------------------------------------------------------------- /resources/js/components/grid/DialogForm.vue: -------------------------------------------------------------------------------- 1 | 16 | 58 | -------------------------------------------------------------------------------- /resources/js/components/grid/TreeColumnDisplay.vue: -------------------------------------------------------------------------------- 1 | 13 | 61 | 76 | -------------------------------------------------------------------------------- /resources/js/components/layout/Column.vue: -------------------------------------------------------------------------------- 1 | 20 | 27 | -------------------------------------------------------------------------------- /resources/js/components/layout/Content.vue: -------------------------------------------------------------------------------- 1 | 21 | 28 | -------------------------------------------------------------------------------- /resources/js/components/layout/MenuItem.vue: -------------------------------------------------------------------------------- 1 | 23 | 31 | -------------------------------------------------------------------------------- /resources/js/components/layout/Row.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Actions/DeleteAction.vue: -------------------------------------------------------------------------------- 1 | 23 | 61 | 62 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Actions/EditAction.vue: -------------------------------------------------------------------------------- 1 | 18 | 52 | 53 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Actions/VueRouteAction.vue: -------------------------------------------------------------------------------- 1 | 6 | 49 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Alert.vue: -------------------------------------------------------------------------------- 1 | 16 | 26 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Badge.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Card.vue: -------------------------------------------------------------------------------- 1 | 25 | 34 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/DialogButton.vue: -------------------------------------------------------------------------------- 1 | 15 | 25 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Divider.vue: -------------------------------------------------------------------------------- 1 | 8 | 13 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Html.vue: -------------------------------------------------------------------------------- 1 | 4 | 13 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Markdown.vue: -------------------------------------------------------------------------------- 1 | 13 | 27 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Steps.vue: -------------------------------------------------------------------------------- 1 | 23 | 30 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Text.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Base/Tooltip.vue: -------------------------------------------------------------------------------- 1 | 24 | 31 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/Cascader.vue: -------------------------------------------------------------------------------- 1 | 41 | 74 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/Checkbox.vue: -------------------------------------------------------------------------------- 1 | 16 | 22 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/CheckboxGroup.vue: -------------------------------------------------------------------------------- 1 | 27 | 38 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/ColorPicker.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/DatePicker.vue: -------------------------------------------------------------------------------- 1 | 25 | 42 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/DateTimePicker.vue: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/Input.vue: -------------------------------------------------------------------------------- 1 | 36 | 51 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/InputNumber.vue: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/ItemSelect.vue: -------------------------------------------------------------------------------- 1 | 18 | 29 | 48 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/RadioGroup.vue: -------------------------------------------------------------------------------- 1 | 21 | 37 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/Rate.vue: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/Slider.vue: -------------------------------------------------------------------------------- 1 | 24 | 35 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/Switch.vue: -------------------------------------------------------------------------------- 1 | 21 | 32 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Form/Transfer.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Grid/Avatar.vue: -------------------------------------------------------------------------------- 1 | 14 | 38 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Grid/Boole.vue: -------------------------------------------------------------------------------- 1 | 7 | 13 | 24 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Grid/GridRoute.vue: -------------------------------------------------------------------------------- 1 | 12 | 37 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Grid/Icon.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Grid/Image.vue: -------------------------------------------------------------------------------- 1 | 12 | 43 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Grid/Link.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Grid/Tag.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /resources/js/components/widgets/Tools/Create.vue: -------------------------------------------------------------------------------- 1 | 17 | 33 | -------------------------------------------------------------------------------- /resources/js/mixins.js: -------------------------------------------------------------------------------- 1 | const GridColumnComponent = { 2 | props: { 3 | attrs: Object, 4 | row: Object, 5 | columnValue: { 6 | default: null 7 | }, 8 | value: { 9 | default: null 10 | } 11 | } 12 | } 13 | 14 | const FormItemComponent = { 15 | data() { 16 | return { 17 | vm: this._.cloneDeep(this.value) 18 | } 19 | }, 20 | props: { 21 | value: { 22 | default: null 23 | }, 24 | formItem: Object, 25 | //当前表单数据 26 | formData: Object, 27 | //当前组件属性 28 | attrs: Object 29 | }, 30 | model: { 31 | prop: "value", 32 | event: "change" 33 | }, 34 | methods: { 35 | onChange(value) { 36 | this.$emit("change", value); 37 | } 38 | }, 39 | watch: { 40 | value(value) { 41 | try { 42 | this.vm = value; 43 | } catch (error) { 44 | 45 | } 46 | 47 | } 48 | } 49 | } 50 | 51 | const BaseComponent = { 52 | mounted() { 53 | 54 | if (this.attrs && this.attrs.ref) { 55 | this.$bus.on(this.attrs.ref, ({ data, self }) => { 56 | let _this = this; 57 | new Function('ref', 'self', data)(_this, self) 58 | }) 59 | } 60 | 61 | if (this.formItem && this.formItem.ref) { 62 | this.$bus.on(this.formItem.ref, ({ data, self }) => { 63 | let _this = this; 64 | new Function('ref', 'self', data)(_this, self) 65 | }) 66 | } 67 | }, 68 | destroyed() { 69 | if (this.attrs && this.attrs.ref) { 70 | this.$bus.off(this.attrs.ref); 71 | } 72 | if (this.formItem && this.formItem.ref) { 73 | this.$bus.off(this.formItem.ref); 74 | } 75 | }, 76 | } 77 | 78 | export { 79 | GridColumnComponent, 80 | FormItemComponent, 81 | BaseComponent 82 | } 83 | -------------------------------------------------------------------------------- /resources/js/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | 5 | 6 | import routes from './routes' 7 | Vue.use(Router) 8 | const router = createRouter({ base: window.config.base }) 9 | export default router 10 | 11 | function createRouter({ base }) { 12 | const router = new Router({ 13 | base, 14 | //mode: 'history', 15 | mode: 'hash', 16 | routes, 17 | }) 18 | router.beforeEach(beforeEach) 19 | router.afterEach(afterEach) 20 | return router 21 | } 22 | 23 | async function beforeEach(to, from, next) { 24 | 25 | 26 | 27 | const components = await resolveComponents( 28 | router.getMatchedComponents({ ...to }) 29 | ) 30 | if (components.length === 0) { 31 | return next() 32 | } 33 | if (components[components.length - 1].loading !== false) { 34 | router.app.$nextTick(() => { 35 | 36 | }) 37 | } 38 | next() 39 | } 40 | 41 | async function afterEach(to, from, next) { 42 | await router.app.$nextTick() 43 | 44 | 45 | 46 | router.app.$bus.emit('route-after', to); 47 | } 48 | 49 | function resolveComponents(components) { 50 | return Promise.all( 51 | components.map(component => { 52 | return typeof component === 'function' ? component() : component 53 | }) 54 | ) 55 | } 56 | 57 | function scrollBehavior(to, from, savedPosition) { 58 | if (savedPosition) { 59 | return savedPosition 60 | } 61 | 62 | if (to.hash) { 63 | return { selector: to.hash } 64 | } 65 | 66 | const [component] = router.getMatchedComponents({ ...to }).slice(-1) 67 | 68 | if (component && component.scrollToTop === false) { 69 | return {} 70 | } 71 | 72 | return { x: 0, y: 0 } 73 | } -------------------------------------------------------------------------------- /resources/js/router/routes.js: -------------------------------------------------------------------------------- 1 | import Base from '../components/layout/Base' 2 | import Page404 from '../components/404' 3 | export default [ 4 | { 5 | name: 'Page404', 6 | path: '/404', 7 | component: Page404 8 | }, 9 | { 10 | name: 'home', 11 | path: '/*', 12 | component: Base 13 | }, 14 | 15 | ] -------------------------------------------------------------------------------- /resources/js/settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | title: 'Laravel Vue Admin', 4 | 5 | /** 6 | * @type {boolean} true | false 7 | * @description Whether fix the header 8 | */ 9 | fixedHeader: false, 10 | 11 | /** 12 | * @type {boolean} true | false 13 | * @description Whether show the logo in sidebar 14 | */ 15 | sidebarLogo: false 16 | } 17 | -------------------------------------------------------------------------------- /resources/js/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | sidebar: state => state.app.sidebar, 3 | device: state => state.app.device, 4 | } 5 | export default getters 6 | -------------------------------------------------------------------------------- /resources/js/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import getters from './getters' 4 | import app from './modules/app' 5 | import settings from './modules/settings' 6 | 7 | Vue.use(Vuex); 8 | 9 | import http from '@/util/axios' 10 | 11 | const store = new Vuex.Store({ 12 | strict: false, 13 | modules: { 14 | app, 15 | settings 16 | }, 17 | state: { 18 | query: "", 19 | path: null, 20 | pages: {}, 21 | contents: {}, 22 | grids: {} 23 | }, 24 | getters: { 25 | ...getters, 26 | thisPage: state => { 27 | return state.pages[state.path] 28 | } 29 | }, 30 | mutations: { 31 | setPath(state, path) { 32 | state.path = path; 33 | }, 34 | initPages(state, path) { 35 | state.pages[path] = { 36 | grids: { 37 | } 38 | } 39 | }, 40 | registerCentent(state, path) { 41 | state.contents[path] = {} 42 | }, 43 | setCenten(state, { data, path }) { 44 | state.contents[path] = data 45 | }, 46 | setGridData(state, { key, data }) { 47 | state.pages[state.path].grids[key] = data; 48 | } 49 | }, 50 | actions: { 51 | getCenten(context, { path, contentUrl, params }) { 52 | 53 | return http.get(contentUrl, { 54 | params: params 55 | }).then(data => { 56 | context.commit('setCenten', { data: data, path: path }); 57 | return Promise.resolve(data) 58 | }).catch(() => { 59 | return Promise.reject() 60 | }); 61 | 62 | } 63 | } 64 | }) 65 | 66 | export default store -------------------------------------------------------------------------------- /resources/js/store/modules/app.js: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie' 2 | 3 | const state = { 4 | sidebar: { 5 | opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, 6 | withoutAnimation: false 7 | }, 8 | device: 'desktop' 9 | } 10 | 11 | const mutations = { 12 | TOGGLE_SIDEBAR: state => { 13 | state.sidebar.opened = !state.sidebar.opened 14 | state.sidebar.withoutAnimation = false 15 | if (state.sidebar.opened) { 16 | Cookies.set('sidebarStatus', 1) 17 | } else { 18 | Cookies.set('sidebarStatus', 0) 19 | } 20 | }, 21 | CLOSE_SIDEBAR: (state, withoutAnimation) => { 22 | Cookies.set('sidebarStatus', 0) 23 | state.sidebar.opened = false 24 | state.sidebar.withoutAnimation = withoutAnimation 25 | }, 26 | TOGGLE_DEVICE: (state, device) => { 27 | state.device = device 28 | } 29 | } 30 | 31 | const actions = { 32 | toggleSideBar({ commit }) { 33 | commit('TOGGLE_SIDEBAR') 34 | }, 35 | closeSideBar({ commit }, { withoutAnimation }) { 36 | commit('CLOSE_SIDEBAR', withoutAnimation) 37 | }, 38 | toggleDevice({ commit }, device) { 39 | commit('TOGGLE_DEVICE', device) 40 | } 41 | } 42 | 43 | export default { 44 | namespaced: true, 45 | state, 46 | mutations, 47 | actions 48 | } 49 | -------------------------------------------------------------------------------- /resources/js/store/modules/settings.js: -------------------------------------------------------------------------------- 1 | import defaultSettings from '@/settings' 2 | 3 | const { showSettings, fixedHeader, sidebarLogo } = defaultSettings 4 | 5 | const state = { 6 | showSettings: showSettings, 7 | fixedHeader: fixedHeader, 8 | sidebarLogo: sidebarLogo 9 | } 10 | 11 | const mutations = { 12 | CHANGE_SETTING: (state, { key, value }) => { 13 | // eslint-disable-next-line no-prototype-builtins 14 | if (state.hasOwnProperty(key)) { 15 | state[key] = value 16 | } 17 | } 18 | } 19 | 20 | const actions = { 21 | changeSetting({ commit }, data) { 22 | commit('CHANGE_SETTING', data) 23 | } 24 | } 25 | 26 | export default { 27 | namespaced: true, 28 | state, 29 | mutations, 30 | actions 31 | } 32 | 33 | -------------------------------------------------------------------------------- /resources/js/styles/element-ui.scss: -------------------------------------------------------------------------------- 1 | // cover some element-ui styles 2 | 3 | .el-breadcrumb__inner, 4 | .el-breadcrumb__inner a { 5 | font-weight: 400 !important; 6 | } 7 | 8 | .el-upload { 9 | input[type="file"] { 10 | display: none !important; 11 | } 12 | } 13 | 14 | .el-upload__input { 15 | display: none; 16 | } 17 | 18 | 19 | // to fixed https://github.com/ElemeFE/element/issues/2461 20 | .el-dialog { 21 | transform: none; 22 | left: 0; 23 | position: relative; 24 | margin: 0 auto; 25 | } 26 | 27 | // refine element ui upload 28 | .upload-container { 29 | .el-upload { 30 | width: 100%; 31 | 32 | .el-upload-dragger { 33 | width: 100%; 34 | height: 200px; 35 | } 36 | } 37 | } 38 | 39 | // dropdown 40 | .el-dropdown-menu { 41 | a { 42 | display: block 43 | } 44 | } 45 | 46 | // to fix el-date-picker css style 47 | .el-range-separator { 48 | box-sizing: content-box; 49 | } 50 | -------------------------------------------------------------------------------- /resources/js/styles/mixin.scss: -------------------------------------------------------------------------------- 1 | @mixin clearfix { 2 | &:after { 3 | content: ""; 4 | display: table; 5 | clear: both; 6 | } 7 | } 8 | 9 | @mixin scrollBar { 10 | &::-webkit-scrollbar-track-piece { 11 | background: #d3dce6; 12 | } 13 | 14 | &::-webkit-scrollbar { 15 | width: 6px; 16 | } 17 | 18 | &::-webkit-scrollbar-thumb { 19 | background: #99a9bf; 20 | border-radius: 20px; 21 | } 22 | } 23 | 24 | @mixin relative { 25 | position: relative; 26 | width: 100%; 27 | height: 100%; 28 | } 29 | -------------------------------------------------------------------------------- /resources/js/styles/transition.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | .fade-enter-active, 4 | .fade-leave-active { 5 | -webkit-transition: opacity 0.1s; 6 | transition: opacity 0.1s; 7 | } 8 | 9 | .fade-enter, 10 | .fade-leave-active { 11 | opacity: 0; 12 | } 13 | 14 | .fade-transform-leave-active, 15 | .fade-transform-enter-active { 16 | -webkit-transition: all 0.5s; 17 | transition: all 0.5s; 18 | } 19 | 20 | .fade-transform-enter { 21 | opacity: 0; 22 | -webkit-transform: translateX(-10px); 23 | transform: translateX(-10px); 24 | } 25 | 26 | .fade-transform-leave-to { 27 | opacity: 0; 28 | -webkit-transform: translateX(0px); 29 | transform: translateX(0px); 30 | } 31 | -------------------------------------------------------------------------------- /resources/js/styles/variables.scss: -------------------------------------------------------------------------------- 1 | // sidebar 2 | $menuText:#bfcbd9; 3 | $menuActiveText:#409EFF; 4 | $subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951 5 | 6 | $menuBg:#304156; 7 | $menuHover:#263445; 8 | 9 | $subMenuBg:#1f2d3d; 10 | $subMenuHover:#001528; 11 | 12 | $sideBarWidth: 210px; 13 | 14 | // the :export directive is the magic sauce for webpack 15 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass 16 | :export { 17 | menuText: $menuText; 18 | menuActiveText: $menuActiveText; 19 | subMenuActiveText: $subMenuActiveText; 20 | menuBg: $menuBg; 21 | menuHover: $menuHover; 22 | subMenuBg: $subMenuBg; 23 | subMenuHover: $subMenuHover; 24 | sideBarWidth: $sideBarWidth; 25 | } 26 | -------------------------------------------------------------------------------- /resources/js/util/dom.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | const isServer = Vue.prototype.$isServer; 3 | 4 | /* istanbul ignore next */ 5 | export const on = (function() { 6 | if (!isServer && document.addEventListener) { 7 | return function(element, event, handler, useCapture = false) { 8 | if (element && event && handler) { 9 | element.addEventListener(event, handler, useCapture); 10 | } 11 | }; 12 | } else { 13 | return function(element, event, handler) { 14 | if (element && event && handler) { 15 | element.attachEvent('on' + event, handler); 16 | } 17 | }; 18 | } 19 | })(); 20 | 21 | /* istanbul ignore next */ 22 | export const off = (function() { 23 | if (!isServer && document.removeEventListener) { 24 | return function(element, event, handler, useCapture = false) { 25 | if (element && event) { 26 | element.removeEventListener(event, handler, useCapture); 27 | } 28 | }; 29 | } else { 30 | return function(element, event, handler) { 31 | if (element && event) { 32 | element.detachEvent('on' + event, handler); 33 | } 34 | }; 35 | } 36 | })(); -------------------------------------------------------------------------------- /resources/js/util/validate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by PanJiaChen on 16/11/18. 3 | */ 4 | 5 | /** 6 | * @param {string} path 7 | * @returns {Boolean} 8 | */ 9 | export function isExternal(path) { 10 | return /^(https?:|mailto:|tel:)/.test(path) 11 | } 12 | 13 | /** 14 | * @param {string} str 15 | * @returns {Boolean} 16 | */ 17 | export function validUsername(str) { 18 | const valid_map = ['admin', 'editor'] 19 | return valid_map.indexOf(str.trim()) >= 0 20 | } 21 | -------------------------------------------------------------------------------- /resources/js/utils.js: -------------------------------------------------------------------------------- 1 | function getArrayValue(data, path, level) { 2 | let index = level + 1; 3 | let key = path[index] 4 | if (!window._.isArray(data)) { 5 | return [data[key]]; 6 | } 7 | let allData = data.map((item) => { 8 | let itemData = item[key] 9 | if (window._.isArray(itemData)) { 10 | return getArrayValue(itemData, path, index) 11 | } else { 12 | return itemData; 13 | } 14 | }) 15 | return allData; 16 | } 17 | 18 | 19 | function flattenDeepChild(data, child_key, key) { 20 | let arr = data.map(item => { 21 | 22 | 23 | let arr = [] 24 | let itemData = item[key] 25 | arr.push(itemData) 26 | let v = item[child_key]; 27 | if (v) { 28 | arr.push(flattenDeepChild(item[child_key], child_key, key)) 29 | } 30 | return window._.flattenDeep(arr); 31 | }) 32 | 33 | return window._.flattenDeep(arr); 34 | } 35 | 36 | 37 | 38 | function getFileUrl(host, path) { 39 | 40 | if (path.indexOf("//") >= 0) { 41 | return path; 42 | } else { 43 | return host + path; 44 | } 45 | } 46 | 47 | function getFileName(path) { 48 | 49 | try { 50 | let pathInfo = path.split('/') 51 | 52 | return pathInfo[pathInfo.length - 1] 53 | 54 | } catch (error) { 55 | return "" 56 | } 57 | 58 | } 59 | 60 | function isNull(argument) { 61 | const type = typeof argument 62 | switch (type) { 63 | case 'object': 64 | return window._.isEmpty(argument) 65 | case 'array': 66 | return argument.length 67 | default: 68 | return argument === "" || argument === null || argument === undefined 69 | } 70 | } 71 | 72 | export { 73 | getArrayValue, 74 | flattenDeepChild, 75 | getFileUrl, 76 | getFileName, 77 | isNull 78 | } 79 | -------------------------------------------------------------------------------- /resources/views/content.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin::layouts.base') 2 | @section('content') 3 | {!! $content !!} 4 | @endsection 5 | -------------------------------------------------------------------------------- /resources/views/form/base-form.blade.php: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /resources/views/grid/table.blade.php: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /resources/views/layouts/base.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ Admin::title() }} 8 | 9 | {!! Admin::css() !!} 10 | @foreach(\SmallRuralDog\Admin\Admin::styles() as $name => $path) 11 | @if (\Illuminate\Support\Str::startsWith($path, ['http://', 'https://'])) 12 | 13 | @else 14 | 15 | @endif 16 | 17 | @endforeach 18 | @yield('head-js') 19 | 20 | 21 |
@yield('content')
22 | 29 | @yield('js') 30 | 31 | 32 | 33 | 34 | 37 | @foreach (\SmallRuralDog\Admin\Admin::scripts() as $name => $path) 38 | @if (\Illuminate\Support\Str::startsWith($path, ['http://', 'https://'])) 39 | 40 | @else 41 | 42 | @endif 43 | @endforeach 44 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /resources/views/login.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin::layouts.base') 2 | 3 | @section('content')@endsection 4 | -------------------------------------------------------------------------------- /resources/views/partials/css.blade.php: -------------------------------------------------------------------------------- 1 | @foreach($css as $c) 2 | 3 | @endforeach -------------------------------------------------------------------------------- /resources/views/root.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin::layouts.base') 2 | @section('content')@endsection 3 | -------------------------------------------------------------------------------- /src/Actions/BaseRowAction.php: -------------------------------------------------------------------------------- 1 | order = $order; 30 | return $this; 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | /** 40 | * 设置操作vif属性算法 41 | * @param array $vif 42 | * @return $this 43 | */ 44 | public function vif($vif) 45 | { 46 | $this->vif = $vif; 47 | return $this; 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/Auth/Database/OperationLog.php: -------------------------------------------------------------------------------- 1 | 'green', 14 | 'POST' => 'yellow', 15 | 'PUT' => 'blue', 16 | 'DELETE' => 'red', 17 | ]; 18 | 19 | public static $methods = [ 20 | 'GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH', 21 | 'LINK', 'UNLINK', 'COPY', 'HEAD', 'PURGE', 22 | ]; 23 | 24 | protected $casts = [ 25 | 'created_at'=>"timestamp:Y-m-d H:i:s", 26 | 'updated_at'=>"timestamp:Y-m-d H:i:s", 27 | ]; 28 | 29 | /** 30 | * Create a new Eloquent model instance. 31 | * 32 | * @param array $attributes 33 | */ 34 | public function __construct(array $attributes = []) 35 | { 36 | $connection = config('admin.database.connection') ?: config('database.default'); 37 | 38 | $this->setConnection($connection); 39 | 40 | $this->setTable(config('admin.database.operation_log_table')); 41 | 42 | parent::__construct($attributes); 43 | } 44 | 45 | /** 46 | * Log belongs to users. 47 | * 48 | * @return BelongsTo 49 | */ 50 | public function user() : BelongsTo 51 | { 52 | return $this->belongsTo(Administrator::class); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Components/Antv/Area.php: -------------------------------------------------------------------------------- 1 | canvasId = Str::random(); 19 | } 20 | 21 | 22 | public static function make() 23 | { 24 | return new Line(); 25 | } 26 | 27 | /** 28 | * 设置数据 29 | * @param mixed $data 30 | * @return $this 31 | */ 32 | public function data($data) 33 | { 34 | if ($data instanceof \Closure) { 35 | $this->data = call_user_func($data); 36 | } else { 37 | $this->data = $data; 38 | } 39 | 40 | 41 | return $this; 42 | } 43 | 44 | /** 45 | * 设置配置信息 46 | * @param mixed $config 47 | * @return $this 48 | */ 49 | public function config($config) 50 | { 51 | if ($config instanceof \Closure) { 52 | $this->config = call_user_func($config); 53 | } else { 54 | $this->config = $config; 55 | } 56 | 57 | return $this; 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/Components/Antv/StepLine.php: -------------------------------------------------------------------------------- 1 | type = "default"; 20 | $op->value = $value; 21 | $op->label = $label; 22 | return $op; 23 | } 24 | 25 | /** 26 | * @param CascaderOption[] $children 27 | * @return $this 28 | */ 29 | public function children($children) 30 | { 31 | $this->children = $children; 32 | return $this; 33 | } 34 | 35 | /** 36 | * @param bool $leaf 37 | * @return $this 38 | */ 39 | public function leaf($leaf=true) 40 | { 41 | $this->leaf = $leaf; 42 | return $this; 43 | } 44 | 45 | 46 | 47 | public function jsonSerialize() 48 | { 49 | $data = []; 50 | foreach ($this as $key => $val) { 51 | if (!empty($val)) $data[$key] = $val; 52 | } 53 | return $data; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/Components/Attrs/CascaderProps.php: -------------------------------------------------------------------------------- 1 | depend = $depend; 19 | return $this; 20 | } 21 | 22 | /** 23 | * @param mixed $paginate 24 | * @return $this 25 | */ 26 | public function paginate($paginate) 27 | { 28 | $this->paginate = $paginate; 29 | return $this; 30 | } 31 | /** 32 | * @param mixed $extUrlParams 33 | * @return $this 34 | */ 35 | public function extUrlParams($extUrlParams) 36 | { 37 | $this->extUrlParams = $extUrlParams; 38 | return $this; 39 | } 40 | /** 41 | * 远程加载时的默认显示名称,因远程时一般仅有value 42 | * @param object form 所属表单 43 | * @param array $label ['key'=>'model','value'=>['value'=>'id','label'=>['title','label']]] // 所属关联模型 用于从data取值 44 | * @return $this 45 | */ 46 | public function label(&$form, $label) 47 | { 48 | $this->label = $label; 49 | $form->item($label['key'])->vif('label' . mt_rand(10000, 99999), false); 50 | return $this; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Components/Attrs/ElLink.php: -------------------------------------------------------------------------------- 1 | type = $type; 21 | return $this; 22 | } 23 | 24 | /** 25 | * @param bool $underline 26 | * @return $this 27 | */ 28 | public function underline(bool $underline = true) 29 | { 30 | $this->underline = $underline; 31 | return $this; 32 | } 33 | 34 | /** 35 | * @param bool $disabled 36 | * @return $this 37 | */ 38 | public function disabled(bool $disabled = true) 39 | { 40 | $this->disabled = $disabled; 41 | return $this; 42 | } 43 | 44 | 45 | /** 46 | * @param mixed $icon 47 | * @return $this 48 | */ 49 | public function icon($icon) 50 | { 51 | $this->icon = $icon; 52 | return $this; 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/Components/Attrs/SelectOption.php: -------------------------------------------------------------------------------- 1 | type = "default"; 22 | $op->value = $value; 23 | $op->label = $label; 24 | return $op; 25 | } 26 | 27 | /** 28 | * 是否禁用该选项 29 | * @param bool $disabled 30 | * @return $this 31 | */ 32 | public function disabled($disabled = true) 33 | { 34 | $this->disabled = $disabled; 35 | return $this; 36 | } 37 | 38 | /** 39 | * @param string $avatar 40 | * @return $this 41 | */ 42 | public function avatar($avatar) 43 | { 44 | $this->avatar = $avatar; 45 | return $this; 46 | } 47 | 48 | /** 49 | * @param mixed $desc 50 | * @return $this 51 | */ 52 | public function desc($desc) 53 | { 54 | $this->desc = $desc; 55 | return $this; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Components/Attrs/Step.php: -------------------------------------------------------------------------------- 1 | title = $title; 30 | return $this; 31 | } 32 | 33 | /** 34 | * 描述性文字 35 | * @param string $description 36 | * @return $this 37 | */ 38 | public function description($description) 39 | { 40 | $this->description = $description; 41 | return $this; 42 | } 43 | 44 | /** 45 | * 图标 46 | * @param string $icon 47 | * @return $this 48 | */ 49 | public function icon($icon) 50 | { 51 | $this->icon = $icon; 52 | return $this; 53 | } 54 | 55 | /** 56 | * 设置当前步骤的状态,不设置则根据 steps 确定状态 57 | * @param mixed $status 58 | * @return $this 59 | */ 60 | public function status($status) 61 | { 62 | $this->status = $status; 63 | return $this; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Components/Attrs/TransferData.php: -------------------------------------------------------------------------------- 1 | key = $key; 31 | $this->label = $label; 32 | $this->disabled = $disabled; 33 | } 34 | 35 | 36 | /** 37 | * @inheritDoc 38 | */ 39 | public function jsonSerialize() 40 | { 41 | $data = []; 42 | foreach ($this as $key => $val) { 43 | $data[$key] = $val; 44 | } 45 | return $data; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Components/Form/DateTimePicker.php: -------------------------------------------------------------------------------- 1 | type($type); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/Components/Form/IconChoose.php: -------------------------------------------------------------------------------- 1 | label($value)->title($title); 34 | } 35 | 36 | /** 37 | * Radio 的 value 38 | * @param $label 39 | * @return $this 40 | */ 41 | public function label($label) 42 | { 43 | $this->label = $label; 44 | return $this; 45 | } 46 | 47 | /** 48 | * 是否禁用 49 | * @param bool $disabled 50 | * @return $this 51 | */ 52 | public function disabled(bool $disabled) 53 | { 54 | $this->disabled = $disabled; 55 | return $this; 56 | } 57 | 58 | /** 59 | * 是否显示边框 60 | * @param bool $border 61 | * @return $this 62 | */ 63 | public function border(bool $border = true) 64 | { 65 | $this->border = $border; 66 | return $this; 67 | } 68 | 69 | /** 70 | * Radio 的尺寸,仅在 border 为真时有效 71 | * @param string $size 72 | * @return $this 73 | */ 74 | public function size(string $size) 75 | { 76 | $this->size = $size; 77 | return $this; 78 | } 79 | 80 | /** 81 | * 原生 name 属性 82 | * @param string $name 83 | * @return $this 84 | */ 85 | public function name(string $name) 86 | { 87 | $this->name = $name; 88 | return $this; 89 | } 90 | 91 | public function title(string $title) 92 | { 93 | $this->title = $title; 94 | return $this; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/Components/Grid/Boole.php: -------------------------------------------------------------------------------- 1 | type = [ 35 | 'data' => $type, 36 | 'random' => $random 37 | ]; 38 | 39 | return $this; 40 | } 41 | 42 | /** 43 | * @param bool $underline 44 | * @return $this 45 | */ 46 | public function underline($underline = true) 47 | { 48 | $this->underline = $underline; 49 | return $this; 50 | } 51 | 52 | /** 53 | * @param bool $disabled 54 | * @return $this 55 | */ 56 | public function disabled(bool $disabled = true) 57 | { 58 | $this->disabled = $disabled; 59 | return $this; 60 | } 61 | 62 | /** 63 | * @param string $href 64 | * @return $this 65 | */ 66 | public function href($href) 67 | { 68 | $this->href = $href; 69 | return $this; 70 | } 71 | 72 | /** 73 | * @param string $icon 74 | * @return $this 75 | */ 76 | public function icon($icon) 77 | { 78 | $this->icon = $icon; 79 | return $this; 80 | } 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/Components/Grid/Route.php: -------------------------------------------------------------------------------- 1 | uri = $uri; 21 | } 22 | 23 | 24 | public static function make($url = "") 25 | { 26 | return new Route($url); 27 | } 28 | 29 | /** 30 | * 类型 31 | * primary / success / warning / danger / info 32 | * @param mixed $type 33 | * @return $this 34 | */ 35 | public function type($type) 36 | { 37 | $this->type = $type; 38 | return $this; 39 | } 40 | 41 | /** 42 | * 图标类名 43 | * @param mixed $icon 44 | * @return $this 45 | */ 46 | public function icon($icon) 47 | { 48 | $this->icon = $icon; 49 | return $this; 50 | } 51 | 52 | 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/Components/GridComponent.php: -------------------------------------------------------------------------------- 1 | value = $value; 28 | } 29 | 30 | public static function make($value) 31 | { 32 | return new Badge($value); 33 | } 34 | 35 | /** 36 | * @param string|int $value 37 | * @return $this 38 | */ 39 | public function value($value) 40 | { 41 | $this->value = $value; 42 | return $this; 43 | } 44 | 45 | /** 46 | * @param int $max 47 | * @return $this 48 | */ 49 | public function max(int $max) 50 | { 51 | $this->max = $max; 52 | return $this; 53 | } 54 | 55 | /** 56 | * @param bool $isDot 57 | * @return $this 58 | */ 59 | public function isDot(bool $isDot) 60 | { 61 | $this->isDot = $isDot; 62 | return $this; 63 | } 64 | 65 | /** 66 | * @param bool $hidden 67 | * @return $this 68 | */ 69 | public function hidden(bool $hidden) 70 | { 71 | $this->hidden = $hidden; 72 | return $this; 73 | } 74 | 75 | /** 76 | * @param string $type 77 | * @return $this 78 | */ 79 | public function type(string $type) 80 | { 81 | $this->type = $type; 82 | return $this; 83 | } 84 | 85 | /** 86 | * @param mixed $child 87 | * @return $this 88 | */ 89 | public function child($child) 90 | { 91 | $this->child = $child; 92 | return $this; 93 | } 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/Components/Widgets/Button.php: -------------------------------------------------------------------------------- 1 | content = $content; 29 | } 30 | 31 | /** 32 | * @param string $content 按钮内容 33 | * @return $this 34 | */ 35 | public static function make($content=null) 36 | { 37 | return new Button($content); 38 | } 39 | 40 | /** 41 | * @param mixed $uri 42 | * @return $this 43 | */ 44 | public function uri($uri) 45 | { 46 | $this->uri = $uri; 47 | return $this; 48 | } 49 | 50 | /** 51 | * @param string $handler 响应类型 request|route|link 52 | * @return $this 53 | */ 54 | public function handler($handler) 55 | { 56 | abort_if(!in_array($handler, [self::HANDLER_LINK, self::HANDLER_REQUEST, self::HANDLER_ROUTE]), 400, "ActionButton 事件类型错误"); 57 | 58 | $this->handler = $handler; 59 | return $this; 60 | } 61 | 62 | public function route($uri) 63 | { 64 | $this->uri = $uri; 65 | $this->handler = self::HANDLER_ROUTE; 66 | return $this; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Components/Widgets/Card.php: -------------------------------------------------------------------------------- 1 | header = instance_content($header); 30 | return $this; 31 | } 32 | 33 | /** 34 | * 设置 body 的样式 35 | * @param string $bodyStyle 36 | * @return $this 37 | */ 38 | public function bodyStyle($bodyStyle) 39 | { 40 | $this->bodyStyle = $bodyStyle; 41 | return $this; 42 | } 43 | 44 | /** 45 | * 设置阴影显示时机 46 | * always / hover / never 47 | * @param string $shadow 48 | * @return $this 49 | */ 50 | public function shadow(string $shadow) 51 | { 52 | $this->shadow = $shadow; 53 | return $this; 54 | } 55 | 56 | /** 57 | * 设置内容组件 58 | * @param $content 59 | * @return $this 60 | */ 61 | public function content($content) 62 | { 63 | $this->content = instance_content($content); 64 | return $this; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Components/Widgets/Dialog.php: -------------------------------------------------------------------------------- 1 | content = $content; 25 | } 26 | 27 | public static function make($content) 28 | { 29 | return new Divider($content); 30 | } 31 | 32 | 33 | /** 34 | * @param string $direction 35 | * @return $this 36 | */ 37 | public function direction(string $direction) 38 | { 39 | $this->direction = $direction; 40 | return $this; 41 | } 42 | 43 | /** 44 | * @param string $contentPosition 45 | * @return $this 46 | */ 47 | public function contentPosition(string $contentPosition) 48 | { 49 | $this->contentPosition = $contentPosition; 50 | return $this; 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/Components/Widgets/Html.php: -------------------------------------------------------------------------------- 1 | html = $html; 19 | } 20 | 21 | 22 | public static function make($html = "") 23 | { 24 | return new Html($html); 25 | } 26 | 27 | /** 28 | * @param string $html 29 | * @return $this 30 | */ 31 | public function html(string $html) 32 | { 33 | $this->html = $html; 34 | return $this; 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/Components/Widgets/Markdown.php: -------------------------------------------------------------------------------- 1 | content = $content; 20 | } 21 | 22 | public static function make($content=""){ 23 | return new Markdown($content); 24 | } 25 | 26 | 27 | public function content($content) 28 | { 29 | $this->content = $content; 30 | return $this; 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/Components/Widgets/Text.php: -------------------------------------------------------------------------------- 1 | text = $text; 23 | } 24 | 25 | 26 | static public function make($text = "") 27 | { 28 | return new Text($text); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Console/AcceptsNameAndVendor.php: -------------------------------------------------------------------------------- 1 | argument('name'); 18 | 19 | if (! Str::contains($name, '/')) { 20 | $this->error("The name argument expects a vendor and name in 'Composer' format. Here's an example: `vendor/name`."); 21 | 22 | return false; 23 | } 24 | 25 | return true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /vendor 3 | /node_modules 4 | package-lock.json 5 | composer.phar 6 | composer.lock 7 | phpunit.xml 8 | .phpunit.result.cache 9 | .DS_Store 10 | Thumbs.db 11 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{ name }}", 3 | "description": "A Laravel Vue Admin Extend", 4 | "keywords": [ 5 | "laravel", 6 | "vue", 7 | "admin" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": ">=7.1.0" 12 | }, 13 | "autoload": { 14 | "psr-4": { 15 | "{{ escapedNamespace }}\\": "src/" 16 | } 17 | }, 18 | "extra": { 19 | "laravel": { 20 | "providers": [ 21 | "{{ escapedNamespace }}\\ExtendServiceProvider" 22 | ] 23 | } 24 | }, 25 | "config": { 26 | "sort-packages": true 27 | }, 28 | "minimum-stability": "dev", 29 | "prefer-stable": true 30 | } 31 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "cross-env": "^5.1", 14 | "laravel-mix": "^4.1.4", 15 | "resolve-url-loader": "^2.3.1", 16 | "sass": "^1.20.1", 17 | "sass-loader": "7.*", 18 | "vue-template-compiler": "^2.6.10" 19 | }, 20 | "dependencies": { 21 | "vue": "^2.6.11" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/resources/js/extend.js: -------------------------------------------------------------------------------- 1 | VueAdmin.booting((Vue, router, store) => { 2 | //Vue.component('组件名称',require('./components/xxx.vue').default); 3 | }); 4 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/resources/sass/extend.scss: -------------------------------------------------------------------------------- 1 | //css 2 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/routes/route.php: -------------------------------------------------------------------------------- 1 | group([ 5 | 'prefix' => config('admin.route.prefix'), 6 | 'middleware' => config('admin.route.middleware'), 7 | ], function ($router) { 8 | 9 | }); 10 | 11 | // 12 | $router->group([ 13 | 'prefix' => config('admin.route.api_prefix'), 14 | 'middleware' => config('admin.route.middleware'), 15 | ], function ($router) { 16 | 17 | }); 18 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/src/ExtendServiceProvider.stub: -------------------------------------------------------------------------------- 1 | registerRouter(); // 31 | } 32 | /** 33 | * 注册路由 34 | * 35 | * @author osi 36 | */ 37 | private function registerRouter() 38 | { 39 | if (strpos($this->app->version(), 'Lumen') === false && !$this->app->routesAreCached()) { 40 | app('router')->namespace('{{ namespace }}\Controllers')->group(__DIR__ . '/../routes/route.php'); 41 | } else { 42 | $this->loadRoutesFrom(__DIR__ . '/../routes/route.php'); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Console/extend-stubs/webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix') 2 | 3 | mix 4 | .setPublicPath('dist') 5 | .js('resources/js/extend.js', 'js') 6 | .sass('resources/sass/extend.scss', 'css'); 7 | -------------------------------------------------------------------------------- /src/Console/form-item-stubs/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /vendor 3 | /node_modules 4 | package-lock.json 5 | composer.phar 6 | composer.lock 7 | phpunit.xml 8 | .phpunit.result.cache 9 | .DS_Store 10 | Thumbs.db 11 | -------------------------------------------------------------------------------- /src/Console/form-item-stubs/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{ name }}", 3 | "description": "A Laravel Vue Admin Form Item Component", 4 | "keywords": [ 5 | "laravel", 6 | "vue", 7 | "admin" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": ">=7.1.0" 12 | }, 13 | "autoload": { 14 | "psr-4": { 15 | "{{ escapedNamespace }}\\": "src/" 16 | } 17 | }, 18 | "extra": { 19 | "laravel": { 20 | "providers": [ 21 | "{{ escapedNamespace }}\\FormItemServiceProvider" 22 | ] 23 | } 24 | }, 25 | "config": { 26 | "sort-packages": true 27 | }, 28 | "minimum-stability": "dev", 29 | "prefer-stable": true 30 | } 31 | -------------------------------------------------------------------------------- /src/Console/form-item-stubs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "cross-env": "^5.1", 14 | "laravel-mix": "^4.1.4" 15 | }, 16 | "dependencies": { 17 | "vue": "^2.6.11" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Console/form-item-stubs/resources/js/components/FormItem.vue: -------------------------------------------------------------------------------- 1 | 4 | 18 | -------------------------------------------------------------------------------- /src/Console/form-item-stubs/resources/js/form-item.js: -------------------------------------------------------------------------------- 1 | VueAdmin.booting((Vue, router, store) => { 2 | Vue.component('form-item-{{ component }}', require('./components/FormItem').default) 3 | }) 4 | -------------------------------------------------------------------------------- /src/Console/form-item-stubs/resources/sass/form-item.scss: -------------------------------------------------------------------------------- 1 | //css 2 | -------------------------------------------------------------------------------- /src/Console/form-item-stubs/src/FormItem.stub: -------------------------------------------------------------------------------- 1 | config('admin.route.domain'), 7 | 'prefix' => config('admin.route.api_prefix'), 8 | 'namespace'=>config('admin.route.namespace'), 9 | 'middleware' => config('admin.route.middleware'), 10 | ], function (Router $router) { 11 | $router->get('/', 'HomeController@index')->name('admin.home'); 12 | $router->get('/home', 'HomeController@index')->name('admin.home'); 13 | }); 14 | -------------------------------------------------------------------------------- /src/Controllers/AdminResource.php: -------------------------------------------------------------------------------- 1 | form(true)->update($id); 11 | } 12 | 13 | public function store() 14 | { 15 | return $this->form()->store(); 16 | } 17 | 18 | public function destroy($id) 19 | { 20 | return $this->form()->destroy($id); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Controllers/RoleController.php: -------------------------------------------------------------------------------- 1 | quickSearch(['slug', 'name']); 24 | 25 | $grid->column('id', 'ID')->width('80px')->sortable(); 26 | $grid->column('slug', "标识"); 27 | $grid->column('name', "名称"); 28 | $grid->column('permissions.name', "权限")->component(Tag::make()->type('info')); 29 | $grid->column('created_at'); 30 | $grid->column('updated_at'); 31 | $grid->dialogForm($this->form()->isDialog()->labelWidth("auto")->className('p-15'), '700px', ['添加角色', '编辑角色']); 32 | return $grid; 33 | } 34 | 35 | public function form() 36 | { 37 | $permissionModel = config('admin.database.permissions_model'); 38 | $roleModel = config('admin.database.roles_model'); 39 | $form = new Form(new $roleModel()); 40 | 41 | $form->item('slug', "标识")->required()->inputWidth(8); 42 | $form->item('name', "名称")->required()->inputWidth(8); 43 | $form->item('permissions', "权限", 'permissions.id')->component( 44 | Transfer::make()->data($permissionModel::get()->map(function ($item) { 45 | return TransferData::make($item->id, $item->name); 46 | }))->titles(['可授权', '已授权'])->filterable() 47 | ); 48 | return $form; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Controllers/RootController.php: -------------------------------------------------------------------------------- 1 | config('app.env')=="local", 16 | 'menu' => Admin::menu(), 17 | 'menuList' => Admin::menuList(), 18 | 'logoShow' => config('admin.logo_show'), 19 | 'logo' => config('admin.logo'), 20 | 'logoLight' => config('admin.logo_light'), 21 | 'logoMini' => config('admin.logo_mini'), 22 | 'logoMiniLight' => config('admin.logo_mini_light'), 23 | 'name' => config('admin.name'), 24 | 'copyright' => config('admin.copyright'), 25 | 'footerLinks' => config('admin.footerLinks'), 26 | 'uniqueOpened' => config('admin.unique_opened',false), 27 | 'user' => $this->getUserData(), 28 | 'url' => $this->getUrls() 29 | ]; 30 | 31 | 32 | return view('admin::root', ['data' => $data]); 33 | } 34 | 35 | 36 | 37 | 38 | protected function getUserData() 39 | { 40 | if (!$user = Admin::user()) { 41 | return []; 42 | } 43 | return Arr::only($user->toArray(), ['id', 'username', 'email', 'name', 'avatar']); 44 | } 45 | 46 | protected function getUrls() 47 | { 48 | return [ 49 | 'logout' => route('admin.logout'), 50 | 'setting' => route('admin.setting') 51 | ]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Controllers/ScriptController.php: -------------------------------------------------------------------------------- 1 | 'application/javascript', 22 | ] 23 | )->setLastModified(DateTime::createFromFormat('U', filemtime($path))); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Controllers/StyleController.php: -------------------------------------------------------------------------------- 1 | 'text/css', 22 | ] 23 | )->setLastModified(DateTime::createFromFormat('U', filemtime($path))); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Facades/Admin.php: -------------------------------------------------------------------------------- 1 | name = $name; 20 | $this->form = $form; 21 | } 22 | 23 | /** 24 | * @return mixed 25 | */ 26 | public function getName() 27 | { 28 | return $this->name; 29 | } 30 | 31 | /** 32 | * @param mixed $name 33 | * @return FormTab 34 | */ 35 | public function name($name) 36 | { 37 | $this->name = $name; 38 | return $this; 39 | } 40 | 41 | 42 | /** 43 | * @param Row|\Closure $closure 44 | * @return $this 45 | */ 46 | public function row($closure) 47 | { 48 | if ($closure instanceof \Closure) { 49 | $row = new Row(); 50 | call_user_func($closure, $row, $this->form); 51 | $this->rows = collect($this->rows)->add($row); 52 | } else { 53 | $this->rows = collect($this->rows)->add($closure); 54 | } 55 | return $this; 56 | } 57 | 58 | public function jsonSerialize() 59 | { 60 | return ['name' => $this->name, 'rows' => $this->rows]; 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/Form/HasRef.php: -------------------------------------------------------------------------------- 1 | successRefData = [ 26 | 'ref' => $ref, 27 | "data" => $data 28 | ]; 29 | return $this; 30 | } 31 | 32 | 33 | public function FormRefDataBuild() 34 | { 35 | return [ 36 | 'successRefData' => $this->successRefData 37 | ]; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/Form/Model.php: -------------------------------------------------------------------------------- 1 | model = $model; 33 | $this->originalModel = $model; 34 | $this->form = $form; 35 | } 36 | 37 | 38 | public function editData(){ 39 | 40 | 41 | return $this->model->findOrFail($this->form->getResourceId()); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/Form/Utils/VIfEval.php: -------------------------------------------------------------------------------- 1 | functionPath = $functionPath; 19 | return $this; 20 | } 21 | 22 | /** 23 | * @param mixed $functionStr 24 | * @return VIfEval 25 | */ 26 | public function functionStr($functionStr) 27 | { 28 | $this->functionStr = $functionStr; 29 | return $this; 30 | } 31 | 32 | /** 33 | * @param array $props 34 | * @return VIfEval 35 | */ 36 | public function props(array $props) 37 | { 38 | $this->props = $props; 39 | return $this; 40 | } 41 | 42 | 43 | public function build() 44 | { 45 | $expression = ""; 46 | if ($this->functionStr) { 47 | $expression = $this->functionStr; 48 | } 49 | if ($this->functionPath) { 50 | abort_if(!file_exists($this->functionPath), 400, "functionPath文件不存在"); 51 | $expression = file_get_contents($this->functionPath); 52 | } 53 | 54 | return [ 55 | "expression" => $expression, 56 | "props" => $this->props 57 | ]; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Grid/Actions.php: -------------------------------------------------------------------------------- 1 | row; 24 | } 25 | 26 | /** 27 | * @param mixed $row 28 | * @return $this 29 | */ 30 | public function row($row) 31 | { 32 | $this->row = $row; 33 | return $this; 34 | } 35 | 36 | /** 37 | * 当前行下标 38 | * @return mixed 39 | */ 40 | public function getKey() 41 | { 42 | return $this->key; 43 | } 44 | 45 | /** 46 | * @param mixed $key 47 | * @return $this 48 | */ 49 | public function key($key) 50 | { 51 | $this->key = $key; 52 | return $this; 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/Grid/Actions/ActionButton.php: -------------------------------------------------------------------------------- 1 | content = $content; 29 | $this->type("text"); 30 | } 31 | 32 | /** 33 | * @param string $content 按钮内容 34 | * @return ActionButton 35 | */ 36 | public static function make($content) 37 | { 38 | return new ActionButton($content); 39 | } 40 | 41 | /** 42 | * @param mixed $uri 43 | * @return $this 44 | */ 45 | public function uri($uri) 46 | { 47 | $this->uri = $uri; 48 | return $this; 49 | } 50 | 51 | /** 52 | * @param string $handler 响应类型 request|route|link 53 | * @return $this 54 | */ 55 | public function handler($handler) 56 | { 57 | abort_if(!in_array($handler, [self::HANDLER_LINK, self::HANDLER_REQUEST, self::HANDLER_ROUTE]), 400, "ActionButton 事件类型错误"); 58 | 59 | $this->handler = $handler; 60 | return $this; 61 | } 62 | 63 | public function route($uri){ 64 | $this->uri = $uri; 65 | $this->handler = self::HANDLER_ROUTE; 66 | return $this; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Grid/Actions/ActionLink.php: -------------------------------------------------------------------------------- 1 | content = $content; 22 | } 23 | 24 | protected static function make($content) 25 | { 26 | return new ActionLink($content); 27 | } 28 | 29 | /** 30 | * @param mixed $uri 31 | * @return $this 32 | */ 33 | public function uri($uri) 34 | { 35 | $this->uri = $uri; 36 | $this->href = $uri; 37 | return $this; 38 | } 39 | 40 | /** 41 | * @param string $handler 响应类型 request|route|link 42 | * @return $this 43 | */ 44 | public function handler($handler) 45 | { 46 | $this->handler = $handler; 47 | return $this; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Grid/Actions/DeleteAction.php: -------------------------------------------------------------------------------- 1 | isDialog = $isDialog; 28 | return $this; 29 | } 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/Grid/Actions/VueRouteAction.php: -------------------------------------------------------------------------------- 1 | name = $name; 31 | return $this; 32 | } 33 | 34 | /** 35 | * @param mixed $path 36 | * @return $this 37 | */ 38 | public function path($path) 39 | { 40 | $this->path = $path; 41 | return $this; 42 | } 43 | 44 | /** 45 | * @param mixed $httpPath 46 | * @return $this 47 | */ 48 | public function httpPath($httpPath) 49 | { 50 | $this->httpPath = $httpPath; 51 | return $this; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/Grid/BatchActions.php: -------------------------------------------------------------------------------- 1 | deleteAction = DeleteAction::make(); 22 | } 23 | 24 | /** 25 | * 添加自定义Action 26 | * @param $action 27 | * @return $this 28 | */ 29 | public function add($action) 30 | { 31 | if ($action instanceof \Closure) { 32 | $this->addActions = collect($this->addActions)->push(call_user_func($action))->all(); 33 | } else { 34 | $this->addActions = collect($this->addActions)->push($action)->all(); 35 | } 36 | 37 | 38 | return $this; 39 | } 40 | 41 | 42 | public function deleteAction() 43 | { 44 | return $this->deleteAction; 45 | } 46 | 47 | /** 48 | * 隐藏删除操作 49 | * @return $this 50 | */ 51 | public function hideDeleteAction() 52 | { 53 | $this->hideDeleteAction = true; 54 | return $this; 55 | } 56 | 57 | /** 58 | * 获取当前Grid选择keys 59 | * @return string 60 | */ 61 | public function getKeys(): string 62 | { 63 | return $this->keys; 64 | } 65 | 66 | 67 | 68 | public function builderActions() 69 | { 70 | $actions = collect($this->actions); 71 | 72 | if (!$this->hideDeleteAction) { 73 | $actions->add($this->deleteAction); 74 | } 75 | foreach ($this->addActions as $addAction) { 76 | $actions->add($addAction); 77 | } 78 | return $actions; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/Grid/BatchActions/DeleteAction.php: -------------------------------------------------------------------------------- 1 | content = $content; 16 | $this->handler = self::HANDLER_REQUEST; 17 | $this->requestMethod = "delete"; 18 | $this->uri = $this->resource . '/' . $this->getKeys(); 19 | $this->message = "确定要批量删除吗?"; 20 | 21 | $this->beforeEmit("tableSetLoading", true); 22 | $this->successEmit("tableReload"); 23 | $this->afterEmit("tableSetLoading", false); 24 | } 25 | 26 | 27 | public static function make($content = "批量删除") 28 | { 29 | return new DeleteAction($content); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/Grid/Column/Attributes.php: -------------------------------------------------------------------------------- 1 | defaultSort = [ 20 | 'sort_prop' => $prop, 21 | 'sort_order' => $order, 22 | 'sort_field' => $field ? $field : $prop 23 | ]; 24 | return $this; 25 | } 26 | 27 | public function getDefaultSort() 28 | { 29 | return $this->defaultSort; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/Grid/Concerns/HasDialog.php: -------------------------------------------------------------------------------- 1 | dialog = new Dialog(); 14 | call_user_func($closure, $this->dialog); 15 | return $this; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/Grid/Concerns/HasFilter.php: -------------------------------------------------------------------------------- 1 | filter->execute($toArray); 23 | } 24 | 25 | 26 | public function filter(Closure $callback) 27 | { 28 | call_user_func($callback, $this->filter); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Grid/Concerns/HasPageAttributes.php: -------------------------------------------------------------------------------- 1 | ,prev, pager, next, jumper"; 13 | 14 | protected $pageBackground = true; 15 | 16 | protected $hidePage = false; 17 | 18 | /** 19 | * 设置分页布局,子组件名用逗号分隔 20 | * prev, pager, next, jumper, ->, total 21 | * @param string $layout 22 | * @return $this 23 | */ 24 | public function pageLayout(string $layout) 25 | { 26 | $this->pageLayout = $layout; 27 | return $this; 28 | } 29 | 30 | 31 | /** 32 | * 每页显示个数选择器的选项设置 33 | * @param array $sizes 34 | * @return $this 35 | */ 36 | public function pageSizes($sizes) 37 | { 38 | $this->pageSizes = $sizes; 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * 每页显示条目个数 45 | * @param int $perPage 46 | * @return $this 47 | */ 48 | public function perPage($perPage) 49 | { 50 | $this->perPage = $perPage; 51 | 52 | return $this; 53 | } 54 | 55 | /** 56 | * 是否为分页按钮添加背景色 57 | * @param bool $pageBackground 58 | * @return $this 59 | */ 60 | public function pageBackground(bool $pageBackground = true) 61 | { 62 | $this->pageBackground = $pageBackground; 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * @return int 69 | */ 70 | public function getPerPage(): int 71 | { 72 | return $this->perPage; 73 | } 74 | 75 | /** 76 | * @return bool 77 | */ 78 | public function isHidePage(): bool 79 | { 80 | return $this->hidePage; 81 | } 82 | 83 | /** 84 | * 隐藏分页 85 | * @return $this 86 | */ 87 | public function hidePage() 88 | { 89 | $this->hidePage = true; 90 | if ($this->model) { 91 | $this->model->usePaginate(false); 92 | } 93 | return $this; 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/Grid/Filter/Between.php: -------------------------------------------------------------------------------- 1 | column)) { 21 | return; 22 | } 23 | 24 | $this->value = Arr::get($inputs, $this->column); 25 | 26 | if (!is_array($this->value)) { 27 | return; 28 | } 29 | 30 | $value = array_filter($this->value, function ($val) { 31 | return $val !== ''; 32 | }); 33 | 34 | if (empty($value)) { 35 | return; 36 | } 37 | 38 | if (!isset($value[0])) { 39 | return $this->buildCondition($this->column, '<=', $value[0]); 40 | } 41 | 42 | if (!isset($value[1])) { 43 | return $this->buildCondition($this->column, '>=', $value[1]); 44 | } 45 | 46 | $this->query = 'whereBetween'; 47 | 48 | return $this->buildCondition($this->column, $this->value); 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/Grid/Filter/Date.php: -------------------------------------------------------------------------------- 1 | column); 24 | 25 | if (is_null($value)) { 26 | return; 27 | } 28 | 29 | $this->value = $value; 30 | 31 | return $this->buildCondition($this->column, '>=', $this->value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Grid/Filter/Ilike.php: -------------------------------------------------------------------------------- 1 | column); 24 | 25 | if (is_null($value)) { 26 | return; 27 | } 28 | 29 | $this->value = (array)$value; 30 | 31 | return $this->buildCondition($this->column, $this->value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Grid/Filter/Like.php: -------------------------------------------------------------------------------- 1 | column); 29 | 30 | if (is_array($value)) { 31 | $value = array_filter($value); 32 | } 33 | 34 | if (is_null($value) || empty($value)) { 35 | return; 36 | } 37 | 38 | $this->value = $value; 39 | 40 | $expr = str_replace('{value}', $this->value, $this->exprFormat); 41 | 42 | return $this->buildCondition($this->column, $this->operator, $expr); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Grid/Filter/Lt.php: -------------------------------------------------------------------------------- 1 | column); 24 | 25 | if (is_null($value)) { 26 | return; 27 | } 28 | 29 | $this->value = $value; 30 | 31 | return $this->buildCondition($this->column, '<=', $this->value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Grid/Filter/Month.php: -------------------------------------------------------------------------------- 1 | column); 15 | 16 | if (!isset($value)) { 17 | return; 18 | } 19 | 20 | $this->value = $value; 21 | 22 | return $this->buildCondition($this->column, '!=', $this->value); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Grid/Filter/NotIn.php: -------------------------------------------------------------------------------- 1 | key = $key; 37 | $this->label = $label ? $label : Str::studly($key); 38 | 39 | $this->queries = new Collection(); 40 | } 41 | 42 | /** 43 | * Get label. 44 | * 45 | * @return string 46 | */ 47 | public function getLabel() 48 | { 49 | return $this->label; 50 | } 51 | 52 | /** 53 | * Get model query conditions. 54 | * 55 | * @return array 56 | */ 57 | public function condition() 58 | { 59 | return $this->queries->map(function ($query) { 60 | return [$query['method'] => $query['arguments']]; 61 | })->toArray(); 62 | } 63 | 64 | 65 | /** 66 | * @param string $method 67 | * @param array $arguments 68 | * 69 | * @return $this 70 | */ 71 | public function __call($method, $arguments) 72 | { 73 | $this->queries->push(compact('method', 'arguments')); 74 | 75 | return $this; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Grid/Filter/StartsWith.php: -------------------------------------------------------------------------------- 1 | where = $query; 28 | 29 | $this->label = $this->formatLabel($label); 30 | $this->column = $column ?: static::getQueryHash($query, $this->label); 31 | 32 | $this->component = Input::make(); 33 | } 34 | 35 | /** 36 | * Get the hash string of query closure. 37 | * @param \Closure $closure 38 | * @param string $label 39 | * @return string 40 | * @throws \ReflectionException 41 | */ 42 | public static function getQueryHash(\Closure $closure, $label = '') 43 | { 44 | $reflection = new ReflectionFunction($closure); 45 | 46 | return md5($reflection->getFileName() . $reflection->getStartLine() . $reflection->getEndLine() . $label); 47 | } 48 | 49 | /** 50 | * Get condition of this filter. 51 | * @param $inputs 52 | * @return array|void 53 | * @throws \ReflectionException 54 | */ 55 | public function condition($inputs) 56 | { 57 | 58 | $value = Arr::get($inputs, $this->column ?: static::getQueryHash($this->where, $this->label)); 59 | 60 | if (is_null($value)) { 61 | return; 62 | } 63 | 64 | $this->input = $this->value = $value; 65 | 66 | return $this->buildCondition($this->where->bindTo($this)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Grid/Filter/Year.php: -------------------------------------------------------------------------------- 1 | 'hasChildren', 'children' => 'children']; 58 | 59 | 60 | public $hideActions=false; 61 | public $actionWidth; 62 | public $actionLabel = "操作"; 63 | public $actionFixed; 64 | public $actionAlign = "left"; 65 | 66 | public $selection = false; 67 | 68 | public $dataVuex = false; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/Grid/Tools/CreateButton.php: -------------------------------------------------------------------------------- 1 | isDialog = $isDialog; 25 | return $this; 26 | } 27 | 28 | 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/Grid/Tools/QuickSearch.php: -------------------------------------------------------------------------------- 1 | $this->searchKey, 23 | 'placeholder' => $this->placeholder, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Grid/Tools/ToolButton.php: -------------------------------------------------------------------------------- 1 | content = $content; 20 | } 21 | 22 | /** 23 | * @param string $content 按钮内容 24 | * @return ToolButton 25 | */ 26 | public static function make($content) 27 | { 28 | return new ToolButton($content); 29 | } 30 | 31 | /** 32 | * @param mixed $uri 33 | * @return $this 34 | */ 35 | public function uri($uri) 36 | { 37 | $this->uri = $uri; 38 | return $this; 39 | } 40 | 41 | /** 42 | * @param string $handler 响应类型 request|route|link 43 | * @return $this 44 | */ 45 | public function handler($handler) 46 | { 47 | $this->handler = $handler; 48 | return $this; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/Layout/Buildable.php: -------------------------------------------------------------------------------- 1 | row($content); 26 | } 27 | 28 | public function row($content) 29 | { 30 | 31 | if ($content instanceof Closure) { 32 | $row = new Row(); 33 | call_user_func($content, $row); 34 | $this->addRow($row); 35 | } else { 36 | $row = new Row($content); 37 | $this->addRow($row); 38 | } 39 | return $this; 40 | } 41 | 42 | 43 | 44 | protected function addRow(Row $row) 45 | { 46 | $this->rows[] = $row; 47 | } 48 | 49 | /** 50 | * @param bool $showHeader 51 | * @return $this 52 | */ 53 | public function showHeader($showHeader = true) 54 | { 55 | $this->showHeader = $showHeader; 56 | return $this; 57 | } 58 | 59 | /** 60 | * @param string $title 61 | * @return $this 62 | */ 63 | public function title($title) 64 | { 65 | $this->title = $title; 66 | return $this; 67 | } 68 | 69 | /** 70 | * @param string $description 71 | * @return $this 72 | */ 73 | public function description($description) 74 | { 75 | $this->description = $description; 76 | return $this; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | guest() && !$this->shouldPassThrough($request)) { 23 | return redirect()->guest($redirectTo); 24 | } 25 | 26 | return $next($request); 27 | } 28 | 29 | /** 30 | * Determine if the request has a URI that should pass through verification. 31 | * 32 | * @param \Illuminate\Http\Request $request 33 | * 34 | * @return bool 35 | */ 36 | protected function shouldPassThrough($request) 37 | { 38 | $excepts = config('admin.auth.excepts', [ 39 | 'auth/login', 40 | 'auth/logout', 41 | 'scripts/*', 42 | 'styles/*', 43 | ]); 44 | 45 | return collect($excepts) 46 | ->map('admin_base_path') 47 | ->contains(function ($except) use ($request) { 48 | if ($except !== '/') { 49 | $except = trim($except, '/'); 50 | } 51 | 52 | return $request->is($except); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Middleware/Bootstrap.php: -------------------------------------------------------------------------------- 1 | $path]); 14 | 15 | if ($domain = config('admin.route.domain')) { 16 | config(['session.domain' => $domain]); 17 | } 18 | 19 | return $next($request); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Traits/AdminBuilder.php: -------------------------------------------------------------------------------- 1 | hideAttrs)->push("hideAttrs")->toArray(); 16 | foreach ($this as $key => $val) { 17 | if (!in_array($key, $hide)) { 18 | $data[$key] = $val; 19 | } 20 | } 21 | return $data; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Traits/Resizable.php: -------------------------------------------------------------------------------- 1 | attributes[$attribute])) { 21 | return ''; 22 | } 23 | 24 | // We take image from posts field 25 | $image = $this->attributes[$attribute]; 26 | 27 | $thumbnail = $this->getThumbnail($image, $type); 28 | 29 | return \Illuminate\Support\Facades\Storage::disk(config('admin.upload.disk'))->exists($thumbnail) ? $thumbnail : $image; 30 | } 31 | 32 | /** 33 | * Generate thumbnail URL. 34 | * 35 | * @param $image 36 | * @param $type 37 | * 38 | * @return string 39 | */ 40 | public function getThumbnail($image, $type) 41 | { 42 | // We need to get extension type ( .jpeg , .png ...) 43 | $ext = pathinfo($image, PATHINFO_EXTENSION); 44 | 45 | // We remove extension from file name so we can append thumbnail type 46 | $name = Str::replaceLast('.'.$ext, '', $image); 47 | 48 | // We merge original name + type + extension 49 | return $name.'-'.$type.'.'.$ext; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Traits/ShouldSnakeAttributes.php: -------------------------------------------------------------------------------- 1 | model instanceof GridModel) ? 28 | $this->model->eloquent() : $this->model; 29 | 30 | $class = get_class($model); 31 | 32 | return static::$snakeAttributes = $class::$snakeAttributes; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require("laravel-mix"); 2 | 3 | 4 | 5 | mix.config.webpackConfig = { 6 | output: { 7 | publicPath: "/vendor/laravel-vue-admin/", 8 | } 9 | }; 10 | 11 | 12 | mix 13 | .js("./resources/js/app.js", "public") 14 | .extract(["axios", "vue", "vuex", "vue-router", "element-ui"]) 15 | .setResourceRoot("/vendor/laravel-vue-admin") 16 | .setPublicPath("public") 17 | .copy("public", "../public/vendor/laravel-vue-admin") 18 | .webpackConfig({ 19 | resolve: { 20 | alias: { 21 | "@": path.resolve(__dirname, "resources/js/"), 22 | }, 23 | }, 24 | }) 25 | .options({ 26 | extractVueStyles: false, 27 | processCssUrls: false, 28 | }) 29 | .disableNotifications().version(); 30 | --------------------------------------------------------------------------------