├── .example.env ├── .gitattributes ├── .gitignore ├── LICENSE ├── LICENSE.txt ├── README.md ├── SECURITY.md ├── app ├── .htaccess ├── AppService.php ├── ExceptionHandle.php ├── admin │ ├── common.php │ ├── config │ │ ├── admin.php │ │ ├── app.php │ │ ├── captcha.php │ │ └── view.php │ ├── controller │ │ ├── AdminBaseController.php │ │ ├── AdminLogController.php │ │ ├── AdminMenuController.php │ │ ├── AdminRoleController.php │ │ ├── AdminUserController.php │ │ ├── AuthController.php │ │ ├── DatabaseController.php │ │ ├── ErrorController.php │ │ ├── FileController.php │ │ ├── GenerateController.php │ │ ├── IndexController.php │ │ ├── SettingController.php │ │ ├── SettingGroupController.php │ │ ├── TestController.php │ │ ├── UserController.php │ │ └── UserLevelController.php │ ├── event.php │ ├── exception │ │ └── AdminServiceException.php │ ├── listener │ │ ├── AdminUserLogin.php │ │ └── AdminUserLogout.php │ ├── middleware.php │ ├── model │ │ ├── AdminBaseModel.php │ │ ├── AdminLog.php │ │ ├── AdminLogData.php │ │ ├── AdminMenu.php │ │ ├── AdminRole.php │ │ └── AdminUser.php │ ├── provider.php │ ├── service │ │ ├── AdminBaseService.php │ │ ├── AdminLogService.php │ │ ├── AdminRoleService.php │ │ ├── AdminUserService.php │ │ ├── AuthService.php │ │ └── PageService.php │ ├── traits │ │ ├── AdminAuthTrait.php │ │ ├── AdminPhpOffice.php │ │ ├── AdminSettingForm.php │ │ ├── AdminTreeTrait.php │ │ └── SettingContent.php │ ├── validate │ │ ├── AdminBaseValidate.php │ │ ├── AdminMenuValidate.php │ │ ├── AdminRoleValidate.php │ │ └── AdminUserValidate.php │ └── view │ │ ├── admin_log │ │ ├── detail.html │ │ └── index.html │ │ ├── admin_menu │ │ ├── add.html │ │ └── index.html │ │ ├── admin_role │ │ ├── access.html │ │ ├── add.html │ │ └── index.html │ │ ├── admin_user │ │ ├── add.html │ │ ├── index.html │ │ └── profile.html │ │ ├── auth │ │ ├── captcha.html │ │ ├── gee_test.html │ │ ├── login.html │ │ └── login_bg.html │ │ ├── database │ │ ├── table.html │ │ └── view.html │ │ ├── error │ │ ├── 403.html │ │ ├── 404.html │ │ └── 500.html │ │ ├── file │ │ ├── index.html │ │ └── upload.html │ │ ├── generate │ │ ├── add.html │ │ ├── css.html │ │ ├── form.html │ │ ├── index.html │ │ └── template.html │ │ ├── index │ │ ├── chart1.html │ │ ├── chart2.html │ │ ├── chart3.html │ │ ├── index.html │ │ ├── top_widget1.html │ │ └── top_widget2.html │ │ ├── public │ │ ├── base.html │ │ ├── change_page.html │ │ ├── content_header.html │ │ ├── control_sidebar.html │ │ ├── footer.html │ │ ├── head_css.html │ │ ├── head_js.html │ │ ├── layer_base.html │ │ ├── navbar │ │ │ ├── message.html │ │ │ ├── nav.html │ │ │ ├── navbar.html │ │ │ ├── notification.html │ │ │ ├── search_form.html │ │ │ ├── sidebar_button.html │ │ │ └── user_menu.html │ │ └── sidebar.html │ │ ├── setting │ │ ├── add.html │ │ ├── all.html │ │ ├── config_type.html │ │ ├── index.html │ │ └── show.html │ │ ├── setting_group │ │ ├── add.html │ │ └── index.html │ │ ├── template │ │ ├── content.html │ │ └── layer_content.html │ │ ├── test │ │ ├── add.html │ │ └── index.html │ │ ├── user │ │ ├── add.html │ │ └── index.html │ │ └── user_level │ │ ├── add.html │ │ └── index.html ├── api │ ├── common.php │ ├── config │ │ └── api.php │ ├── controller │ │ ├── ApiBaseController.php │ │ ├── AuthController.php │ │ ├── IndexController.php │ │ ├── TestController.php │ │ ├── TokenController.php │ │ ├── UserController.php │ │ └── UserLevelController.php │ ├── exception │ │ └── ApiServiceException.php │ ├── middleware.php │ ├── middleware │ │ └── AllowCrossDomain.php │ ├── service │ │ ├── ApiBaseService.php │ │ ├── AuthService.php │ │ ├── TestService.php │ │ ├── TokenService.php │ │ ├── UserLevelService.php │ │ └── UserService.php │ └── traits │ │ ├── ApiAuthTrait.php │ │ └── ApiThrottleTrait.php ├── command │ ├── GenerateAppKey.php │ ├── GenerateJwtKey.php │ ├── InitEnv.php │ ├── ResetAdminPassword.php │ └── Test.php ├── common.php ├── common │ ├── exception │ │ ├── CommonServiceException.php │ │ └── tpl │ │ │ └── think_exception.tpl │ ├── model │ │ ├── CommonBaseModel.php │ │ ├── Setting.php │ │ ├── SettingGroup.php │ │ ├── Test.php │ │ ├── User.php │ │ └── UserLevel.php │ ├── service │ │ ├── CommonBaseService.php │ │ ├── DateService.php │ │ └── StringService.php │ └── validate │ │ ├── CommonBaseValidate.php │ │ ├── SettingGroupValidate.php │ │ ├── SettingValidate.php │ │ ├── TestValidate.php │ │ ├── UserLevelValidate.php │ │ └── UserValidate.php ├── event.php ├── index │ ├── common.php │ ├── config │ │ └── view.php │ ├── controller │ │ ├── AuthController.php │ │ ├── IndexBaseController.php │ │ ├── IndexController.php │ │ └── UserController.php │ ├── exception │ │ └── IndexServiceException.php │ ├── middleware.php │ ├── service │ │ ├── AuthService.php │ │ └── IndexBaseService.php │ ├── traits │ │ └── IndexAuthTrait.php │ └── view │ │ ├── auth │ │ └── login.html │ │ ├── index │ │ ├── about.html │ │ ├── index.html │ │ └── product.html │ │ └── user │ │ └── index.html ├── middleware.php ├── provider.php └── service.php ├── composer.json ├── config ├── app.php ├── cache.php ├── captcha.php ├── console.php ├── cookie.php ├── database.php ├── filesystem.php ├── lang.php ├── log.php ├── map.php ├── middleware.php ├── route.php ├── session.php ├── trace.php └── view.php ├── database ├── example │ └── README.md └── migrations │ ├── 20191001081329_setting.php │ ├── 20191001081340_setting_group.php │ ├── 20200804023050_admin_user.php │ ├── 20200806095505_admin_menu.php │ ├── 20200806100423_admin_role.php │ ├── 20200806100513_admin_log.php │ ├── 20200806100516_admin_log_data.php │ ├── 20200827064827_user.php │ ├── 20210219080541_user_level.php │ └── 20210908031808_test.php ├── extend ├── generate │ ├── AdminControllerBuild.php │ ├── AdminMenuBuild.php │ ├── AdminViewBuild.php │ ├── ApiControllerBuild.php │ ├── ApiServiceBuild.php │ ├── Build.php │ ├── Generate.php │ ├── ModelBuild.php │ ├── ValidateBuild.php │ ├── exception │ │ └── GenerateException.php │ ├── field │ │ ├── Color.php │ │ ├── Date.php │ │ ├── DateRange.php │ │ ├── Datetime.php │ │ ├── DatetimeRange.php │ │ ├── Editor.php │ │ ├── Email.php │ │ ├── Field.php │ │ ├── File.php │ │ ├── Icon.php │ │ ├── IdCard.php │ │ ├── Image.php │ │ ├── Ip.php │ │ ├── Map.php │ │ ├── Mobile.php │ │ ├── MultiFile.php │ │ ├── MultiImage.php │ │ ├── MultiSelect.php │ │ ├── Number.php │ │ ├── Password.php │ │ ├── Select.php │ │ ├── SwitchField.php │ │ ├── Text.php │ │ ├── Textarea.php │ │ ├── Time.php │ │ ├── TimeRange.php │ │ ├── Url.php │ │ ├── Video.php │ │ ├── Year.php │ │ ├── YearMonth.php │ │ ├── YearMonthRange.php │ │ └── YearRange.php │ ├── stub │ │ ├── admin_controller │ │ │ ├── AdminController.stub │ │ │ ├── action_add.stub │ │ │ ├── action_del.stub │ │ │ ├── action_disable.stub │ │ │ ├── action_edit.stub │ │ │ ├── action_enable.stub │ │ │ ├── action_export.stub │ │ │ ├── action_import.stub │ │ │ ├── action_index.stub │ │ │ ├── relation_assign_1.stub │ │ │ ├── relation_data_list.stub │ │ │ ├── relation_delete.stub │ │ │ └── relation_with.stub │ │ ├── admin_view │ │ │ ├── add │ │ │ │ ├── add.stub │ │ │ │ ├── customer_multi_select_data.stub │ │ │ │ ├── customer_select_data.stub │ │ │ │ └── relation_select_data.stub │ │ │ └── index │ │ │ │ ├── create.stub │ │ │ │ ├── del1.stub │ │ │ │ ├── del2.stub │ │ │ │ ├── enable1.stub │ │ │ │ ├── enable2.stub │ │ │ │ ├── export.stub │ │ │ │ ├── filter.stub │ │ │ │ ├── import.stub │ │ │ │ ├── index.stub │ │ │ │ ├── refresh.stub │ │ │ │ ├── select1.stub │ │ │ │ ├── select2.stub │ │ │ │ └── sort.stub │ │ ├── api_controller │ │ │ ├── ApiController.stub │ │ │ ├── api_add.stub │ │ │ ├── api_del.stub │ │ │ ├── api_disable.stub │ │ │ ├── api_edit.stub │ │ │ ├── api_enable.stub │ │ │ ├── api_index.stub │ │ │ └── api_info.stub │ │ ├── api_service │ │ │ ├── ApiService.stub │ │ │ ├── api_add.stub │ │ │ ├── api_del.stub │ │ │ ├── api_disable.stub │ │ │ ├── api_edit.stub │ │ │ ├── api_enable.stub │ │ │ ├── api_index.stub │ │ │ └── api_info.stub │ │ ├── model │ │ │ ├── Model.stub │ │ │ ├── getter_setter_date.stub │ │ │ ├── getter_setter_datetime.stub │ │ │ ├── getter_setter_multi_select.stub │ │ │ ├── getter_setter_select.stub │ │ │ ├── getter_setter_switch.stub │ │ │ └── relation.stub │ │ └── validate │ │ │ └── Validate.stub │ ├── traits │ │ ├── Tools.php │ │ └── Tree.php │ └── validate │ │ ├── Color16.php │ │ ├── ComplexPassword.php │ │ ├── Email.php │ │ ├── IdCard.php │ │ ├── Ip.php │ │ ├── Ipv4.php │ │ ├── Ipv6.php │ │ ├── MiddlePassword.php │ │ ├── Mobile.php │ │ ├── Number.php │ │ ├── Number6.php │ │ ├── Required.php │ │ ├── Rule.php │ │ ├── SimplePassword.php │ │ └── Url.php └── util │ ├── geetest │ └── GeeTest.php │ ├── jwt │ ├── Example.php │ ├── Jwt.php │ ├── JwtException.php │ ├── README.md │ ├── private.key │ └── public.key │ └── safe │ └── SafeCookie.php ├── public ├── .htaccess ├── favicon.ico ├── index.php ├── robots.txt ├── router.php ├── static │ ├── admin │ │ ├── css │ │ │ ├── access.css │ │ │ ├── admin.css │ │ │ └── adminlte.min.css │ │ ├── images │ │ │ ├── avatar.png │ │ │ ├── login-default-bg.jpg │ │ │ └── logo.png │ │ ├── js │ │ │ ├── admin.js │ │ │ ├── adminlte.min.js │ │ │ ├── requrest.js │ │ │ ├── upload.js │ │ │ └── validate.js │ │ └── plugins │ │ │ ├── bootstrap-colorpicker │ │ │ ├── css │ │ │ │ └── bootstrap-colorpicker.min.css │ │ │ └── js │ │ │ │ └── bootstrap-colorpicker.min.js │ │ │ ├── bootstrap-number │ │ │ └── bootstrap-number.min.js │ │ │ ├── bootstrap-switch │ │ │ ├── css │ │ │ │ └── bootstrap3 │ │ │ │ │ └── bootstrap-switch.min.css │ │ │ └── js │ │ │ │ └── bootstrap-switch.min.js │ │ │ ├── bootstrap │ │ │ └── js │ │ │ │ └── bootstrap.bundle.min.js │ │ │ ├── bs-custom-file-input │ │ │ └── bs-custom-file-input.min.js │ │ │ ├── clipboard │ │ │ └── clipboard.min.js │ │ │ ├── echarts │ │ │ └── echarts.simple.min.js │ │ │ ├── fileinput │ │ │ ├── css │ │ │ │ ├── fileinput-rtl.min.css │ │ │ │ └── fileinput.min.css │ │ │ ├── img │ │ │ │ ├── loading-sm.gif │ │ │ │ └── loading.gif │ │ │ ├── js │ │ │ │ ├── fileinput.min.js │ │ │ │ ├── locales │ │ │ │ │ ├── LANG.js │ │ │ │ │ ├── ja.js │ │ │ │ │ ├── kr.js │ │ │ │ │ ├── zh-TW.js │ │ │ │ │ └── zh.js │ │ │ │ └── plugins │ │ │ │ │ ├── piexif.min.js │ │ │ │ │ ├── purify.min.js │ │ │ │ │ └── sortable.min.js │ │ │ └── themes │ │ │ │ ├── bs5 │ │ │ │ ├── theme.js │ │ │ │ └── theme.min.js │ │ │ │ ├── explorer-fa │ │ │ │ ├── theme.css │ │ │ │ ├── theme.js │ │ │ │ ├── theme.min.css │ │ │ │ └── theme.min.js │ │ │ │ ├── explorer-fas │ │ │ │ ├── theme.css │ │ │ │ ├── theme.js │ │ │ │ ├── theme.min.css │ │ │ │ └── theme.min.js │ │ │ │ ├── explorer │ │ │ │ ├── theme.css │ │ │ │ ├── theme.js │ │ │ │ ├── theme.min.css │ │ │ │ └── theme.min.js │ │ │ │ ├── fa │ │ │ │ ├── theme.js │ │ │ │ └── theme.min.js │ │ │ │ ├── fas │ │ │ │ ├── theme.js │ │ │ │ └── theme.min.js │ │ │ │ └── gly │ │ │ │ ├── theme.js │ │ │ │ └── theme.min.js │ │ │ ├── fontawesome-free │ │ │ ├── css │ │ │ │ └── all.min.css │ │ │ └── webfonts │ │ │ │ ├── fa-brands-400.woff2 │ │ │ │ ├── fa-regular-400.woff2 │ │ │ │ └── fa-solid-900.woff2 │ │ │ ├── fontawesome-iconpicker │ │ │ ├── css │ │ │ │ └── fontawesome-iconpicker.min.css │ │ │ └── js │ │ │ │ └── fontawesome-iconpicker.min.js │ │ │ ├── gee-test │ │ │ └── gee-test.min.js │ │ │ ├── icheck-bootstrap │ │ │ ├── LICENSE │ │ │ └── icheck-bootstrap.min.css │ │ │ ├── jquery-input-file-text │ │ │ └── jquery-input-file-text.js │ │ │ ├── jquery-pjax │ │ │ └── jquery.pjax.js │ │ │ ├── jquery-validation │ │ │ ├── jquery.validate.min.js │ │ │ └── localization │ │ │ │ ├── messages_zh.min.js │ │ │ │ └── messages_zh_TW.min.js │ │ │ ├── jquery-viewer │ │ │ └── jquery-viewer.min.js │ │ │ ├── jquery │ │ │ └── jquery.min.js │ │ │ ├── js-cookie │ │ │ └── js.cookie-2.2.0.min.js │ │ │ ├── js-tree │ │ │ ├── jstree.min.js │ │ │ └── themes │ │ │ │ ├── default-dark │ │ │ │ ├── 32px.png │ │ │ │ ├── 40px.png │ │ │ │ ├── style.min.css │ │ │ │ └── throbber.gif │ │ │ │ └── default │ │ │ │ ├── 32px.png │ │ │ │ ├── 40px.png │ │ │ │ ├── style.min.css │ │ │ │ └── throbber.gif │ │ │ ├── laydate │ │ │ ├── laydate.js │ │ │ └── theme │ │ │ │ └── default │ │ │ │ ├── font │ │ │ │ ├── iconfont.eot │ │ │ │ ├── iconfont.svg │ │ │ │ ├── iconfont.ttf │ │ │ │ └── iconfont.woff │ │ │ │ └── laydate.css │ │ │ ├── layer │ │ │ ├── layer.js │ │ │ ├── mobile │ │ │ │ ├── layer.js │ │ │ │ └── need │ │ │ │ │ └── layer.css │ │ │ └── theme │ │ │ │ └── default │ │ │ │ ├── icon-ext.png │ │ │ │ ├── icon.png │ │ │ │ ├── layer.css │ │ │ │ ├── loading-0.gif │ │ │ │ ├── loading-1.gif │ │ │ │ └── loading-2.gif │ │ │ ├── nprogress │ │ │ ├── nprogress.css │ │ │ └── nprogress.js │ │ │ ├── pjax │ │ │ └── jquery.pjax.js │ │ │ ├── select2-bootstrap4-theme │ │ │ └── select2-bootstrap4.min.css │ │ │ ├── select2 │ │ │ ├── css │ │ │ │ └── select2.min.css │ │ │ └── js │ │ │ │ ├── i18n │ │ │ │ ├── en.js │ │ │ │ ├── zh-CN.js │ │ │ │ └── zh-TW.js │ │ │ │ └── select2.min.js │ │ │ ├── viewer │ │ │ ├── viewer.min.css │ │ │ └── viewer.min.js │ │ │ └── wangEditor │ │ │ └── wangEditor.min.js │ └── index │ │ ├── css │ │ └── adminlte.min.css │ │ ├── images │ │ ├── avatar.png │ │ └── user_level_default.png │ │ ├── js │ │ ├── adminlte.min.js │ │ └── index.js │ │ └── plugins │ │ ├── bootstrap │ │ └── js │ │ │ └── bootstrap.bundle.min.js │ │ ├── fontawesome-free │ │ ├── css │ │ │ └── all.min.css │ │ └── webfonts │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.woff2 │ │ │ └── fa-solid-900.woff2 │ │ ├── icheck-bootstrap │ │ ├── LICENSE │ │ └── icheck-bootstrap.min.css │ │ ├── jquery-validation │ │ ├── jquery.validate.min.js │ │ └── localization │ │ │ └── messages_zh.min.js │ │ ├── jquery │ │ └── jquery.min.js │ │ └── sweetalert2 │ │ ├── sweetalert2.all.min.js │ │ └── sweetalert2.min.css └── uploads │ └── uploads │ └── 20211105 │ ├── 09f88c2c15fd9ea2eaebefa94fc82519.png │ ├── 393c19a1f90e320dde433eb064d0bc37.png │ ├── 5606eb6dda163840c30eb58ba82bbfca.png │ ├── 6c0ef20747bac6a8f0b1f75d78327806.jpg │ ├── 943dafd0517fecce981b6e3c06e4ac87.png │ ├── c8ef52b10a8b478f31bf8f2763b9478e.png │ ├── d62acc7db724543cdab5635c03fa4bab.png │ └── f5ffbf069f86c0bbeef12754c236c053.png ├── route └── app.php └── think /.example.env: -------------------------------------------------------------------------------- 1 | APP_DEBUG=true [APP] DEFAULT_TIMEZONE=Asia/Shanghai HOST=https://wwww.bearadmin.com APP_KEY= [DATABASE] TYPE=mysql HOSTNAME=127.0.0.1 DATABASE=bear_admin USERNAME=root PASSWORD=root HOSTPORT=3306 CHARSET=utf8mb4 DEBUG=true [CACHE] DRIVER=file [REDIS] REDIS_HOST=127.0.0.1 REDIS_PORT=6379 REDIS_PASSWORD= REDIS_SELECT=0 [LANG] default_lang=zh-cn [FILESYSTEM] driver=public [API] HTTP_CODE_SYNC=true ALLOW_CROSS_DOMAIN=true JWT_KEY= JWT_EXP=3600 ENABLE_REFRESH_TOKEN=true REFRESH_TOKEN_EXP=1296000 REUSE_CHECK=true JWT_ISS=s JWT_AUD=a TOKEN_POSITION=header TOKEN_FIELD=token -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=PHP 2 | *.css linguist-language=PHP 3 | *.html linguist-language=PHP -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | runtime 3 | .ENV 4 | composer.phar 5 | composer.lock 6 | Thumbs.db 7 | *.DS_Store 8 | .idea 9 | .vscode 10 | import -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 3 | 版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) 4 | All rights reserved。 5 | ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 6 | 7 | Apache Licence是著名的非盈利开源组织Apache采用的协议。 8 | 该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, 9 | 允许代码修改,再作为开源或商业软件发布。需要满足 10 | 的条件: 11 | 1. 需要给代码的用户一份Apache Licence ; 12 | 2. 如果你修改了代码,需要在被修改的文件中说明; 13 | 3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 14 | 带有原来代码中的协议,商标,专利声明和其他原来作者规 15 | 定需要包含的说明; 16 | 4. 如果再发布的产品中包含一个Notice文件,则在Notice文 17 | 件中需要带有本协议内容。你可以在Notice中增加自己的 18 | 许可,但不可以表现为对Apache Licence构成更改。 19 | 具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please report security issues to `yupoxiong [at] gmail.com`. -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /app/AppService.php: -------------------------------------------------------------------------------- 1 | [ 10 | // 后台名称 11 | 'name'=>'XX后台系统', 12 | // 后台简称 13 | 'short_name'=>'后台', 14 | // 后台作者 15 | 'author'=>'xx科技', 16 | // 作者网站 17 | 'website'=>'#', 18 | // 后台版本 19 | 'version'=>'0.1', 20 | // 后台LOGO 21 | 'logo'=>'/static/admin/images/logo.png', 22 | ], 23 | // 登录设置:后台登录相关设置 24 | 'login'=>[ 25 | // 登录token验证 26 | 'token'=>'0', 27 | // 验证码 28 | 'captcha'=>'1', 29 | // 登录背景 30 | 'background'=>'/static/admin/images/login-default-bg.jpg', 31 | // 极验ID 32 | 'geetest_id'=>'66cfc0f309e368364b753dad7d2f67f2', 33 | // 极验KEY 34 | 'geetest_key'=>'99750f86ec232c997efaff56c7b30cd3', 35 | // 登录重试限制 36 | 'login_limit'=>'1', 37 | // 限制最大次数 38 | 'login_max_count'=>'5', 39 | // 禁止登录时长(小时) 40 | 'login_limit_hour'=>'2', 41 | ], 42 | // 安全设置:安全相关配置 43 | 'safe'=>[ 44 | // 加密key 45 | 'admin_key'=>'89ce3272dc949fc3698fe7108d1dbe37', 46 | // SessionKeyUid 47 | 'store_uid_key'=>'admin_user_id', 48 | // SessionKeySign 49 | 'store_sign_key'=>'admin_user_sign', 50 | // 后台用户密码强度检测 51 | 'password_check'=>'0', 52 | // 密码安全强度等级 53 | 'password_level'=>'2', 54 | // 单设备登录 55 | 'one_device_login'=>'1', 56 | // CSRFToken检测 57 | 'check_token'=>'1', 58 | // CSRFToken验证方法 59 | 'check_token_action_list'=>'add,edit,del,import,profile,update', 60 | ], 61 | ]; -------------------------------------------------------------------------------- /app/admin/config/app.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | $config = [ 8 | 9 | 'default_ajax_return' => 'html', 10 | ]; 11 | if (!env('app_debug')) { 12 | // 自定后台义异常页面的模板文件 13 | $config['exception_tmpl'] = app()->getAppPath() . 'view/error/500.html'; 14 | } 15 | return $config; -------------------------------------------------------------------------------- /app/admin/config/captcha.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | return [ 8 | // 验证码字体大小 9 | 'fontSize' => 30, 10 | // 验证码位数 11 | 'length' => 4, 12 | // 关闭验证码杂点 13 | 'useNoise' => false, 14 | // 只用数字 15 | 'codeSet' => '0123456789', 16 | ]; 17 | -------------------------------------------------------------------------------- /app/admin/config/view.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | return [ 8 | // 模版替换参数 9 | 'tpl_replace_string' => [ 10 | '__STATIC__' => '/static', 11 | '__ADMIN_STATIC__' => '/static/admin', 12 | '__ADMIN_JS__' => '/static/admin/js', 13 | '__ADMIN_CSS__' => '/static/admin/css', 14 | '__ADMIN_IMAGES__' => '/static/admin/images', 15 | '__ADMIN_PLUGINS__' => '/static/admin/plugins', 16 | ] 17 | ]; 18 | -------------------------------------------------------------------------------- /app/admin/controller/ErrorController.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\controller; 10 | 11 | use Exception; 12 | 13 | class ErrorController extends AdminBaseController 14 | { 15 | /** 16 | * 403 没有权限访问 17 | * @throws Exception 18 | */ 19 | public function err403(): string 20 | { 21 | return $this->fetch('error/403'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/admin/controller/IndexController.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\controller; 10 | 11 | use Exception; 12 | 13 | class IndexController extends AdminBaseController 14 | { 15 | /** 16 | * 后台首页 17 | * @return string 18 | * @throws Exception 19 | */ 20 | public function index(): string 21 | { 22 | return $this->fetch(); 23 | } 24 | } -------------------------------------------------------------------------------- /app/admin/event.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | use app\admin\listener\AdminUserLogin; 8 | use app\admin\listener\AdminUserLogout; 9 | 10 | return [ 11 | 'bind' => [ 12 | 13 | ], 14 | 15 | 'listen' => [ 16 | // AdminUserLogin 17 | 'AdminUserLogin' => [ 18 | AdminUserLogin::class, 19 | ], 20 | 'AdminUserLogout' => [ 21 | AdminUserLogout::class, 22 | ], 23 | 'AppInit' => [], 24 | 'HttpRun' => [], 25 | 'HttpEnd' => [], 26 | 'LogLevel' => [], 27 | 'LogWrite' => [], 28 | ], 29 | 30 | 'subscribe' => [ 31 | ], 32 | ]; 33 | -------------------------------------------------------------------------------- /app/admin/exception/AdminServiceException.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\exception; 10 | 11 | use Exception; 12 | 13 | class AdminServiceException extends Exception 14 | { 15 | } -------------------------------------------------------------------------------- /app/admin/listener/AdminUserLogin.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\listener; 10 | 11 | use think\facade\Log; 12 | use app\admin\service\AdminLogService; 13 | use app\admin\exception\AdminServiceException; 14 | 15 | class AdminUserLogin 16 | { 17 | 18 | public function handle($user): void 19 | { 20 | try { 21 | // 记录日志 22 | (new AdminLogService())->create($user, '登录'); 23 | } catch (AdminServiceException $e) { 24 | Log::error('记录登录异常,信息:'.$e->getMessage()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/admin/listener/AdminUserLogout.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\listener; 10 | 11 | use think\facade\Log; 12 | use app\admin\service\AdminLogService; 13 | use app\admin\exception\AdminServiceException; 14 | 15 | class AdminUserLogout 16 | { 17 | public function handle($user): void 18 | { 19 | try { 20 | (new AdminLogService)->create($user, '退出'); 21 | } catch (AdminServiceException $e) { 22 | Log::error('记录退出异常,信息:'.$e->getMessage()); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/admin/middleware.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\model; 10 | 11 | use app\common\model\CommonBaseModel; 12 | 13 | class AdminBaseModel extends CommonBaseModel 14 | { 15 | 16 | } -------------------------------------------------------------------------------- /app/admin/model/AdminLog.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\model; 10 | 11 | use think\model\relation\HasOne; 12 | use think\model\concern\SoftDelete; 13 | use think\model\relation\BelongsTo; 14 | 15 | /** 16 | * Class AdminLog 17 | * @package app\admin\model 18 | * @property string $log_ip 19 | */ 20 | class AdminLog extends AdminBaseModel 21 | { 22 | use SoftDelete; 23 | /** 24 | * @var array 搜索的字段:操作,URL 25 | */ 26 | public array $searchField = [ 27 | 'name', 28 | 'url', 29 | ]; 30 | 31 | public array $whereField = [ 32 | 'admin_user_id' 33 | ]; 34 | 35 | /** 36 | * 关联用户 37 | * @return BelongsTo 38 | */ 39 | public function adminUser(): BelongsTo 40 | { 41 | return $this->belongsTo(AdminUser::class); 42 | } 43 | 44 | /** 45 | * 关联详情 46 | * @return HasOne 47 | */ 48 | public function adminLogData(): HasOne 49 | { 50 | return $this->hasOne(AdminLogData::class); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/admin/model/AdminLogData.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\model; 10 | 11 | use JsonException; 12 | use think\model\concern\SoftDelete; 13 | use think\model\relation\BelongsTo; 14 | 15 | class AdminLogData extends AdminBaseModel 16 | { 17 | use SoftDelete; 18 | /** 19 | * 关联log 20 | * @return BelongsTo 21 | */ 22 | public function adminLog(): BelongsTo 23 | { 24 | return $this->belongsTo(AdminLog::class); 25 | } 26 | 27 | /** 28 | * @throws JsonException 29 | */ 30 | public function getDataFormatAttr($value, $data) 31 | { 32 | return json_encode(json_decode($data['data'], true, 512, JSON_THROW_ON_ERROR), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/admin/model/AdminMenu.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\model; 10 | 11 | use think\model\concern\SoftDelete; 12 | 13 | /** 14 | * Class AdminMenu 15 | * @package app\admin\model 16 | * @property int $parent_id 17 | * @property string $name 18 | * @property int $id 19 | * @property string $icon 20 | * @property string $url 21 | * @property string $log_method 22 | */ 23 | class AdminMenu extends AdminBaseModel 24 | { 25 | use SoftDelete; 26 | /** 27 | * @var array 不允许被删除的菜单ID 28 | */ 29 | public array $noDeletionIds = [ 30 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 31 | ]; 32 | 33 | /** 34 | * @var array 日志记录方法列表 35 | */ 36 | public static array $logMethodList = [ 37 | [ 38 | 'id' => '不记录', 39 | 'name' => '不记录', 40 | ], 41 | [ 42 | 'id' => 'GET', 43 | 'name' => 'GET', 44 | ], 45 | [ 46 | 'id' => 'POST', 47 | 'name' => 'POST', 48 | ], 49 | [ 50 | 'id' => 'PUT', 51 | 'name' => 'PUT', 52 | ], 53 | [ 54 | 'id' => 'DELETE', 55 | 'name' => 'DELETE', 56 | ], 57 | [ 58 | 'id' => 'PATCH', 59 | 'name' => 'PATCH', 60 | ], 61 | ]; 62 | } 63 | -------------------------------------------------------------------------------- /app/admin/model/AdminRole.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace app\admin\model; 8 | 9 | use think\model\concern\SoftDelete; 10 | 11 | /** 12 | * Class AdminRole 13 | * @package app\admin\model 14 | * @property array $url 15 | */ 16 | class AdminRole extends AdminBaseModel 17 | { 18 | use SoftDelete; 19 | 20 | public array $searchField = [ 21 | 'name' 22 | ]; 23 | 24 | /** 25 | * 角色初始权限 26 | * @param AdminRole $data 27 | * @return void 28 | */ 29 | public static function onBeforeInsert($data): void 30 | { 31 | $data->url = empty($data->url) ? [1, 2, 18] : $data->url; 32 | } 33 | 34 | protected function getUrlAttr($value) 35 | { 36 | return !empty($value) ? explode(',', $value) : []; 37 | } 38 | 39 | protected function setUrlAttr($value): string 40 | { 41 | return !empty($value) ? implode(',', $value) : ''; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/admin/provider.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | return [ 8 | 'think\Paginator' => 'app\admin\service\PageService' 9 | ]; -------------------------------------------------------------------------------- /app/admin/service/AdminBaseService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\service; 10 | 11 | class AdminBaseService 12 | { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/admin/service/AdminLogService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\service; 10 | 11 | use Exception; 12 | use think\facade\Db; 13 | use app\admin\model\AdminLog; 14 | use app\admin\model\AdminUser; 15 | use app\admin\exception\AdminServiceException; 16 | 17 | class AdminLogService extends AdminBaseService 18 | { 19 | protected AdminLog $model; 20 | 21 | public function __construct() 22 | { 23 | $this->model = new AdminLog(); 24 | } 25 | 26 | /** 27 | * 创建日志 28 | * @param AdminUser $user 用户 29 | * @param string $name 操作名称 30 | * @throws AdminServiceException 31 | */ 32 | public function create(AdminUser $user, string $name): void 33 | { 34 | Db::startTrans(); 35 | try { 36 | $data = [ 37 | 'admin_user_id' => $user->id, 38 | 'name' => $name, 39 | 'log_method' => request()->method(), 40 | 'url' => request()->url(), 41 | 'log_ip' => request()->ip() 42 | ]; 43 | $log = $this->model::create($data); 44 | 45 | $data_arr = [ 46 | 'header' => request()->header(), 47 | 'param' => request()->param(), 48 | ]; 49 | $log_data = [ 50 | 'data' => json_encode($data_arr, JSON_THROW_ON_ERROR), 51 | ]; 52 | $log->adminLogData()->save($log_data); 53 | 54 | Db::commit(); 55 | } catch (Exception $exception) { 56 | Db::rollback(); 57 | throw new AdminServiceException($exception->getMessage()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/admin/service/AdminRoleService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\service; 10 | 11 | use think\Collection; 12 | use app\admin\model\AdminRole; 13 | use think\db\exception\DbException; 14 | use think\db\exception\DataNotFoundException; 15 | use think\db\exception\ModelNotFoundException; 16 | 17 | class AdminRoleService 18 | { 19 | protected AdminRole $model; 20 | 21 | public function __construct() 22 | { 23 | $this->model = new AdminRole(); 24 | } 25 | 26 | /** 27 | * 获取所有角色 28 | * @return AdminRole[]|array|Collection 29 | */ 30 | public function getAll() 31 | { 32 | try { 33 | return $this->model->select(); 34 | } catch (DataNotFoundException | ModelNotFoundException | DbException $e) { 35 | return []; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/admin/validate/AdminBaseValidate.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\validate; 10 | 11 | use app\common\validate\CommonBaseValidate; 12 | 13 | class AdminBaseValidate extends CommonBaseValidate 14 | { 15 | 16 | } -------------------------------------------------------------------------------- /app/admin/validate/AdminMenuValidate.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\validate; 10 | 11 | class AdminMenuValidate extends AdminBaseValidate 12 | { 13 | protected $rule = [ 14 | 'parent_id|父级菜单' => 'require|egt:0', 15 | 'name|名称' => 'require', 16 | 'url|URL' => 'require|unique:admin_menu', 17 | 'icon|图标' => 'require', 18 | 'sort_number|排序' => 'require', 19 | 'is_show|是否显示' => 'require', 20 | 'log_method|日志记录方式' => 'require', 21 | ]; 22 | 23 | protected $message = [ 24 | 'parent_id.egt' => '请选择上级菜单', 25 | ]; 26 | 27 | protected $scene = [ 28 | 'admin_add' => ['parent_id', 'title', 'url', 'icon', 'sort_number', 'is_show', 'log_method'], 29 | 'admin_edit' => ['parent_id', 'title', 'url', 'icon', 'sort_number', 'is_show', 'log_method'], 30 | ]; 31 | 32 | } -------------------------------------------------------------------------------- /app/admin/validate/AdminRoleValidate.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\validate; 10 | 11 | class AdminRoleValidate extends AdminBaseValidate 12 | { 13 | protected $rule = [ 14 | 'name|名称' => 'require', 15 | 'description|介绍' => 'require', 16 | 'rules|权限' => 'require', 17 | ]; 18 | 19 | protected $scene = [ 20 | 'admin_add' => ['name', 'description'], 21 | 'admin_edit' => ['name', 'description'], 22 | ]; 23 | } 24 | -------------------------------------------------------------------------------- /app/admin/validate/AdminUserValidate.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\admin\validate; 10 | 11 | class AdminUserValidate extends AdminBaseValidate 12 | { 13 | protected $rule = [ 14 | 'username|帐号' => 'require|unique:admin_user', 15 | 'password|密码' => 'require', 16 | 'current_password|当前密码' => 'require', 17 | 'new_password|新密码' => 'require', 18 | 're_new_password|确认新密码' => 'require|confirm:new_password', 19 | 'nickname|昵称' => 'require', 20 | 'role|角色' => 'require', 21 | 'status|状态' => 'require', 22 | ]; 23 | 24 | protected $message = [ 25 | 'name.require' => '名称必须', 26 | 'name.max' => '名称最多不能超过25个字符', 27 | 'age.number' => '年龄必须是数字', 28 | 'age.between' => '年龄只能在1-120之间', 29 | 'email' => '邮箱格式错误', 30 | ]; 31 | 32 | protected $scene = [ 33 | 'admin_add' => ['username', 'password'], 34 | 'admin_edit' => ['username', 'password'], 35 | 'admin_login' => ['username', 'password'], 36 | 'admin_password' => ['current_password', 'new_password', 're_new_password'], 37 | ]; 38 | 39 | public function sceneLogin(): void 40 | { 41 | $this->only(['username', 'password']) 42 | ->remove('username', 'unique'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/admin/view/auth/captcha.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 |
6 | 7 |
8 | 图形验证码 9 |
10 |
11 | 12 | 26 | 27 | -------------------------------------------------------------------------------- /app/admin/view/auth/login_bg.html: -------------------------------------------------------------------------------- 1 | 2 | {if $login_config.background} 3 | 13 | {/if} -------------------------------------------------------------------------------- /app/admin/view/database/view.html: -------------------------------------------------------------------------------- 1 | 2 | {extend name='public/layer_base' /} 3 | {block name='content'} 4 |
5 |
6 |
7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {foreach name='data' id='item'} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {/foreach} 35 | 36 |
字段名类型排序规则是否为空是否为主键默认值更多信息备注
{$item.name}{$item.type}{$item.collation}{$item.null}{$item.key}{$item.default}{$item.extra}{$item.comment}
37 |
38 |
39 |
40 |
41 |
42 | 43 | {/block} -------------------------------------------------------------------------------- /app/admin/view/error/403.html: -------------------------------------------------------------------------------- 1 | {extend name='public/base' /} 2 | {block name='content'} 3 | {include file='public/content_header' /} 4 |
5 |
6 |

403

7 |
8 |

抱歉! 没有权限。

9 |

10 | 您访问的页面没有权限,您可以 点此去首页 11 |

12 |
13 |
14 |
15 | {/block} -------------------------------------------------------------------------------- /app/admin/view/error/404.html: -------------------------------------------------------------------------------- 1 | {extend name='public/base' /} 2 | {block name='content'} 3 | {include file='public/content_header' /} 4 |
5 |
6 |

404

7 |
8 |

糟糕! 页面未找到。

9 |

10 | 您访问的页面不存在,您可以 点此去首页 11 |

12 |
13 |
14 |
15 | {/block} -------------------------------------------------------------------------------- /app/admin/view/file/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/admin/view/generate/index.html: -------------------------------------------------------------------------------- 1 | {extend name="public/base" /} 2 | {block name='content'} 3 | {include file='public/content_header' /} 4 |
5 |
6 |
7 |
8 | 9 |
10 | 代码自动生成 11 | 点击跳转 12 |
13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 | 表单字段生成 21 | 点击跳转 22 |
23 |
24 |
25 | 26 |
27 |
28 | 29 | {/block} -------------------------------------------------------------------------------- /app/admin/view/index/index.html: -------------------------------------------------------------------------------- 1 | 2 | {extend name='public/base' /} 3 | {block name='content'} 4 | {include file='public/content_header' /} 5 | 6 |
7 | 8 | 9 | {include file='index/top_widget1' /} 10 | 11 | {include file='index/top_widget2' /} 12 | 13 | {include file='index/chart1' /} 14 | 15 | {include file='index/chart2' /} 16 | 17 | {include file='index/chart3' /} 18 | 19 |
20 | 21 | {/block} -------------------------------------------------------------------------------- /app/admin/view/index/top_widget2.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 | 6 | 7 |
8 | 消息数 9 | 1,410 10 |
11 |
12 |
13 | 14 |
15 |
16 | 17 | 18 |
19 | 书签数 20 | 410 21 |
22 |
23 |
24 | 25 |
26 |
27 | 28 | 29 |
30 | 附件数 31 | 13,648 32 |
33 | 34 |
35 |
36 | 37 |
38 |
39 | 40 | 41 |
42 | 收藏数 43 | 93,139 44 |
45 |
46 |
47 | 48 |
49 | 50 | -------------------------------------------------------------------------------- /app/admin/view/public/base.html: -------------------------------------------------------------------------------- 1 | {if !$admin.is_pjax} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {/if} 12 | 13 | {block name='title'} 14 | {$admin.title|default='Admin'} | {$admin.base.name|default='Admin'} 15 | {/block} 16 | 17 | {if !$admin.is_pjax} 18 | 19 | {include file='public/head_css' /} 20 | {include file='public/head_js' /} 21 | 22 | 23 |
24 | {/if} 25 | 26 | 27 | {block name='navbar'} 28 | {include file='public/navbar/navbar' /} 29 | {/block} 30 | 31 | 32 | {block name='sidebar'} 33 | {include file='public/sidebar' /} 34 | {/block} 35 | 36 | 37 |
38 | {block name='content'} 39 | {/block} 40 |
41 | 42 | 43 | {block name='footer'} 44 | {include file='public/footer' /} 45 | {/block} 46 | 47 | 48 | {block name='control_sidebar'} 49 | {include file='public/control_sidebar' /} 50 | {/block} 51 | 52 | {if !$admin.is_pjax} 53 |
54 | {/if} 55 | 56 | {if !$admin.is_pjax} 57 | 58 | 59 | 60 | {/if} -------------------------------------------------------------------------------- /app/admin/view/public/change_page.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/admin/view/public/content_header.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |

{$admin.title|default='ADMIN'}

6 |
7 |
8 | 17 |
18 |
19 |
20 |
-------------------------------------------------------------------------------- /app/admin/view/public/footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/admin/view/public/head_css.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {css href="__ADMIN_PLUGINS__/viewer/viewer.min.css" /} 4 | {css href="__ADMIN_PLUGINS__/nprogress/nprogress.css" /} 5 | {css href="__ADMIN_PLUGINS__/select2/css/select2.min.css" /} 6 | {css href="__ADMIN_PLUGINS__/fileinput/css/fileinput.min.css" /} 7 | {css href="__ADMIN_PLUGINS__/fontawesome-free/css/all.min.css" /} 8 | {css href="__ADMIN_PLUGINS__/icheck-bootstrap/icheck-bootstrap.min.css" /} 9 | {css href="__ADMIN_PLUGINS__/select2-bootstrap4-theme/select2-bootstrap4.min.css" /} 10 | {css href="__ADMIN_PLUGINS__/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css" /} 11 | {css href="__ADMIN_PLUGINS__/bootstrap-switch/css/bootstrap3/bootstrap-switch.min.css" /} 12 | {css href="__ADMIN_PLUGINS__/fontawesome-iconpicker/css/fontawesome-iconpicker.min.css" /} 13 | {css href="__ADMIN_CSS__/adminlte.min.css" /} 14 | {css href="__ADMIN_CSS__/admin.css" /} 15 | -------------------------------------------------------------------------------- /app/admin/view/public/layer_base.html: -------------------------------------------------------------------------------- 1 | {if !$admin.is_pjax} 2 | {include file='public/head_css' /} 3 | {include file='public/head_js' /} 4 | {/if} 5 | 6 |
7 | {block name='content'} 8 | {/block} 9 |
10 | 11 | -------------------------------------------------------------------------------- /app/admin/view/public/navbar/nav.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | -------------------------------------------------------------------------------- /app/admin/view/public/navbar/navbar.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/admin/view/public/navbar/notification.html: -------------------------------------------------------------------------------- 1 | {if $admin.top_notification} 2 | 3 | 29 | {/if} -------------------------------------------------------------------------------- /app/admin/view/public/navbar/search_form.html: -------------------------------------------------------------------------------- 1 | {if $admin.top_search} 2 |
3 |
4 | 5 |
6 | 9 |
10 |
11 |
12 | {/if} 13 | -------------------------------------------------------------------------------- /app/admin/view/public/navbar/sidebar_button.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/admin/view/public/navbar/user_menu.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 17 | 18 | -------------------------------------------------------------------------------- /app/admin/view/public/sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/admin/view/template/content.html: -------------------------------------------------------------------------------- 1 | 2 | {extend name='public/base' /} 3 | {block name='content'} 4 | {include file='public/content_header' /} 5 |
6 | 7 | 8 | 9 |
10 | 11 | {/block} -------------------------------------------------------------------------------- /app/admin/view/template/layer_content.html: -------------------------------------------------------------------------------- 1 | 2 | {extend name='public/layer_base' /} 3 | {block name='content'} 4 |
5 | 6 | 7 | 8 |
9 | 10 | {/block} -------------------------------------------------------------------------------- /app/api/config/api.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | return [ 8 | 9 | // api跨域设置 10 | 'cross_domain' => [ 11 | // 是否允许跨域 12 | 'allow' => env('api.allow_cross_domain', true), 13 | // header设置 14 | 'header' => [ 15 | 'Access-Control-Allow-Origin' => '*', 16 | 'Access-Control-Allow-Methods' => '*', 17 | 'Access-Control-Allow-Headers' => 'Content-Type,' . (env('api.token_position') === 'header' ? env('api.token_field') : 'token'), 18 | 'Access-Control-Request-Headers' => 'Origin, Content-Type, Accept, ' . (env('api.token_position') === 'header' ? env('api.token_field') : 'token'), 19 | ], 20 | ], 21 | // api响应配置 22 | 'response' => [ 23 | // HTTP状态码和业务状态码同步 24 | 'http_code_sync' => env('api.http_code_sync', false), 25 | ], 26 | 'auth' => [ 27 | 'jwt_key' => env('api.jwt_key', 'f2244f5316b70ef2887514b65caf795f'), 28 | 'jwt_exp' => (int)env('api.jwt_exp', 3600), 29 | 'jwt_aud' => env('api.jwt_aud', 'a'), 30 | 'jwt_iss' => env('api.jwt_iss', 's'), 31 | 'enable_refresh_token' => (bool)env('api.enable_refresh_token', true), 32 | 'refresh_token_exp' => (int)env('api.refresh_token_exp', 1296000), 33 | 'reuse_check' => (bool)env('api.reuse_check', true), 34 | 'token_position' => env('api.token_position', 'header'), 35 | 'token_field' => env('api.token_field', 'token'), 36 | ] 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /app/api/controller/AuthController.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\api\controller; 10 | 11 | use app\common\validate\UserValidate; 12 | use think\Request; 13 | use think\response\Json; 14 | use app\api\service\AuthService; 15 | use app\api\exception\ApiServiceException; 16 | 17 | class AuthController 18 | { 19 | /** 20 | * @param Request $request 21 | * @param UserValidate $validate 22 | * @param AuthService $service 23 | * @return Json 24 | */ 25 | public function login(Request $request, UserValidate $validate,AuthService $service): Json 26 | { 27 | $param = $request->param(); 28 | 29 | $check = $validate->scene('api_login')->check($param); 30 | if (!$check) { 31 | return api_error($validate->getError()); 32 | } 33 | 34 | try { 35 | 36 | $username = $param['username']; 37 | $password = $param['password']; 38 | $result = $service->usernameLogin($username, $password); 39 | 40 | return api_success($result); 41 | } catch (ApiServiceException $e) { 42 | return api_error('登录失败,参考信息:'.$e->getMessage()); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /app/api/controller/IndexController.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\api\controller; 10 | 11 | use think\response\Json; 12 | 13 | class IndexController extends ApiBaseController 14 | { 15 | public function index(): Json 16 | { 17 | return api_success(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/api/controller/TokenController.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | 10 | namespace app\api\controller; 11 | 12 | 13 | use app\api\exception\ApiServiceException; 14 | use app\api\service\TokenService; 15 | use think\response\Json; 16 | 17 | class TokenController 18 | { 19 | 20 | /** 21 | * 刷新token,当刷新返回错误的时候需要重新登录 22 | * @return Json 23 | */ 24 | public function refresh(): Json 25 | { 26 | $param = request()->param(); 27 | $refresh_token = $param['refresh_token']; 28 | $service = new TokenService(); 29 | 30 | try { 31 | $data = $service->refreshToken($refresh_token); 32 | return api_success($data); 33 | } catch (ApiServiceException $e) { 34 | return api_error($e->getMessage()); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/api/exception/ApiServiceException.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\api\exception; 10 | 11 | use Exception; 12 | 13 | class ApiServiceException extends Exception 14 | { 15 | 16 | } -------------------------------------------------------------------------------- /app/api/middleware.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | $config = []; 8 | if(env('api.allow_cross_domain')){ 9 | $config = [ 10 | \app\api\middleware\AllowCrossDomain::class 11 | ]; 12 | } 13 | 14 | return $config; -------------------------------------------------------------------------------- /app/api/middleware/AllowCrossDomain.php: -------------------------------------------------------------------------------- 1 | $value) { 23 | header($key . ':' . $value); 24 | } 25 | if ($request->isOptions()) { 26 | return json(''); 27 | } 28 | return $next($request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/api/service/ApiBaseService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\api\service; 10 | 11 | class ApiBaseService 12 | { 13 | 14 | } -------------------------------------------------------------------------------- /app/api/service/AuthService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\api\service; 10 | 11 | use app\api\exception\ApiServiceException; 12 | use app\common\model\User; 13 | use think\facade\Event; 14 | 15 | class AuthService extends ApiBaseService 16 | { 17 | protected User $model; 18 | 19 | public function __construct() 20 | { 21 | $this->model = new User(); 22 | } 23 | 24 | /** 25 | * @param $username 26 | * @param $password 27 | * @return array 28 | * @throws ApiServiceException 29 | */ 30 | public function usernameLogin($username, $password): array 31 | { 32 | /** @var User $user */ 33 | $user = $this->model->where('username', '=', $username)->findOrEmpty(); 34 | 35 | if ($user->isEmpty()) { 36 | throw new ApiServiceException('用户不存在'); 37 | } 38 | 39 | $verify = password_verify($password, base64_decode($user->password)); 40 | if (!$verify) { 41 | throw new ApiServiceException('密码错误'); 42 | } 43 | 44 | // 检查是否被冻结 45 | if ($user->status !== 1) { 46 | throw new ApiServiceException('账号被冻结'); 47 | } 48 | 49 | // Event_事件 管理用户登录 50 | Event::trigger('UserLogin', $user); 51 | 52 | $service = new TokenService(); 53 | 54 | $data = [ 55 | 'access_token' => $service->getAccessToken($user->id), 56 | ]; 57 | if ($service->isEnableRefreshToken()) { 58 | $data['refresh_token'] = $service->getRefreshToken($user->id); 59 | } 60 | 61 | return $data; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /app/command/GenerateAppKey.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | declare (strict_types=1); 7 | 8 | namespace app\command; 9 | 10 | use think\console\Command; 11 | use think\console\Output; 12 | use think\console\Input; 13 | 14 | class GenerateAppKey extends Command 15 | { 16 | protected function configure() 17 | { 18 | // 指令配置 19 | $this->setName('generate:app_key') 20 | ->setDescription('生成新的APP_KEY'); 21 | } 22 | 23 | protected function execute(Input $input, Output $output) 24 | { 25 | $env = app()->getRootPath() . '.env'; 26 | $search = 'APP_KEY=' . env('app.app_key'); 27 | $key = md5(uniqid('app_key', true)); 28 | $result = file_put_contents($env, str_replace($search, 'APP_KEY=' . $key, file_get_contents($env))); 29 | if ($result) { 30 | $output->writeln('新的APP_KEY生成成功,值为:' . $key); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/command/GenerateJwtKey.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | declare (strict_types=1); 7 | 8 | namespace app\command; 9 | 10 | use think\console\Command; 11 | use think\console\Output; 12 | use think\console\Input; 13 | 14 | class GenerateJwtKey extends Command 15 | { 16 | protected function configure() 17 | { 18 | // 指令配置 19 | $this->setName('generate:jwt_key') 20 | ->setDescription('生成新的JWT_KEY'); 21 | } 22 | 23 | protected function execute(Input $input, Output $output) 24 | { 25 | $env = app()->getRootPath() . '.env'; 26 | $search = 'JWT_KEY=' . env('api.jwt_key'); 27 | $key = md5(uniqid('jwt_key', true)); 28 | $result = file_put_contents($env, str_replace($search, 'JWT_KEY=' . $key, file_get_contents($env))); 29 | if ($result) { 30 | $output->writeln('新的JWT_KEY生成成功,值为:' . $key); 31 | } 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /app/command/InitEnv.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\command; 10 | 11 | use think\console\input\Option; 12 | use think\console\Command; 13 | use think\facade\Console; 14 | use think\console\Output; 15 | use think\console\Input; 16 | 17 | class InitEnv extends Command 18 | { 19 | protected function configure() 20 | { 21 | $this->setName('init:env') 22 | ->addOption('--force', '-f', Option::VALUE_NONE, '强制初始化env配置文件') 23 | ->setDescription('初始化项目env配置文件'); 24 | } 25 | 26 | protected function execute(Input $input, Output $output) 27 | { 28 | $force = $input->getOption('force'); 29 | 30 | $example_file = $this->app->getRootPath() . '.example.env'; 31 | $env_file = $this->app->getRootPath() . '.env'; 32 | 33 | if ($force === true || !file_exists($env_file)) { 34 | copy($example_file, $env_file); 35 | $output->info('env配置文件初始化成功'); 36 | 37 | $app_key_result = Console::call('generate:app_key'); 38 | $output->info($app_key_result->fetch()); 39 | $jwt_key_result = Console::call('generate:jwt_key'); 40 | $output->info($jwt_key_result->fetch()); 41 | } else { 42 | $output->info('env配置文件已存在'); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/command/ResetAdminPassword.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\command; 10 | 11 | use app\common\exception\CommonServiceException; 12 | use app\common\service\StringService; 13 | use think\console\input\Argument; 14 | use think\console\input\Option; 15 | use app\admin\model\AdminUser; 16 | use think\console\Command; 17 | use think\console\Output; 18 | use think\console\Input; 19 | 20 | class ResetAdminPassword extends Command 21 | { 22 | protected function configure() 23 | { 24 | $this->setName('reset:admin_password') 25 | ->addArgument('password', Argument::OPTIONAL, "新密码,可空") 26 | ->addOption('uid', null, Option::VALUE_REQUIRED, '需要重置密码的用户ID') 27 | ->setDescription('重置后台用户密码,默认重置开发管理员密码'); 28 | } 29 | 30 | /** 31 | * @throws CommonServiceException 32 | */ 33 | protected function execute(Input $input, Output $output) 34 | { 35 | $password = trim((string)$input->getArgument('password')); 36 | $password = $password ?: StringService::getRandString(10, true, true, true, false); 37 | 38 | $uid = 1; 39 | if ($input->hasOption('uid')) { 40 | $uid = $input->getOption('uid'); 41 | } 42 | 43 | $user = (new AdminUser())->where('id', '=', $uid)->findOrEmpty(); 44 | if ($user->isEmpty()) { 45 | $output->error('用户不存在'); 46 | return; 47 | } 48 | 49 | $user->password = $password; 50 | $result = $user->save(); 51 | $output_text = '[ID:' . $user->id . ']' . $user->nickname; 52 | if ($result) { 53 | $output->info($output_text . '的密码重置成功,新密码为:' . $password); 54 | return; 55 | } 56 | 57 | $output->error($output_text . '的密码重置失败'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/command/Test.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\command; 10 | 11 | use think\console\Command; 12 | use think\console\Input; 13 | use think\console\Output; 14 | 15 | class Test extends Command 16 | { 17 | 18 | protected function configure() 19 | { 20 | $this->setName('test') 21 | ->setDescription('测试命令'); 22 | } 23 | 24 | protected function execute(Input $input, Output $output) 25 | { 26 | $output->info('这是测试信息'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/common/exception/CommonServiceException.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | 10 | namespace app\common\exception; 11 | 12 | 13 | use Exception; 14 | 15 | class CommonServiceException extends Exception 16 | { 17 | 18 | } -------------------------------------------------------------------------------- /app/common/model/Setting.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace app\common\model; 8 | 9 | use JsonException; 10 | use think\model\concern\SoftDelete; 11 | use think\model\relation\BelongsTo; 12 | 13 | /** 14 | * Class Setting 15 | * @package app\common\model 16 | * @property int $id ID 17 | * @property int $name 名称 18 | * @property string $code 代码 19 | * @property array $content 设置内容 20 | * @property int $setting_group_id 所属分组ID 21 | */ 22 | class Setting extends CommonBaseModel 23 | { 24 | use SoftDelete; 25 | 26 | protected $name = 'setting'; 27 | protected $autoWriteTimestamp = true; 28 | 29 | public array $noDeletionIds = [ 30 | 1, 2, 3, 4, 5, 31 | ]; 32 | 33 | //可搜索字段 34 | public array $searchField = ['name', 'description', 'code',]; 35 | 36 | 37 | //关联设置分组 38 | public function settingGroup(): BelongsTo 39 | { 40 | return $this->belongsTo(SettingGroup::class); 41 | } 42 | 43 | 44 | public function setContentAttr($value) 45 | { 46 | try { 47 | return json_encode($value, JSON_THROW_ON_ERROR); 48 | } catch (JsonException $e) { 49 | return (object)[]; 50 | } 51 | } 52 | 53 | public function getContentAttr($value) 54 | { 55 | try { 56 | return json_decode($value, true, 512, JSON_THROW_ON_ERROR); 57 | } catch (JsonException $e) { 58 | return []; 59 | } 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/common/model/SettingGroup.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace app\common\model; 8 | 9 | use think\model\Collection; 10 | use think\model\relation\HasMany; 11 | use think\model\concern\SoftDelete; 12 | 13 | /** 14 | * Class SettingGroup 15 | * @package app\common\model 16 | * @property int $id 17 | * @property string $name 18 | * @property int $auto_create_file 19 | * @property int $auto_create_menu 20 | * @property string $code 21 | * @property string $module 22 | * @property string $description 23 | * @property Setting[] $setting 24 | * @property string $icon 25 | */ 26 | class SettingGroup extends CommonBaseModel 27 | { 28 | use SoftDelete; 29 | protected $name = 'setting_group'; 30 | protected $autoWriteTimestamp = true; 31 | 32 | public array $noDeletionIds =[ 33 | 1,2,3,4,5, 34 | ]; 35 | 36 | // 可搜索字段 37 | public array $searchField = ['name', 'description', 'code',]; 38 | 39 | // 关联设置 40 | public function setting(): HasMany 41 | { 42 | return $this->hasMany(Setting::class); 43 | } 44 | 45 | /** 46 | * 自动生成菜单字段获取器 47 | * @param $value 48 | * @param $data 49 | * @return string 50 | */ 51 | public function getAutoCreateMenuTextAttr($value,$data): string 52 | { 53 | return self::BOOLEAN_TEXT[$data['auto_create_menu']]; 54 | } 55 | 56 | /** 57 | * 自动生成配置文件获取器 58 | * @param $value 59 | * @param $data 60 | * @return string 61 | */ 62 | public function getAutoCreateFileTextAttr($value,$data): string 63 | { 64 | return self::BOOLEAN_TEXT[$data['auto_create_file']]; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/common/model/Test.php: -------------------------------------------------------------------------------- 1 | belongsTo(UserLevel::class); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/common/model/UserLevel.php: -------------------------------------------------------------------------------- 1 | hasMany(Test::class); 34 | }// 关联用户 35 | public function user(): HasMany 36 | { 37 | return $this->hasMany(User::class); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/common/service/CommonBaseService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | 10 | namespace app\common\service; 11 | 12 | 13 | class CommonBaseService 14 | { 15 | 16 | } -------------------------------------------------------------------------------- /app/common/service/DateService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\common\service; 10 | 11 | class DateService 12 | { 13 | /** 14 | * 获取当前微秒时间戳 15 | * @return string 16 | */ 17 | public static function microTimestamp(): string 18 | { 19 | $time = explode(' ', microtime()); 20 | $micro = substr($time[0], 2, 3); 21 | return $time[1] . $micro; 22 | } 23 | 24 | /** 25 | * 获取指定日期当月第一天 26 | * @param $date 27 | * @return false|string 28 | */ 29 | public static function getCurMonthFirstDay($date) { 30 | return date('Y-m-01', strtotime($date)); 31 | } 32 | 33 | /** 34 | * 获取指定日期当月最后一天 35 | * @param $date 36 | * @return false|string 37 | */ 38 | public static function getCurMonthLastDay($date) { 39 | return date('Y-m-d', strtotime(date('Y-m-01', strtotime($date)) . ' +1 month -1 day')); 40 | } 41 | 42 | /** 43 | * 获取月初的时间戳 44 | * @param string $month 月份,格式2020-10 45 | * @return false|int 46 | */ 47 | public static function getMonthStartTimestamp(string $month) 48 | { 49 | return strtotime($month); 50 | } 51 | 52 | /** 53 | * 获取月末时间戳 54 | * @param string $month 月份,格式2020-10 55 | * @return false|int 56 | */ 57 | public static function getMonthEndTimestamp(string $month) 58 | { 59 | return strtotime(date('Y-m-t',strtotime($month)).' 23:59:59'); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /app/common/validate/SettingGroupValidate.php: -------------------------------------------------------------------------------- 1 | 'require|chsDash', 12 | 'description|描述' => 'require|chsDash', 13 | 'module|作用模块' => 'require|alpha|length:1,30', 14 | 'code|代码' => 'require|unique:setting_group|code', 15 | 'sort_number|排序' => 'require|number|elt:9999999999|egt:1', 16 | 'auto_create_menu|自动生成菜单' => 'require', 17 | 'auto_create_file|自动生成配置文件' => 'require', 18 | 19 | ]; 20 | 21 | protected $message = [ 22 | 'name.require' => '名称不能为空', 23 | 'description.require' => '描述不能为空', 24 | 'module.require' => '作用模块不能为空', 25 | 'code.require' => '代码不能为空', 26 | 'sort_number.require' => '排序不能为空', 27 | 'auto_create_menu.require' => '自动生成菜单不能为空', 28 | 'auto_create_file.require' => '自动生成配置文件不能为空', 29 | ]; 30 | 31 | protected $scene = [ 32 | 'add' => ['name', 'description', 'module', 'code', 'sort_number', 'auto_create_menu', 'auto_create_file',], 33 | 'edit' => ['name', 'description', 'module', 'code', 'sort_number', 'auto_create_menu', 'auto_create_file',], 34 | ]; 35 | 36 | 37 | /** 38 | * 验证code 39 | * @param $value 40 | * @param $rule 41 | * @param array $data 42 | * @param string $field 43 | * @param string $desc 44 | * @return bool|string 45 | */ 46 | protected function code($value, $rule, array $data = [], string $field = '', string $desc = '') 47 | { 48 | $pattern = '/^[a-zA-z]\w{2,29}$/'; 49 | return preg_match($pattern, $value) ? true : $desc . '的规则为[字母、数字、下划线组成,字母开头,3-30位]'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/common/validate/SettingValidate.php: -------------------------------------------------------------------------------- 1 | 'require|number|elt:9999|egt:1', 12 | 'name|名称' => 'require|chsDash', 13 | 'description|描述' => 'require|chsDash', 14 | 'code|代码' => 'require|unique:setting|code', 15 | 'sort_number|排序' => 'require|number|elt:9999999999|egt:1', 16 | 17 | ]; 18 | 19 | protected $message = [ 20 | 'setting_group_id.require' => '所属分组不能为空', 21 | 'name.require' => '名称不能为空', 22 | 'description.require' => '描述不能为空', 23 | 'code.require' => '代码不能为空', 24 | 'sort_number.require' => '排序不能为空', 25 | ]; 26 | 27 | protected $scene = [ 28 | 'add' => ['setting_group_id', 'name', 'description', 'code', 'sort_number',], 29 | 'edit' => ['setting_group_id', 'name', 'description', 'code', 'sort_number',], 30 | ]; 31 | 32 | /** 33 | * 验证code 34 | * @param $value 35 | * @param $rule 36 | * @param array $data 37 | * @param string $field 38 | * @param string $desc 39 | * @return bool|string 40 | */ 41 | protected function code($value, $rule, array $data = [], string $field = '', string $desc = '') 42 | { 43 | $pattern = '/^[a-zA-z]\w{2,29}$/'; 44 | return preg_match($pattern, $value) ? true : $desc . '的值只能是字母、数字、下划线组成,字母开头,3-50位'; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/common/validate/TestValidate.php: -------------------------------------------------------------------------------- 1 | 'require', 12 | 'username|用户名' => 'require', 13 | 'nickname|昵称' => 'require', 14 | 'mobile|手机号' => 'require', 15 | 'user_level_id|用户等级' => 'require', 16 | 'password|密码' => 'require', 17 | 'status|是否启用' => 'require', 18 | 'slide|相册' => 'require', 19 | 'content|内容' => 'require', 20 | 21 | ]; 22 | 23 | protected $message = [ 24 | 'avatar.required' => '头像不能为空', 25 | 'username.required' => '用户名不能为空', 26 | 'nickname.required' => '昵称不能为空', 27 | 'mobile.required' => '手机号不能为空', 28 | 'user_level_id.required' => '用户等级不能为空', 29 | 'password.required' => '密码不能为空', 30 | 'status.required' => '是否启用不能为空', 31 | 'slide.required' => '相册不能为空', 32 | 'content.required' => '内容不能为空', 33 | 34 | ]; 35 | 36 | protected $scene = [ 37 | 'admin_add' => ['avatar', 'username', 'nickname', 'mobile', 'user_level_id', 'password', 'status', 'lng', 'slide', 'content', ], 38 | 'admin_edit' => ['id', 'avatar', 'username', 'nickname', 'mobile', 'user_level_id', 'password', 'status', 'lng', 'slide', 'content', ], 39 | 'admin_del' => ['id', ], 40 | 'admin_disable' => ['id', ], 41 | 'admin_enable' => ['id', ], 42 | 'api_add' => ['avatar', 'username', 'nickname', 'mobile', 'user_level_id', 'password', 'status', 'lng', 'slide', 'content', ], 43 | 'api_info' => ['id', ], 44 | 'api_edit' => ['id', 'avatar', 'username', 'nickname', 'mobile', 'user_level_id', 'password', 'status', 'lng', 'slide', 'content', ], 45 | 'api_del' => ['id', ], 46 | 'api_disable' => ['id', ], 47 | 'api_enable' => ['id', ], 48 | ]; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/common/validate/UserLevelValidate.php: -------------------------------------------------------------------------------- 1 | 'require', 12 | 'description|简介' => 'require', 13 | 'img|图片' => 'require', 14 | 'status|是否启用' => 'require', 15 | 16 | ]; 17 | 18 | protected $message = [ 19 | 'name.required' => '名称不能为空', 20 | 'description.required' => '简介不能为空', 21 | 'img.required' => '图片不能为空', 22 | 'status.required' => '是否启用不能为空', 23 | 24 | ]; 25 | 26 | protected $scene = [ 27 | 'admin_add' => ['name', 'description', 'img', 'status',], 28 | 'admin_edit' => ['id', 'name', 'description', 'img', 'status',], 29 | 'admin_del' => ['id',], 30 | 'admin_disable' => ['id',], 31 | 'admin_enable' => ['id',], 32 | 'api_add' => ['name', 'description', 'img', 'status',], 33 | 'api_info' => ['id',], 34 | 'api_edit' => ['id', 'name', 'description', 'img', 'status',], 35 | 'api_del' => ['id',], 36 | 'api_disable' => ['id',], 37 | 'api_enable' => ['id',], 38 | ]; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/common/validate/UserValidate.php: -------------------------------------------------------------------------------- 1 | 'require', 12 | 'username|账号' => 'require', 13 | 'password|密码' => 'require', 14 | 'mobile|手机号' => 'require', 15 | 'nickname|昵称' => 'require', 16 | 'avatar|头像' => 'require', 17 | 'status|是否启用' => 'require', 18 | 19 | ]; 20 | 21 | protected $message = [ 22 | 'user_level_id.required' => '用户等级不能为空', 23 | 'username.required' => '账号不能为空', 24 | 'password.required' => '密码不能为空', 25 | 'mobile.required' => '手机号不能为空', 26 | 'nickname.required' => '昵称不能为空', 27 | 'avatar.required' => '头像不能为空', 28 | 'status.required' => '是否启用不能为空', 29 | 30 | ]; 31 | 32 | protected $scene = [ 33 | 'admin_add' => ['user_level_id', 'username', 'password', 'mobile', 'nickname', 'avatar', 'status',], 34 | 'admin_edit' => ['id', 'user_level_id', 'username', 'password', 'mobile', 'nickname', 'avatar', 'status',], 35 | 'admin_del' => ['id',], 36 | 'admin_disable' => ['id',], 37 | 'admin_enable' => ['id',], 38 | 'api_add' => ['user_level_id', 'username', 'password', 'mobile', 'nickname', 'avatar', 'status',], 39 | 'api_info' => ['id',], 40 | 'api_edit' => ['id', 'user_level_id', 'username', 'password', 'mobile', 'nickname', 'avatar', 'status',], 41 | 'api_del' => ['id',], 42 | 'api_disable' => ['id',], 43 | 'api_enable' => ['id',], 44 | 'api_login' => ['username', 'password'], 45 | 'index_login' => ['username', 'password'], 46 | ]; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/event.php: -------------------------------------------------------------------------------- 1 | [ 5 | ], 6 | 7 | 'listen' => [ 8 | 'AppInit' => [], 9 | 'HttpRun' => [], 10 | 'HttpEnd' => [], 11 | 'LogLevel' => [], 12 | 'LogWrite' => [], 13 | ], 14 | 15 | 'subscribe' => [ 16 | ], 17 | ]; 18 | -------------------------------------------------------------------------------- /app/index/common.php: -------------------------------------------------------------------------------- 1 | build(); 28 | if (request()->isPost() || request()->isAjax()) { 29 | $result = [ 30 | 'code' => $code, 31 | 'msg' => $msg, 32 | 'data' => $data, 33 | 'url' => $url, 34 | 'wait' => $wait, 35 | ]; 36 | return Response::create($result, 'json')->header($header); 37 | } 38 | 39 | if ($url === null) { 40 | $url = request()->server('HTTP_REFERER') ?? url('index/index/index')->build();; 41 | } 42 | 43 | return redirect($url); 44 | } 45 | } -------------------------------------------------------------------------------- /app/index/config/view.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | return [ 8 | // 模版替换参数 9 | 'tpl_replace_string' => [ 10 | '__STATIC__' => '/static', 11 | '__INDEX_STATIC__' => '/static/index', 12 | '__INDEX_JS__' => '/static/index/js', 13 | '__INDEX_CSS__' => '/static/index/css', 14 | '__INDEX_IMAGES__' => '/static/index/images', 15 | '__INDEX_PLUGINS__' => '/static/index/plugins', 16 | ] 17 | ]; 18 | -------------------------------------------------------------------------------- /app/index/controller/AuthController.php: -------------------------------------------------------------------------------- 1 | param(); 28 | 29 | //登录逻辑 30 | if($request->isPost()){ 31 | 32 | $check = $validate->scene('index_login')->check($param); 33 | if (!$check) { 34 | return index_error($validate->getError()); 35 | } 36 | try { 37 | $user = $service->login($param['username'], $param['password']); 38 | self::authLogin($user,(bool)($param['remember']??false)); 39 | return index_success('登录成功','index/index',$user); 40 | } catch (IndexServiceException $e) { 41 | return index_error($e->getMessage()); 42 | } 43 | } 44 | 45 | return $this->fetch(); 46 | } 47 | 48 | 49 | /** 50 | * 退出 51 | * @return Redirect 52 | */ 53 | public function logout(): Redirect 54 | { 55 | self::authLogout(); 56 | 57 | return redirect(url('index/auth/login')); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/index/controller/IndexController.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace app\index\controller; 10 | 11 | use Exception; 12 | 13 | class IndexController extends IndexBaseController 14 | { 15 | /** 16 | * @throws Exception 17 | */ 18 | public function index(): string 19 | { 20 | $this->index['name'] = '演示首页'; 21 | $this->index['title'] = '首页演示,自定义即可'; 22 | return $this->fetch(); 23 | } 24 | 25 | /** 26 | * @throws Exception 27 | */ 28 | public function product(): string 29 | { 30 | $this->index['name'] = '演示产品'; 31 | $this->index['title'] = '这是产品的演示页面,啊啊啊啊啊,这个地方可以用富文本,自己合理安排就行。。'; 32 | 33 | return $this->fetch(); 34 | } 35 | 36 | /** 37 | * @throws Exception 38 | */ 39 | public function about(): string 40 | { 41 | $this->index['name'] = '演示关于'; 42 | $this->index['title'] = '这是关于我们的演示页面,啊啊啊啊啊,这个地方可以用富文本,自己合理安排就行。。'; 43 | 44 | return $this->fetch(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/index/controller/UserController.php: -------------------------------------------------------------------------------- 1 | fetch(); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/index/exception/IndexServiceException.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | 10 | namespace app\index\exception; 11 | 12 | 13 | use Exception; 14 | 15 | class IndexServiceException extends Exception 16 | { 17 | 18 | } -------------------------------------------------------------------------------- /app/index/middleware.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | 10 | namespace app\index\service; 11 | 12 | 13 | use app\common\model\User; 14 | use app\index\exception\IndexServiceException; 15 | 16 | class AuthService extends IndexBaseService 17 | { 18 | 19 | protected $model; 20 | public function __construct() 21 | { 22 | $this->model = new User(); 23 | } 24 | 25 | /** 26 | * 用户登录 27 | * @param $username 28 | * @param $password 29 | * @return User|array|\think\Model 30 | * @throws IndexServiceException 31 | */ 32 | public function login($username,$password) 33 | { 34 | 35 | $user =$this->model->where('username' ,'=', $username)->findOrEmpty(); 36 | 37 | if ($user->isEmpty()) { 38 | throw new IndexServiceException('用户不存在'); 39 | } 40 | 41 | if (!password_verify($password, base64_decode($user->password))) { 42 | throw new IndexServiceException('密码错误'); 43 | } 44 | 45 | if ((int)$user->status !== 1) { 46 | throw new IndexServiceException('用户被冻结'); 47 | } 48 | return $user; 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /app/index/service/IndexBaseService.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | 10 | namespace app\index\service; 11 | 12 | 13 | class IndexBaseService 14 | { 15 | 16 | } -------------------------------------------------------------------------------- /app/middleware.php: -------------------------------------------------------------------------------- 1 | ExceptionHandle::class, 7 | ]; 8 | -------------------------------------------------------------------------------- /app/service.php: -------------------------------------------------------------------------------- 1 | =7.4", 24 | "topthink/framework": "^6.0.0", 25 | "topthink/think-orm": "^2.0", 26 | "topthink/think-multi-app": "^1.0", 27 | "topthink/think-view": "^1.0", 28 | "topthink/think-migration": "^3.0", 29 | "topthink/think-captcha": "^3.0", 30 | "phpoffice/phpspreadsheet": "^1.16", 31 | "mk-j/php_xlsxwriter": "^0.38.0", 32 | "ext-openssl": "*", 33 | "ext-json": "*", 34 | "ext-curl": "*", 35 | "topthink/think-filesystem": "^2.0" 36 | }, 37 | "require-dev": { 38 | "symfony/var-dumper": "^4.2", 39 | "topthink/think-trace": "^1.0" 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "app\\": "app" 44 | }, 45 | "psr-0": { 46 | "": "extend/" 47 | } 48 | }, 49 | "config": { 50 | "preferred-install": "dist" 51 | }, 52 | "scripts": { 53 | "post-autoload-dump": [ 54 | "@php think service:discover", 55 | "@php think vendor:publish", 56 | "@php think init:env" 57 | ] 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /config/app.php: -------------------------------------------------------------------------------- 1 | env('app.host', ''), 9 | // 应用的命名空间 10 | 'app_namespace' => '', 11 | // 是否启用路由 12 | 'with_route' => true, 13 | // 是否启用事件 14 | 'with_event' => true, 15 | // 默认应用 16 | 'default_app' => 'index', 17 | // 默认时区 18 | 'default_timezone' => env('app.default_timezone', 'Asia/Shanghai'), 19 | 20 | // 应用映射(自动多应用模式有效) 21 | 'app_map' => [], 22 | // 域名绑定(自动多应用模式有效) 23 | 'domain_bind' => [], 24 | // 禁止URL访问的应用列表(自动多应用模式有效) 25 | 'deny_app_list' => [ 26 | 'command', 27 | 'common', 28 | 'facade', 29 | 'service', 30 | ], 31 | 32 | // 异常页面的模板文件 33 | 'exception_tmpl' => app()->getAppPath() . 'common/exception/tpl/think_exception.tpl', 34 | 35 | // 错误显示信息,非调试模式有效 36 | 'error_message' => '系统繁忙,请稍后再试~', 37 | // 显示错误信息 38 | 'show_error_msg' => false, 39 | 'app_key' => env('app.app_key', ''), 40 | ]; 41 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('cache.driver', 'file'), 9 | 10 | // 缓存连接方式配置 11 | 'stores' => [ 12 | 'file' => [ 13 | // 驱动方式 14 | 'type' => 'File', 15 | // 缓存保存目录 16 | 'path' => '', 17 | // 缓存前缀 18 | 'prefix' => '', 19 | // 缓存有效期 0表示永久缓存 20 | 'expire' => 0, 21 | // 缓存标签前缀 22 | 'tag_prefix' => 'tag:', 23 | // 序列化机制 例如 ['serialize', 'unserialize'] 24 | 'serialize' => [], 25 | ], 26 | // redis缓存 27 | 'redis' => [ 28 | // 驱动方式 29 | 'type' => 'redis', 30 | // 服务器地址 31 | 'host' => env('redis.redis_host', '127.0.0.1'), 32 | 'port' => env('redis.redis_port', 6379), 33 | 'password' => env('redis.redis_password', ''), 34 | 'select' => env('redis.redis_select', 0), 35 | ], 36 | // 更多的缓存连接 37 | ], 38 | ]; 39 | -------------------------------------------------------------------------------- /config/captcha.php: -------------------------------------------------------------------------------- 1 | 5, 9 | // 验证码字符集合 10 | 'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY', 11 | // 验证码过期时间 12 | 'expire' => 1800, 13 | // 是否使用中文验证码 14 | 'useZh' => false, 15 | // 是否使用算术验证码 16 | 'math' => false, 17 | // 是否使用背景图 18 | 'useImgBg' => false, 19 | //验证码字符大小 20 | 'fontSize' => 25, 21 | // 是否使用混淆曲线 22 | 'useCurve' => true, 23 | //是否添加杂点 24 | 'useNoise' => true, 25 | // 验证码字体 不设置则随机 26 | 'fontttf' => '', 27 | //背景颜色 28 | 'bg' => [243, 251, 254], 29 | // 验证码图片高度 30 | 'imageH' => 48, 31 | // 验证码图片宽度 32 | 'imageW' => 240, 33 | 34 | // 添加额外的验证码设置 35 | // verify => [ 36 | // 'length'=>4, 37 | // ... 38 | //], 39 | ]; 40 | -------------------------------------------------------------------------------- /config/console.php: -------------------------------------------------------------------------------- 1 | [ 14 | // 测试指令 15 | 'test' => \app\command\Test::class, 16 | // 初始化env文件 17 | 'init:env' => InitEnv::class, 18 | // 生成新的app_key 19 | 'generate:app_key' => GenerateAppKey::class, 20 | // 生成新的jwt_key 21 | 'generate:jwt_key' => GenerateJwtKey::class, 22 | // 重置后台管理员密码 23 | 'reset:admin_password' => ResetAdminPassword::class 24 | ], 25 | ]; 26 | -------------------------------------------------------------------------------- /config/cookie.php: -------------------------------------------------------------------------------- 1 | 0, 8 | // cookie 保存路径 9 | 'path' => '/', 10 | // cookie 有效域名 11 | 'domain' => '', 12 | // cookie 启用安全传输 13 | 'secure' => false, 14 | // httponly设置 15 | 'httponly' => false, 16 | // 是否使用 setcookie 17 | 'setcookie' => true, 18 | ]; 19 | -------------------------------------------------------------------------------- /config/lang.php: -------------------------------------------------------------------------------- 1 | env('lang.default_lang', 'zh-cn'), 9 | // 允许的语言列表 10 | 'allow_lang_list' => [], 11 | // 多语言自动侦测变量名 12 | 'detect_var' => 'lang', 13 | // 是否使用Cookie记录 14 | 'use_cookie' => true, 15 | // 多语言cookie变量 16 | 'cookie_var' => 'app_lang', 17 | // 扩展语言包 18 | 'extend_list' => [], 19 | // Accept-Language转义为对应语言包名称 20 | 'accept_language' => [ 21 | 'zh-hans-cn' => 'zh-cn', 22 | ], 23 | // 是否支持语言分组 24 | 'allow_group' => false, 25 | ]; 26 | -------------------------------------------------------------------------------- /config/log.php: -------------------------------------------------------------------------------- 1 | env('log.channel', 'file'), 9 | // 日志记录级别 10 | 'level' => [], 11 | // 日志类型记录的通道 ['error'=>'email',...] 12 | 'type_channel' => [], 13 | // 关闭全局日志写入 14 | 'close' => false, 15 | // 全局日志处理 支持闭包 16 | 'processor' => null, 17 | 18 | // 日志通道列表 19 | 'channels' => [ 20 | 'file' => [ 21 | // 日志记录方式 22 | 'type' => 'File', 23 | // 日志保存目录 24 | 'path' => '', 25 | // 单文件日志写入 26 | 'single' => false, 27 | // 独立日志级别 28 | 'apart_level' => [], 29 | // 最大日志文件数量 30 | 'max_files' => 0, 31 | // 使用JSON格式记录 32 | 'json' => false, 33 | // 日志处理 34 | 'processor' => null, 35 | // 关闭通道日志写入 36 | 'close' => false, 37 | // 日志输出格式化 38 | 'format' => '[%s][%s] %s', 39 | // 是否实时写入 40 | 'realtime_write' => false, 41 | ], 42 | // 其它日志通道配置 43 | ], 44 | 45 | ]; 46 | -------------------------------------------------------------------------------- /config/map.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | return [ 10 | // 高德地图 11 | 'amap' => [ 12 | // 13 | 'web_api_key' => '7d1edf73d7afe85dcc33fbaaba935512', 14 | 'js_api_key' => 'cccf8ea926e153be0a013d55edd47c11', 15 | ], 16 | ]; -------------------------------------------------------------------------------- /config/middleware.php: -------------------------------------------------------------------------------- 1 | [], 6 | // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行 7 | 'priority' => [], 8 | ]; 9 | -------------------------------------------------------------------------------- /config/route.php: -------------------------------------------------------------------------------- 1 | '/', 9 | // URL伪静态后缀 10 | 'url_html_suffix' => 'html', 11 | // URL普通方式参数 用于自动生成 12 | 'url_common_param' => true, 13 | // 是否开启路由延迟解析 14 | 'url_lazy_route' => false, 15 | // 是否强制使用路由 16 | 'url_route_must' => false, 17 | // 合并路由规则 18 | 'route_rule_merge' => false, 19 | // 路由是否完全匹配 20 | 'route_complete_match' => false, 21 | // 访问控制器层名称 22 | 'controller_layer' => 'controller', 23 | // 空控制器名 24 | 'empty_controller' => 'Error', 25 | // 是否使用控制器后缀 26 | 'controller_suffix' => true, 27 | // 默认的路由变量规则 28 | 'default_route_pattern' => '[\w\.]+', 29 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 30 | 'request_cache' => false, 31 | // 请求缓存有效期 32 | 'request_cache_expire' => null, 33 | // 全局请求缓存排除规则 34 | 'request_cache_except' => [], 35 | // 默认控制器名 36 | 'default_controller' => 'Index', 37 | // 默认操作名 38 | 'default_action' => 'index', 39 | // 操作方法后缀 40 | 'action_suffix' => '', 41 | // 默认JSONP格式返回的处理方法 42 | 'default_jsonp_handler' => 'jsonpReturn', 43 | // 默认JSONP处理方法 44 | 'var_jsonp_handler' => 'callback', 45 | ]; 46 | -------------------------------------------------------------------------------- /config/session.php: -------------------------------------------------------------------------------- 1 | 'AppSId', 9 | // SESSION_ID的提交变量,解决flash上传跨域 10 | 'var_session_id' => '', 11 | // 驱动方式 支持file cache 12 | 'type' => 'file', 13 | // 存储连接标识 当type使用cache的时候有效 14 | 'store' => null, 15 | // 过期时间 16 | 'expire' => 1440, 17 | // 前缀 18 | 'prefix' => '', 19 | ]; 20 | -------------------------------------------------------------------------------- /config/trace.php: -------------------------------------------------------------------------------- 1 | 'Console', 8 | // 读取的日志通道名 9 | 'channel' => '', 10 | ]; 11 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | 'Think', 9 | // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法 10 | 'auto_rule' => 1, 11 | // 模板目录名 12 | 'view_dir_name' => 'view', 13 | // 模板后缀 14 | 'view_suffix' => 'html', 15 | // 模板文件名分隔符 16 | 'view_depr' => DIRECTORY_SEPARATOR, 17 | // 模板引擎普通标签开始标记 18 | 'tpl_begin' => '{', 19 | // 模板引擎普通标签结束标记 20 | 'tpl_end' => '}', 21 | // 标签库标签开始标记 22 | 'taglib_begin' => '{', 23 | // 标签库标签结束标记 24 | 'taglib_end' => '}', 25 | 'default_filter' => 'htmlentities_view', 26 | ]; 27 | -------------------------------------------------------------------------------- /database/example/README.md: -------------------------------------------------------------------------------- 1 | # 常用表迁移文件 2 | > 常用表迁移文件代码参考,可自行复制到迁移文件内使用。 3 | 4 | ### -------------------------------------------------------------------------------- /database/migrations/20200806100513_admin_log.php: -------------------------------------------------------------------------------- 1 | table('admin_log', ['comment' => '后台操作日志', 'engine' => 'InnoDB', 'encoding' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci']); 14 | $table 15 | ->addColumn('admin_user_id', 'integer', ['signed' => false, 'limit' => 10, 'comment' => '用户']) 16 | ->addColumn('name', 'string', ['limit' => 30, 'default' => '', 'comment' => '操作']) 17 | ->addColumn('url', 'string', ['limit' => 100, 'default' => '', 'comment' => 'URL']) 18 | ->addColumn('log_method', 'string', ['limit' => 8, 'default' => '不记录', 'comment' => '记录日志方法']) 19 | ->addColumn('log_ip', 'string', ['limit' => 20, 'default' => '', 'comment' => '操作IP']) 20 | ->addColumn('create_time', 'integer', ['signed' => false, 'limit' => 10, 'default' => 0, 'comment' => '创建时间']) 21 | ->addColumn('update_time', 'integer', ['signed' => false, 'limit' => 10, 'default' => 0, 'comment' => '更新时间']) 22 | ->addColumn('delete_time', 'integer', ['signed' => false, 'limit' => 10, 'default' => 0, 'comment' => '删除时间']) 23 | ->create(); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/migrations/20200806100516_admin_log_data.php: -------------------------------------------------------------------------------- 1 | table('admin_log_data', ['comment' => '后台操作日志数据', 'engine' => 'InnoDB', 'encoding' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci']); 16 | $table 17 | ->addColumn('admin_log_id', 'integer', ['signed' => false, 'limit' => 10, 'comment' => '日志ID']) 18 | ->addColumn('data', 'text', ['limit' => MysqlAdapter::TEXT_LONG, 'comment' => '日志内容']) 19 | ->addColumn('create_time', 'integer', ['signed' => false, 'limit' => 10, 'default' => 0, 'comment' => '创建时间']) 20 | ->addColumn('update_time', 'integer', ['signed' => false, 'limit' => 10, 'default' => 0, 'comment' => '更新时间']) 21 | ->addColumn('delete_time', 'integer', ['signed' => false, 'limit' => 10, 'default' => 0, 'comment' => '删除时间']) 22 | ->create(); 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/migrations/20210908031808_test.php: -------------------------------------------------------------------------------- 1 | table('test', ['comment' => '测试', 'engine' => 'InnoDB', 'encoding' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci']); 13 | $table 14 | ->addColumn('avatar', 'string', ['limit' => 255, 'default' => '/static/index/images/avatar.png', 'comment' => '头像']) 15 | ->addColumn('username', 'string', ['limit' => 30, 'default' => '', 'comment' => '用户名']) 16 | ->addColumn('nickname', 'string', ['limit' => 30, 'default' => '', 'comment' => '昵称']) 17 | ->addColumn('mobile', 'string', ['limit' => 11, 'default' => '', 'comment' => '手机号']) 18 | ->addColumn('user_level_id', 'integer', ['limit' => 10, 'default' => 1, 'comment' => '用户等级']) 19 | ->addColumn('password', 'string', ['limit' => 255, 'default' => base64_encode(password_hash('_default__password_', 1)), 'comment' => '密码']) 20 | ->addColumn('status', 'boolean', ['limit' => 1, 'default' => 1, 'comment' => '是否启用']) 21 | ->addColumn('lng', 'decimal', ['precision' => 14, 'scale' => 8, 'default' => 116, 'comment' => '经度'])// 测试地图 22 | ->addColumn('lat', 'decimal', ['precision' => 14, 'scale' => 8, 'default' => 37, 'comment' => '纬度']) 23 | ->addColumn('slide', 'text', [ 'comment' => '相册'])// 测试多图上传 24 | ->addColumn('content', 'text', [ 'comment' => '内容'])// 测试编辑器 25 | ->addColumn('create_time', 'integer', ['limit' => 10, 'default' => 0, 'comment' => '创建时间']) 26 | ->addColumn('update_time', 'integer', ['limit' => 10, 'default' => 0, 'comment' => '更新时间']) 27 | ->addColumn('delete_time', 'integer', ['limit' => 10, 'default' => 0, 'comment' => '删除时间']) 28 | ->create(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /extend/generate/exception/GenerateException.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\exception; 10 | 11 | use Exception; 12 | 13 | class GenerateException extends Exception 14 | { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /extend/generate/field/Color.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Color extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 30 | 31 | \n 32 | EOF; 33 | 34 | public static array $rules = [ 35 | 'required' => '非空', 36 | 'color16' => '16进制颜色', 37 | ]; 38 | 39 | public static function create($data): string 40 | { 41 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /extend/generate/field/Date.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Date extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | 22 | 23 | \n 24 | EOF; 25 | 26 | public static function create($data): string 27 | { 28 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 29 | } 30 | } -------------------------------------------------------------------------------- /extend/generate/field/DateRange.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class DateRange extends Field 10 | { 11 | 12 | public static string $html = << 14 | 15 |
16 | 17 |
18 | 24 | 25 | \n 26 | EOF; 27 | 28 | public static function create($data): string 29 | { 30 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 31 | } 32 | } -------------------------------------------------------------------------------- /extend/generate/field/Datetime.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Datetime extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | 23 | 24 | \n 25 | EOF; 26 | 27 | public static function create($data): string 28 | { 29 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 30 | } 31 | } -------------------------------------------------------------------------------- /extend/generate/field/DatetimeRange.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class DatetimeRange extends Field 10 | { 11 | 12 | public static string $html = << 14 | 15 |
16 | 17 |
18 | 25 | 26 | \n 27 | EOF; 28 | 29 | public static function create($data): string 30 | { 31 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 32 | } 33 | } -------------------------------------------------------------------------------- /extend/generate/field/Editor.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Editor extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 |
{\$data.[FIELD_NAME]|raw|default='

[FIELD_DEFAULT]

'}
16 | 17 |
18 | 32 | \n 33 | EOF; 34 | 35 | /** 36 | * @var string 富文本字段添加处理 37 | */ 38 | public static string $controllerAddCode = <<param(false)['[FIELD_NAME]']; 40 | \n 41 | EOF; 42 | /** 43 | * @var string 富文本字段修改处理 44 | */ 45 | public static string $controllerEditCode = <<param(false)['[FIELD_NAME]']; 47 | \n 48 | EOF; 49 | 50 | public static function create($data): string 51 | { 52 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 53 | } 54 | } -------------------------------------------------------------------------------- /extend/generate/field/Email.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Email extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static array $rules = [ 21 | 'required' => '非空', 22 | 'email' => '邮箱', 23 | ]; 24 | 25 | public static function create($data): string 26 | { 27 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 28 | } 29 | } -------------------------------------------------------------------------------- /extend/generate/field/File.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | namespace generate\field; 7 | 8 | class File extends Field 9 | { 10 | 11 | public static string $html = << 13 | 14 |
15 | 16 | 17 |
18 | 19 | 22 | \n 23 | EOF; 24 | 25 | public static function create($data): string 26 | { 27 | $html = self::$html; 28 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]'), array($data['form_name'], $data['field_name']), $html); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /extend/generate/field/Icon.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Icon extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 |
16 |
17 | 18 | 19 | 20 |
21 | 24 |
25 |
26 | 27 | 30 | \n 31 | EOF; 32 | 33 | public static function create($data): string 34 | { 35 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 36 | } 37 | } -------------------------------------------------------------------------------- /extend/generate/field/IdCard.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class IdCard extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static array $rules = [ 21 | 'required' => '非空', 22 | 'idCard' => '身份证', 23 | ]; 24 | 25 | 26 | public static function create($data): string 27 | { 28 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 29 | } 30 | } -------------------------------------------------------------------------------- /extend/generate/field/Image.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Image extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 |
16 | 17 | 18 | 21 |
22 |
23 | 24 | EOF; 25 | 26 | public static function create($data): string 27 | { 28 | $html = self::$html; 29 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), $html); 30 | } 31 | } -------------------------------------------------------------------------------- /extend/generate/field/Ip.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Ip extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static array $rules = [ 21 | 'required' => '非空', 22 | 'ipv4' => 'IPV4', 23 | 'ipv6' => 'IPV6', 24 | 'ip' => 'IP', 25 | ]; 26 | 27 | 28 | public static function create($data): string 29 | { 30 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 31 | } 32 | } -------------------------------------------------------------------------------- /extend/generate/field/Mobile.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Mobile extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static array $rules = [ 21 | 'required' => '非空', 22 | 'mobile' => '手机号', 23 | ]; 24 | 25 | public static function create($data): string 26 | { 27 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 28 | } 29 | } -------------------------------------------------------------------------------- /extend/generate/field/MultiFile.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class MultiFile extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 | 17 | 20 |
21 | 22 | EOF; 23 | 24 | public static function create($data): string 25 | { 26 | $html = self::$html; 27 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]'), array($data['form_name'], $data['field_name']), $html); 28 | } 29 | } -------------------------------------------------------------------------------- /extend/generate/field/MultiImage.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class MultiImage extends Field 10 | { 11 | public static string $html = << 14 | 15 |
16 |
17 | 18 | 19 | 22 |
23 |
24 | 25 | EOF; 26 | 27 | public static function create($data): string 28 | { 29 | $html = self::$html; 30 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]'), array($data['form_name'], $data['field_name']), $html); 31 | } 32 | } -------------------------------------------------------------------------------- /extend/generate/field/MultiSelect.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class MultiSelect extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 19 |
20 | 21 | 24 | \n 25 | EOF; 26 | 27 | public static function create($data): string 28 | { 29 | $html = self::$html; 30 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[OPTION_DATA]'), array($data['form_name'], $data['field_name'] ?? '', $data['option_data'] ?? ''), $html); 31 | } 32 | } -------------------------------------------------------------------------------- /extend/generate/field/Number.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Number extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 28 | \n 29 | EOF; 30 | 31 | public static array $rules = [ 32 | //非空 33 | 'required' => '非空', 34 | //纯数字 35 | 'number' => '纯数字', 36 | ]; 37 | 38 | public static function create($data): string 39 | { 40 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 41 | } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /extend/generate/field/Password.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Password extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static array $rules = [ 21 | 'required' => '非空', 22 | 'number6' => '6位纯数字', 23 | 'simplePassword' => '简单密码', 24 | 'middlePassword' => '中等密码', 25 | 'complexPassword' => '复杂密码', 26 | ]; 27 | 28 | public static function create($data): string 29 | { 30 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 31 | } 32 | } -------------------------------------------------------------------------------- /extend/generate/field/Select.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Select extends Field 10 | { 11 | 12 | public static string $html = << 14 | 15 |
16 | 20 |
21 | 22 | 27 | \n 28 | EOF; 29 | 30 | public static function create($data): string 31 | { 32 | $html = self::$html; 33 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[OPTION_DATA]'), array($data['form_name'], $data['field_name'] ?? '', $data['option_data'] ?? ''), $html); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /extend/generate/field/SwitchField.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | namespace generate\field; 7 | 8 | class SwitchField extends Field 9 | { 10 | public static string $html = << 12 | 13 |
14 | 16 | 17 |
18 | 19 | 30 | \n 31 | EOF; 32 | 33 | 34 | public static function create($data): string 35 | { 36 | $html = self::$html; 37 | //switch开的文字 38 | if (isset($data['on_text'])) { 39 | $html = str_replace('[ON_TEXT]', $data['on_text'], $html); 40 | } else { 41 | $html = str_replace('[ON_TEXT]', '是', $html); 42 | } 43 | //switch关的文字 44 | if (isset($data['off_text'])) { 45 | $html = str_replace('[OFF_TEXT]', $data['off_text'], $html); 46 | } else { 47 | $html = str_replace('[OFF_TEXT]', '否', $html); 48 | } 49 | 50 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), $html); 51 | } 52 | } -------------------------------------------------------------------------------- /extend/generate/field/Text.php: -------------------------------------------------------------------------------- 1 | 4 | */ 5 | 6 | namespace generate\field; 7 | 8 | class Text extends Field 9 | { 10 | 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static function create($data): string 21 | { 22 | return str_replace( 23 | array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), 24 | array($data['form_name'], $data['field_name'], $data['field_default']), 25 | self::$html); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /extend/generate/field/Textarea.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Textarea extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static function create($data): string 21 | { 22 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]', '[ROWS]'), array($data['form_name'], $data['field_name'], $data['field_default'], $data['rows'] ?? 3), self::$html); 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /extend/generate/field/Time.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Time extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | 18 | 24 | \n 25 | EOF; 26 | 27 | public static array $rules = [ 28 | 'required' => '非空', 29 | 'time' => '时间', 30 | ]; 31 | 32 | 33 | public static function create($data): string 34 | { 35 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 36 | } 37 | } -------------------------------------------------------------------------------- /extend/generate/field/TimeRange.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class TimeRange extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | 18 | 25 | \n 26 | EOF; 27 | 28 | public static array $rules = [ 29 | 'required' => '非空', 30 | 'time_range' => '时间范围', 31 | ]; 32 | 33 | public static function create($data): string 34 | { 35 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 36 | } 37 | } -------------------------------------------------------------------------------- /extend/generate/field/Url.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Url extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 |
17 | \n 18 | EOF; 19 | 20 | public static array $rules = [ 21 | 'required' => '非空', 22 | 'url' => 'URL', 23 | ]; 24 | 25 | 26 | public static function create($data): string 27 | { 28 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 29 | } 30 | } -------------------------------------------------------------------------------- /extend/generate/field/Video.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Video extends Field 10 | { 11 | public static string $html = << 13 | 14 |
15 | 16 | 17 |
18 | 19 | 22 | \n 23 | EOF; 24 | 25 | public static function create($data): string 26 | { 27 | $html = self::$html; 28 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]'), array($data['form_name'], $data['field_name']), $html); 29 | } 30 | } -------------------------------------------------------------------------------- /extend/generate/field/Year.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class Year extends Field 10 | { 11 | 12 | public static string $html = << 14 | 15 |
16 | 17 |
18 | 19 | 25 | \n 26 | EOF; 27 | public static array $rules = [ 28 | 'required' => '非空', 29 | 'year' => '年', 30 | ]; 31 | 32 | public static function create($data): string 33 | { 34 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 35 | } 36 | } -------------------------------------------------------------------------------- /extend/generate/field/YearMonth.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class YearMonth extends Field 10 | { 11 | 12 | public static string $html = << 14 | 15 |
16 | 17 |
18 | 19 | 25 | \n 26 | EOF; 27 | 28 | public static array $rules = [ 29 | 'required' => '非空', 30 | 'year_month' => '年月', 31 | ]; 32 | 33 | public static function create($data): string 34 | { 35 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 36 | } 37 | } -------------------------------------------------------------------------------- /extend/generate/field/YearMonthRange.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class YearMonthRange extends Field 10 | { 11 | 12 | public static string $html = << 14 | 15 |
16 | 17 |
18 | 25 | \n 26 | EOF; 27 | 28 | public static array $rules = [ 29 | 'required' => '非空', 30 | 'year_month_range' => '年月范围', 31 | ]; 32 | 33 | 34 | public static function create($data): string 35 | { 36 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 37 | } 38 | } -------------------------------------------------------------------------------- /extend/generate/field/YearRange.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | namespace generate\field; 8 | 9 | class YearRange extends Field 10 | { 11 | 12 | public static string $html = << 14 | 15 |
16 | 17 |
18 | 19 | 26 | \n 27 | EOF; 28 | 29 | public static array $rules = [ 30 | 'required' => '非空', 31 | 'year' => '年范围', 32 | ]; 33 | 34 | public static function create($data): string 35 | { 36 | return str_replace(array('[FORM_NAME]', '[FIELD_NAME]', '[FIELD_DEFAULT]'), array($data['form_name'], $data['field_name'], $data['field_default']), self::$html); 37 | } 38 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/AdminController.stub: -------------------------------------------------------------------------------- 1 | isPost()) { 12 | $param = $request->param(); 13 | $validate_result = $validate->scene('admin_add')->check($param); 14 | if (!$validate_result) { 15 | return admin_error($validate->getError()); 16 | } 17 | [ADD_FIELD_CODE] 18 | $result = $model::create($param); 19 | 20 | $url = URL_BACK; 21 | if (isset($param['_create']) && (int)$param['_create'] === 1) { 22 | $url = URL_RELOAD; 23 | } 24 | return $result ? admin_success('添加成功', [], $url) : admin_error(); 25 | } 26 | [RELATION_2] 27 | return $this->fetch(); 28 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/action_del.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 删除 3 | * @param mixed $id 4 | * @param [MODEL_NAME] $model 5 | * @return Json 6 | */ 7 | public function del($id, [MODEL_NAME] $model): Json 8 | { 9 | $check = $model->inNoDeletionIds($id); 10 | if (false !== $check) { 11 | return admin_error('ID为' . $check . '的数据不能被删除'); 12 | } 13 | 14 | $result = $model::destroy(static function ($query) use ($id) { 15 | /** @var Query $query */ 16 | $query->whereIn('id', $id); 17 | }); 18 | 19 | return $result ? admin_success('删除成功', [], URL_RELOAD) : admin_error('删除失败'); 20 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/action_disable.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 禁用 3 | * @param mixed $id 4 | * @param [MODEL_NAME] $model 5 | * @return Json 6 | */ 7 | public function disable($id, [MODEL_NAME] $model): Json 8 | { 9 | $result = $model->whereIn('id', $id)->update(['status' => 0]); 10 | return $result ? admin_success('操作成功', [], URL_RELOAD) : admin_error(); 11 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/action_edit.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 修改 3 | * @param $id 4 | * @param Request $request 5 | * @param [MODEL_NAME] $model 6 | * @param [VALIDATE_NAME]Validate $validate 7 | * @return string|Json 8 | * @throws Exception 9 | */ 10 | public function edit($id, Request $request, [MODEL_NAME] $model, [VALIDATE_NAME]Validate $validate) 11 | { 12 | $data = $model->findOrEmpty($id); 13 | if ($request->isPost()) { 14 | $param = $request->param(); 15 | $check = $validate->scene('admin_edit')->check($param); 16 | if (!$check) { 17 | return admin_error($validate->getError()); 18 | } 19 | [EDIT_FIELD_CODE] 20 | $result = $data->save($param); 21 | 22 | return $result ? admin_success('修改成功', [], URL_BACK) : admin_error('修改失败'); 23 | } 24 | 25 | $this->assign([ 26 | 'data' => $data, 27 | [RELATION_3] 28 | ]); 29 | 30 | return $this->fetch('add'); 31 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/action_enable.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 启用 3 | * @param mixed $id 4 | * @param [MODEL_NAME] $model 5 | * @return Json 6 | */ 7 | public function enable($id, [MODEL_NAME] $model): Json 8 | { 9 | $result = $model->whereIn('id', $id)->update(['status' => 1]); 10 | return $result ? admin_success('操作成功', [], URL_RELOAD) : admin_error(); 11 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/action_export.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 导出 3 | * @param Request $request 4 | * @param [MODEL_NAME] $model 5 | * @throws Exception 6 | */ 7 | public function export(Request $request, [MODEL_NAME] $model) 8 | { 9 | $param = $request->param(); 10 | $data = $model[RELATION_WITH]->scope('where', $param)->select(); 11 | 12 | $header = [[HEADER_LIST]]; 13 | $body = []; 14 | foreach ($data as $item) { 15 | $record = []; 16 | [BODY_ITEM] 17 | $body[] = $record; 18 | } 19 | $this->exportData($header, $body, '[FILE_NAME]-' . date('YmdHis')); 20 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/action_import.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 导入 3 | * @param Request $request 4 | * @return Json 5 | */ 6 | public function import(Request $request): Json 7 | { 8 | $param = $request->param(); 9 | $field_name_list = [[FILED_NAME_LIST]]; 10 | if (isset($param['action']) && $param['action'] === 'download_example') { 11 | $this->downloadExample($field_name_list); 12 | } 13 | 14 | $field_list = [[FILED_LIST]]; 15 | $result = $this->importData('file','[TABLE_NAME]',$field_list); 16 | 17 | return true === $result ? admin_success('操作成功', [], URL_RELOAD) : admin_error($result); 18 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/action_index.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 列表 3 | * @param Request $request 4 | * @param [MODEL_NAME] $model 5 | * @return string 6 | * @throws Exception 7 | */ 8 | public function index(Request $request, [MODEL_NAME] $model): string 9 | { 10 | $param = $request->param(); 11 | $data = $model[RELATION_WITH]->scope('where', $param) 12 | ->paginate([ 13 | 'list_rows' => $this->admin['admin_list_rows'], 14 | 'var_page' => 'page', 15 | 'query' => $request->get(), 16 | ]); 17 | // 关键词,排序等赋值 18 | $this->assign($request->get()); 19 | 20 | $this->assign([ 21 | 'data' => $data, 22 | 'page' => $data->render(), 23 | 'total' => $data->total(), 24 | [SEARCH_DATA_LIST] 25 | ]); 26 | return $this->fetch(); 27 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/relation_assign_1.stub: -------------------------------------------------------------------------------- 1 | $this->assign([ 2 | [RELATION_LIST] 3 | ]); 4 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/relation_data_list.stub: -------------------------------------------------------------------------------- 1 | '[LIST_NAME]' => [CLASS_NAME]::select(), 2 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/relation_delete.stub: -------------------------------------------------------------------------------- 1 | // 关联数据删除限制 2 | $msg_[FIELD_NAME] = '下有[FORM_NAME]数据,请删除[FORM_NAME]后再进行删除操作'; 3 | if(is_array($id)){ 4 | foreach ($id as $item){ 5 | $data = $model::get($item); 6 | if($data->school->count()>0){ 7 | return error($data->name.$msg_[FIELD_NAME]); 8 | } 9 | } 10 | }else{ 11 | $data = $model::get($id); 12 | if($data->school->count()>0){ 13 | return error($data->name.$msg_[FIELD_NAME]); 14 | } 15 | } -------------------------------------------------------------------------------- /extend/generate/stub/admin_controller/relation_with.stub: -------------------------------------------------------------------------------- 1 | ->with([[WITH_LIST]]) -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/add/customer_multi_select_data.stub: -------------------------------------------------------------------------------- 1 | {foreach [FIELD_LIST] as $key=>$value} 2 | 3 | {/foreach} 4 | 5 | 6 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/add/customer_select_data.stub: -------------------------------------------------------------------------------- 1 | {foreach [FIELD_LIST] as $key=>$value} 2 | 3 | {/foreach} 4 | 5 | 6 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/add/relation_select_data.stub: -------------------------------------------------------------------------------- 1 | {foreach name='[DATA_LIST]' id='item'} 2 | 5 | {/foreach} -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/create.stub: -------------------------------------------------------------------------------- 1 | 2 | 添加 3 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/del1.stub: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/del2.stub: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/enable1.stub: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/enable2.stub: -------------------------------------------------------------------------------- 1 | {if $item.status==1} 2 | 6 | {else/} 7 | 11 | {/if} 12 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/export.stub: -------------------------------------------------------------------------------- 1 |
2 | 4 |
-------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/filter.stub: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 | 8 |
9 | 11 |
12 | [SEARCH_HTML] 13 | [SORT_CODE] 14 | 15 |
16 | 18 |
19 | [INDEX_EXPORT] 20 |
21 | 24 |
25 |
26 |
27 |
28 |
29 |
-------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/refresh.stub: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/select1.stub: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/select2.stub: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /extend/generate/stub/admin_view/index/sort.stub: -------------------------------------------------------------------------------- 1 |
2 | 6 |
7 | 8 |
9 | 14 |
15 | -------------------------------------------------------------------------------- /extend/generate/stub/api_controller/ApiController.stub: -------------------------------------------------------------------------------- 1 | scene('api_add')->check($this->param); 10 | if (!$check) { 11 | return api_error($validate->getError()); 12 | } 13 | 14 | $result = $service->createData($this->param); 15 | 16 | return $result ? api_success() : api_error(); 17 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_controller/api_del.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 删除 3 | * @param [SERVICE_NAME]Service $service 4 | * @param [VALIDATE_NAME]Validate $validate 5 | * @return Json 6 | */ 7 | public function del([SERVICE_NAME]Service $service, [VALIDATE_NAME]Validate $validate): Json 8 | { 9 | $check = $validate->scene('api_del')->check($this->param); 10 | if (!$check) { 11 | return api_error($validate->getError()); 12 | } 13 | 14 | try { 15 | $service->deleteData($this->id); 16 | return api_success(); 17 | } catch (ApiServiceException $e) { 18 | return api_error($e->getMessage()); 19 | } 20 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_controller/api_disable.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 禁用 3 | * @param [SERVICE_NAME]Service $service 4 | * @param [VALIDATE_NAME]Validate $validate 5 | * @return Json 6 | */ 7 | public function disable([SERVICE_NAME]Service $service, [VALIDATE_NAME]Validate $validate): Json 8 | { 9 | $check = $validate->scene('api_disable')->check($this->param); 10 | if (!$check) { 11 | return api_error($validate->getError()); 12 | } 13 | 14 | try { 15 | $service->disableData($this->id); 16 | return api_success(); 17 | } catch (ApiServiceException $e) { 18 | return api_error($e->getMessage()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /extend/generate/stub/api_controller/api_edit.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 修改 3 | * @param [SERVICE_NAME]Service $service 4 | * @param [VALIDATE_NAME]Validate $validate 5 | * @return Json 6 | */ 7 | public function edit([SERVICE_NAME]Service $service, [VALIDATE_NAME]Validate $validate): Json 8 | { 9 | $check = $validate->scene('api_edit')->check($this->param); 10 | if (!$check) { 11 | return api_error($validate->getError()); 12 | } 13 | 14 | try { 15 | $service->updateData($this->id, $this->param); 16 | return api_success(); 17 | } catch (ApiServiceException $e) { 18 | return api_error($e->getMessage()); 19 | } 20 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_controller/api_enable.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 启用 3 | * @param [SERVICE_NAME]Service $service 4 | * @param [VALIDATE_NAME]Validate $validate 5 | * @return Json 6 | */ 7 | public function enable([SERVICE_NAME]Service $service, [VALIDATE_NAME]Validate $validate): Json 8 | { 9 | $check = $validate->scene('api_enable')->check($this->param); 10 | if (!$check) { 11 | return api_error($validate->getError()); 12 | } 13 | 14 | try { 15 | $service->enableData($this->id); 16 | return api_success(); 17 | } catch (ApiServiceException $e) { 18 | return api_error($e->getMessage()); 19 | } 20 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_controller/api_index.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 列表 3 | * @param [SERVICE_NAME]Service $service 4 | * @return Json 5 | */ 6 | public function index([SERVICE_NAME]Service $service): Json 7 | { 8 | try { 9 | $data = $service->getList($this->param, $this->page, $this->limit); 10 | $result = [ 11 | '[TABLE_NAME]' => $data, 12 | ]; 13 | 14 | return api_success($result); 15 | } catch (ApiServiceException $e) { 16 | return api_error($e->getMessage()); 17 | } 18 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_controller/api_info.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 详情 3 | * @param [VALIDATE_NAME]Validate $validate 4 | * @param [SERVICE_NAME]Service $service 5 | * @return Json 6 | */ 7 | public function info([SERVICE_NAME]Validate $validate, [VALIDATE_NAME]Service $service): Json 8 | { 9 | $check = $validate->scene('api_info')->check($this->param); 10 | if (!$check) { 11 | return api_error($validate->getError()); 12 | } 13 | 14 | try { 15 | 16 | $result = $service->getDataInfo($this->id); 17 | return api_success([ 18 | '[TABLE_NAME]' => $result, 19 | ]); 20 | 21 | } catch (ApiServiceException $e) { 22 | return api_error($e->getMessage()); 23 | } 24 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_service/ApiService.stub: -------------------------------------------------------------------------------- 1 | model = new [MODEL_NAME](); 21 | } 22 | 23 | [SERVICE_INDEX] 24 | 25 | [SERVICE_ADD] 26 | 27 | [SERVICE_INFO] 28 | 29 | [SERVICE_EDIT] 30 | 31 | [SERVICE_DEL] 32 | 33 | [SERVICE_DISABLE] 34 | 35 | [SERVICE_ENABLE] 36 | } 37 | -------------------------------------------------------------------------------- /extend/generate/stub/api_service/api_add.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 添加 3 | * @param $param 4 | * @return bool 5 | */ 6 | public function createData($param): bool 7 | { 8 | $result = $this->model::create($param); 9 | return (bool)$result; 10 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_service/api_del.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 删除 3 | * @param mixed $id 4 | * @return bool 5 | * @throws ApiServiceException 6 | */ 7 | public function deleteData($id): bool 8 | { 9 | $result = $this->model::destroy(function ($query) use ($id) { 10 | $query->whereIn('id', $id); 11 | }); 12 | 13 | if (!$result) { 14 | throw new ApiServiceException('更新失败'); 15 | } 16 | 17 | return true; 18 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_service/api_disable.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 禁用 3 | * @param mixed $id 4 | * @return bool 5 | * @throws ApiServiceException 6 | */ 7 | public function disableData($id): bool 8 | { 9 | $result = $this->model 10 | ->whereIn('id', $id) 11 | ->save(['status' => 0]); 12 | 13 | if (!$result) { 14 | throw new ApiServiceException('禁用失败'); 15 | } 16 | 17 | return true; 18 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_service/api_edit.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 修改 3 | * @param $id 4 | * @param $param 5 | * @return bool 6 | * @throws ApiServiceException 7 | */ 8 | public function updateData($id, $param): bool 9 | { 10 | $data = $this->model->where('id', '=', $id)->findOrEmpty(); 11 | if ($data->isEmpty()) { 12 | throw new ApiServiceException('数据不存在'); 13 | } 14 | $result = $data->save($param); 15 | 16 | if (!$result) { 17 | throw new ApiServiceException('更新失败'); 18 | } 19 | 20 | return true; 21 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_service/api_enable.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 启用 3 | * @param mixed $id 4 | * @return bool 5 | * @throws ApiServiceException 6 | */ 7 | public function enableData($id): bool 8 | { 9 | $result = $this->model 10 | ->whereIn('id', $id) 11 | ->save(['status' => 1]); 12 | 13 | if (!$result) { 14 | throw new ApiServiceException('启用失败'); 15 | } 16 | return true; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /extend/generate/stub/api_service/api_index.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 列表 3 | * @param $param 4 | * @param $page 5 | * @param $limit 6 | * @return array 7 | * @throws ApiServiceException 8 | */ 9 | public function getList($param, $page, $limit): array 10 | { 11 | try { 12 | $field = '[FIELD_LIST]'; 13 | $data = $this->model 14 | ->scope('ApiWhere', $param) 15 | ->page($page, $limit) 16 | ->field($field) 17 | ->select() 18 | ->toArray(); 19 | } catch (DataNotFoundException | ModelNotFoundException $e) { 20 | $data = []; 21 | } catch (DbException $e) { 22 | throw new ApiServiceException('查询列表失败,信息' . $e->getMessage()); 23 | } 24 | 25 | return $data; 26 | } -------------------------------------------------------------------------------- /extend/generate/stub/api_service/api_info.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * 数据详情 3 | * @param $id 4 | * @return array 5 | * @throws ApiServiceException 6 | */ 7 | public function getDataInfo($id): array 8 | { 9 | $data = $this->model->where('id', '=', $id)->findOrEmpty(); 10 | if ($data->isEmpty()) { 11 | throw new ApiServiceException('数据不存在'); 12 | } 13 | return $data->toArray(); 14 | } -------------------------------------------------------------------------------- /extend/generate/stub/model/Model.stub: -------------------------------------------------------------------------------- 1 | [RELATION_TYPE]([CLASS_NAME]::class); 7 | } -------------------------------------------------------------------------------- /extend/generate/stub/validate/Validate.stub: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Color16 extends Rule 12 | { 13 | protected string $name = 'color16'; 14 | 15 | protected string $msg = '必须为十六进制颜色代码'; 16 | } 17 | -------------------------------------------------------------------------------- /extend/generate/validate/ComplexPassword.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class ComplexPassword extends Rule 12 | { 13 | protected string $name = 'complexPassword'; 14 | protected string $msg = '至少1个大写字母和1个小写字母和1个数字和1个特殊字符,8-16位'; 15 | } -------------------------------------------------------------------------------- /extend/generate/validate/Email.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Email extends Rule 12 | { 13 | protected string $name = 'email'; 14 | protected string $msg = '必须为邮箱地址'; 15 | } 16 | -------------------------------------------------------------------------------- /extend/generate/validate/IdCard.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class IdCard extends Rule 12 | { 13 | protected string $name = 'idCard'; 14 | protected string $msg = '必须为身份证号码'; 15 | } 16 | -------------------------------------------------------------------------------- /extend/generate/validate/Ip.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Ip extends Rule 12 | { 13 | protected string $name = 'ip'; 14 | protected string $msg = '必须为IP地址'; 15 | } 16 | -------------------------------------------------------------------------------- /extend/generate/validate/Ipv4.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | declare (strict_types=1); 7 | 8 | namespace generate\validate; 9 | 10 | class Ipv4 extends Rule 11 | { 12 | protected string $name = 'ipv4'; 13 | protected string $msg = '必须为IPV4地址'; 14 | } 15 | -------------------------------------------------------------------------------- /extend/generate/validate/Ipv6.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Ipv6 extends Rule 12 | { 13 | protected string $name = 'ipv6'; 14 | protected string $msg = '必须为IPV6地址'; 15 | } 16 | -------------------------------------------------------------------------------- /extend/generate/validate/MiddlePassword.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class MiddlePassword extends Rule 12 | { 13 | protected string $name = 'middlePassword'; 14 | protected string $msg = '至少1个大写字母和1个小写字母和1个数字,8-16位'; 15 | } -------------------------------------------------------------------------------- /extend/generate/validate/Mobile.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Mobile extends Rule 12 | { 13 | protected string $name = 'mobile'; 14 | protected string $msg = '必须为11位手机号码'; 15 | } 16 | -------------------------------------------------------------------------------- /extend/generate/validate/Number.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Number extends Rule 12 | { 13 | protected string $name = 'number'; 14 | protected string $msg = '必须为纯数字'; 15 | } 16 | -------------------------------------------------------------------------------- /extend/generate/validate/Number6.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Number6 extends Rule 12 | { 13 | protected string $name = 'number6'; 14 | 15 | protected string $msg = '必须为6位数字'; 16 | } 17 | -------------------------------------------------------------------------------- /extend/generate/validate/Required.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace generate\validate; 10 | 11 | class Required extends Rule 12 | { 13 | 14 | protected string $name = 'required'; 15 | protected string $msg = '不能为空'; 16 | } 17 | -------------------------------------------------------------------------------- /extend/generate/validate/SimplePassword.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | declare (strict_types=1); 7 | 8 | namespace generate\validate; 9 | 10 | class SimplePassword extends Rule 11 | { 12 | protected string $name = 'simplePassword'; 13 | protected string $msg = '至少1个字母和1个数字,6-16位'; 14 | } -------------------------------------------------------------------------------- /extend/generate/validate/Url.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | declare (strict_types=1); 7 | 8 | namespace generate\validate; 9 | 10 | class Url extends Rule 11 | { 12 | protected string $name = 'url'; 13 | protected string $msg = '必须为正确的网址'; 14 | } 15 | -------------------------------------------------------------------------------- /extend/util/jwt/JwtException.php: -------------------------------------------------------------------------------- 1 | 5 | */ 6 | 7 | declare (strict_types=1); 8 | 9 | namespace util\jwt; 10 | 11 | use Exception; 12 | 13 | class JwtException extends Exception 14 | { 15 | 16 | } -------------------------------------------------------------------------------- /extend/util/jwt/README.md: -------------------------------------------------------------------------------- 1 | # JWT加密验证 2 | 3 | > 简单的jwt加密验证扩展 4 | 5 | ## 使用方法 6 | 7 | ### HS256(HS384,HS512)加密 8 | 9 | ```php 10 | 11 | $key = 'ThisIsKey'; 12 | $jwt =new \util\jwt\Jwt(); 13 | $token = $jwt->setAlg('HS256') 14 | ->setKey($key) 15 | ->setClaim() 16 | ->getToken(); 17 | 18 | ``` 19 | 20 | ### HS256(HS384,HS512)验证 21 | 22 | ```php 23 | $token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3MiLCJhdWQiOiJhdWQiLCJqdGkiOiI2YjkxNTE3YmZkMzM5YmI4ZDI5MmJiOGM1NmYzZDVkOSIsImlhdCI6MTYzNjM0MTQ3NywibmJmIjoxNjM2MzQxNDc3LCJleHAiOjE2MzYzNDg2NzcsInVpZCI6MX0.352KUpUo08S6ujeSCyVhwYgA9l5XMU9drremhFE5KKM'; 24 | $key = 'ThisIsKey'; 25 | $jwt =new \util\jwt\Jwt(); 26 | $result = $jwt->setAlg('HS256')->setKey($key)->checkToken($token); 27 | if($result===true){ 28 | $uid = $jwt->getUid(); 29 | }else{ 30 | var_dump($jwt->getMessage()); 31 | } 32 | ``` 33 | 34 | ### RS256(RS384,RS512)加密 35 | ```php 36 | $private_key = 'ThisIsKey'; 37 | $jwt =new \util\jwt\Jwt(); 38 | $token = $jwt->setAlg('RS256') 39 | ->setPrivateKey($private_key) 40 | ->setClaim() 41 | ->getToken(); 42 | ``` 43 | ### RS256(RS384,RS512)验证 44 | ```php 45 | $public_key = 'ThisIsKey'; 46 | $jwt =new \util\jwt\Jwt(); 47 | $token = $jwt->setAlg('RS256') 48 | ->setPublicKey($key) 49 | ->setClaim() 50 | ->getToken(); 51 | ``` 52 | 53 | 具体示例代码可参考Example.php文件内方法。 -------------------------------------------------------------------------------- /extend/util/jwt/private.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtGJrW/kUyp8AS 3 | UhAm/c928vRlO8Ie0CV+/T0PkD0mbEHyaU8ikClUXI1MBpDaCOtSC40y2izCZ1uU 4 | JvUPuJ8nzKwIwtgEGmdj8k2hJy0QzR8Swk2jhzxd+xT8oaOWdUXD4rZsATxLqNXm 5 | 2cbykWRSWdyiquOfFjfh3pAak9cs3zhXeL21wiJtLJdcimQjpaltPZDB0WWOi5Eg 6 | pMo/Dc9FIn7r+Oq6Yop7ShhrVGxji36GiAUvay3lVOpCRPrA2ql8jdgmWpXehMGA 7 | WBNTfOK5UFmI/PA+frhEy0mU7CrjVR96Hm/egbROkXJemB+gxpwwwAPGMpsiWq45 8 | qAOrXCgjAgMBAAECggEAAz2hsILEMuWXIACvUruPxc9YqgiLYt5MxWriWMc/jdeb 9 | CHnWRHRkgbLV5mV9Esf19+xFcX1KNz2OJmDwV6ICQNGBKwzS1IjWBLYFpA3CtzzP 10 | 5x8CKxyeEbhgtTYlhOyfKMK23aDMSzJXBuJu6h20viH2kokWh+T3mN/83LKF5c4k 11 | MtNsQvXKrUI53M6qWfx+ZnmhUuM+LAX/Mq0WhJMEf6Af8uB44Elf4A3MEOdqhhyn 12 | BPo/a8kNFKshgf//FvjLY7agnQ/uEdvAicQEAh1OhIp8cdr07jgchsTRM+eOWqCL 13 | 12pMIOVVybvkwQqGldYPOek1cGASEjM1SHc77Rs98QKBgQDVXIRbGQrEkSvOMTML 14 | LKn8lTToJn1h36O5JqXB6ngRWiXLgF9GpnWSyp0U8qXeXd4D6ZExHP7G1/Ny44lt 15 | KNBYaJAN1VlqqvVMA70MoEbyuFLREGTMa+MXAPpfs5Ue+kixYIEj9rkeiZDQDusc 16 | pD5RLkTcOMDBrRByfAuEkgyHiwKBgQDPsCHZqkRGEGRIA8xcYCtfcgDFtUoyJ3a3 17 | FG8H+805gbP5hc0EhPSnRlacrL2yNxabB4XfH3gdQKlo8lgDe0W0E1ynHwbGQ6mq 18 | KhPgEx5wI9UPY6WJmg7aCij3FSH/j/sD6S5lUazm6mpP6ZfO9bivKZ1MXBmAhYFs 19 | ARo5V6i0yQKBgQCYeAm5U9bnC1rDeVMhrCQ5dKKfN0ooU/maySxwu85bkBEsMKtl 20 | QHUKljHUk2XG10tdfl6cOz0x+YZmVoWRdTYVx3sR96FzYYHzdUR2rl6k+uVrswxl 21 | LL/WY4OIOjvZLEAgSXdfrOMzGFlc5RxMlm5V8vuQaBoPDU6QkWZlsTy06wKBgEs1 22 | CMz9b0O/49CAL5yz5oDlk4oEoB2RVNfvOlW1xRcx9K5C2X7tdnqsaejKVNcYQ8NX 23 | 8g5eIuzU4YPzXhPEq/UNnduWzKk3D1Vjb1cRFVCeaSTtfKBbfU1PqI3wxSL6THea 24 | FQbzkJz9/gl6GVMEgCBN/XwNTd7QeZFWxNxG9fyhAoGARYj8aXtMzUefSblVJGvq 25 | FGNfu6M8/ddKZGV3iFApPHozrJW5zeCHuOUfdWljIq73yvd3TY0+YJH4csDQjCNH 26 | 9mIf/iflCkbR3PnmwrYJziUrEr0if8pHk/MgPWjFS7V+J9C+JTRBWspvXIcDljmD 27 | t1cZfREnNoEV5Rpwb1bC4iY= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /extend/util/jwt/public.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArRia1v5FMqfAElIQJv3P 3 | dvL0ZTvCHtAlfv09D5A9JmxB8mlPIpApVFyNTAaQ2gjrUguNMtoswmdblCb1D7if 4 | J8ysCMLYBBpnY/JNoSctEM0fEsJNo4c8XfsU/KGjlnVFw+K2bAE8S6jV5tnG8pFk 5 | UlncoqrjnxY34d6QGpPXLN84V3i9tcIibSyXXIpkI6WpbT2QwdFljouRIKTKPw3P 6 | RSJ+6/jqumKKe0oYa1RsY4t+hogFL2st5VTqQkT6wNqpfI3YJlqV3oTBgFgTU3zi 7 | uVBZiPzwPn64RMtJlOwq41Ufeh5v3oG0TpFyXpgfoMacMMADxjKbIlquOagDq1wo 8 | IwIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymlinks -Multiviews 3 | RewriteEngine On 4 | 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 8 | 9 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // [ 应用入口文件 ] 13 | namespace think; 14 | 15 | require __DIR__ . '/../vendor/autoload.php'; 16 | 17 | // 执行HTTP应用并响应 18 | $http = (new App())->http; 19 | 20 | $response = $http->run(); 21 | 22 | $response->send(); 23 | 24 | $http->end($response); 25 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow:/admin/ 3 | Disallow:/api/ 4 | -------------------------------------------------------------------------------- /public/router.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | // $Id$ 12 | 13 | if (is_file($_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_NAME'])) { 14 | return false; 15 | } 16 | 17 | $_SERVER['SCRIPT_FILENAME'] = __DIR__ . '/index.php'; 18 | 19 | require __DIR__ . '/index.php'; 20 | -------------------------------------------------------------------------------- /public/static/admin/css/access.css: -------------------------------------------------------------------------------- 1 | .checkbox { 2 | cursor: pointer; 3 | } 4 | 5 | .checkMod { 6 | margin-bottom: 20px; 7 | border: 1px solid #ebebeb; 8 | padding-bottom: 5px; 9 | } 10 | 11 | .checkMod dt { 12 | padding-left: 10px; 13 | height: 30px; 14 | line-height: 30px; 15 | font-weight: bold; 16 | border-bottom: 1px solid #ebebeb; 17 | background-color: #ECECEC; 18 | } 19 | 20 | .checkMod dt { 21 | margin-bottom: 5px; 22 | border-bottom-color: #ebebeb; 23 | background-color: #ECECEC; 24 | } 25 | 26 | .checkbox, .radio { 27 | display: inline-block; 28 | height: 20px; 29 | line-height: 20px; 30 | margin-left: 20px; 31 | margin-right: 20px; 32 | } 33 | 34 | .checkMod dd { 35 | padding-left: 30px; 36 | line-height: 30px; 37 | } 38 | 39 | .checkMod dd .checkbox { 40 | margin: 0 30px 0 0; 41 | font-weight: normal; 42 | } 43 | 44 | .checkMod dd .divsion { 45 | margin-right: 20px; 46 | } 47 | 48 | .checkMod dt { 49 | line-height: 30px; 50 | font-weight: bold; 51 | 52 | } 53 | 54 | .rule_check { 55 | border: 1px solid #ebebeb; 56 | margin: auto; 57 | padding: 5px 15px; 58 | } 59 | 60 | .menu_parent { 61 | margin-bottom: 5px; 62 | } -------------------------------------------------------------------------------- /public/static/admin/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/images/avatar.png -------------------------------------------------------------------------------- /public/static/admin/images/login-default-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/images/login-default-bg.jpg -------------------------------------------------------------------------------- /public/static/admin/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/images/logo.png -------------------------------------------------------------------------------- /public/static/admin/js/requrest.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/js/requrest.js -------------------------------------------------------------------------------- /public/static/admin/plugins/bootstrap-number/bootstrap-number.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.bootstrapNumber=function(b){var c=a.extend({upClass:"default",downClass:"default",upText:"+",downText:"-",center:!0},b);return this.each(function(){function i(a){return isNaN(a)||f&&f>a||g&&a>g?!1:(e.focus().val(a),e.trigger("change"),!0)}var d=a(this),e=d.clone(!0,!0),f=d.attr("min"),g=d.attr("max"),h=parseInt(d.attr("step"))||1,j=a("
"),k=a("").attr("class","btn btn-"+c.downClass).click(function(){i(parseInt(e.val()||e.attr("value"))-h)}),l=a("").attr("class","btn btn-"+c.upClass).click(function(){i(parseInt(e.val()||e.attr("value"))+h)});a("").append(k).appendTo(j),e.appendTo(j),e&&c.center&&e.css("text-align","center"),a("").append(l).appendTo(j),e.prop("type","text").keydown(function(b){var c,d;-1!==a.inArray(b.keyCode,[46,8,9,27,13,110,190])||65==b.keyCode&&b.ctrlKey===!0||b.keyCode>=35&&b.keyCode<=39||((b.shiftKey||b.keyCode<48||b.keyCode>57)&&(b.keyCode<96||b.keyCode>105)&&b.preventDefault(),c=String.fromCharCode(b.which),d=parseInt(e.val()+c),(f&&f>d||g&&d>g)&&b.preventDefault())}),d.replaceWith(j)})}}(jQuery); -------------------------------------------------------------------------------- /public/static/admin/plugins/fileinput/img/loading-sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/plugins/fileinput/img/loading-sm.gif -------------------------------------------------------------------------------- /public/static/admin/plugins/fileinput/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/plugins/fileinput/img/loading.gif -------------------------------------------------------------------------------- /public/static/admin/plugins/fileinput/themes/explorer/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v5.2.7 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Krajee Explorer theme configuration for bootstrap-fileinput. Load this theme file after loading `fileinput.js`. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2021, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD-3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):e("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(e){"use strict";e.fn.fileinputThemes.explorer={layoutTemplates:{footer:'
{caption}
{size}{progress}
{indicator} {actions}
',actions:'{drag}\n
\n \n
'},previewSettings:{html:{width:"100px",height:"60px"},text:{width:"100px",height:"60px"},video:{width:"auto",height:"60px"},audio:{width:"auto",height:"60px"},flash:{width:"100%",height:"60px"},object:{width:"100%",height:"60px"},pdf:{width:"100px",height:"60px"},other:{width:"100%",height:"60px"}},frameClass:"explorer-frame"}}); -------------------------------------------------------------------------------- /public/static/admin/plugins/fileinput/themes/fa/theme.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * bootstrap-fileinput v5.2.7 3 | * http://plugins.krajee.com/file-input 4 | * 5 | * Font Awesome icon theme configuration for bootstrap-fileinput. Requires font awesome assets to be loaded. 6 | * 7 | * Author: Kartik Visweswaran 8 | * Copyright: 2014 - 2021, Kartik Visweswaran, Krajee.com 9 | * 10 | * Licensed under the BSD-3-Clause 11 | * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md 12 | */!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof module&&"object"==typeof module.exports?require("jquery"):window.jQuery)}(function(a){"use strict";a.fn.fileinputThemes.fa={fileActionSettings:{removeIcon:'',uploadIcon:'',uploadRetryIcon:'',downloadIcon:'',zoomIcon:'',dragIcon:'',indicatorNew:'',indicatorSuccess:'',indicatorError:'',indicatorLoading:'',indicatorPaused:''},layoutTemplates:{fileIcon:' '},previewZoomButtonIcons:{prev:'',next:'',toggleheader:'',fullscreen:'',borderless:'',close:''},previewFileIcon:'',browseIcon:'',removeIcon:'',cancelIcon:'',pauseIcon:'',uploadIcon:'',msgValidationErrorIcon:' '}}); -------------------------------------------------------------------------------- /public/static/admin/plugins/fontawesome-free/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/plugins/fontawesome-free/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /public/static/admin/plugins/fontawesome-free/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /public/static/admin/plugins/fontawesome-free/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yupoxiong/BearAdmin/a1a6261d549e8d7e246fcd76fe1be0c1f8c4bfe6/public/static/admin/plugins/fontawesome-free/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /public/static/admin/plugins/icheck-bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Hovhannes Bantikyan 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 | -------------------------------------------------------------------------------- /public/static/admin/plugins/jquery-validation/localization/messages_zh.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.19.3 - 1/9/2021 2 | * https://jqueryvalidation.org/ 3 | * Copyright (c) 2021 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","../jquery.validate.min"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return a.extend(a.validator.messages,{required:"这是必填字段",remote:"请修正此字段",email:"请输入有效的电子邮件地址",url:"请输入有效的网址",date:"请输入有效的日期",dateISO:"请输入有效的日期 (YYYY-MM-DD)",number:"请输入有效的数字",digits:"只能输入数字",creditcard:"请输入有效的信用卡号码",equalTo:"你的输入不相同",extension:"请输入有效的后缀",maxlength:a.validator.format("最多可以输入 {0} 个字符"),minlength:a.validator.format("最少要输入 {0} 个字符"),rangelength:a.validator.format("请输入长度在 {0} 到 {1} 之间的字符串"),range:a.validator.format("请输入范围在 {0} 到 {1} 之间的数值"),step:a.validator.format("请输入 {0} 的整数倍值"),max:a.validator.format("请输入不大于 {0} 的数值"),min:a.validator.format("请输入不小于 {0} 的数值")}),a}); -------------------------------------------------------------------------------- /public/static/admin/plugins/jquery-validation/localization/messages_zh_TW.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.19.3 - 1/9/2021 2 | * https://jqueryvalidation.org/ 3 | * Copyright (c) 2021 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","../jquery.validate.min"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return a.extend(a.validator.messages,{required:"必須填寫",remote:"請修正此欄位",email:"請輸入有效的電子郵件",url:"請輸入有效的網址",date:"請輸入有效的日期",dateISO:"請輸入有效的日期 (YYYY-MM-DD)",number:"請輸入正確的數值",digits:"只可輸入數字",creditcard:"請輸入有效的信用卡號碼",equalTo:"請重複輸入一次",extension:"請輸入有效的後綴",maxlength:a.validator.format("最多 {0} 個字"),minlength:a.validator.format("最少 {0} 個字"),rangelength:a.validator.format("請輸入長度為 {0} 至 {1} 之間的字串"),range:a.validator.format("請輸入 {0} 至 {1} 之間的數值"),step:a.validator.format("請輸入 {0} 的整數倍值"),max:a.validator.format("請輸入不大於 {0} 的數值"),min:a.validator.format("請輸入不小於 {0} 的數值")}),a}); -------------------------------------------------------------------------------- /public/static/admin/plugins/jquery-viewer/jquery-viewer.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Viewer v1.0.1 3 | * https://fengyuanchen.github.io/jquery-viewer 4 | * 5 | * Copyright 2018-present Chen Fengyuan 6 | * Released under the MIT license 7 | * 8 | * Date: 2019-12-14T09:00:02.315Z 9 | */ 10 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("jquery"),require("viewerjs")):"function"==typeof define&&define.amd?define(["jquery","viewerjs"],t):t((e=e||self).jQuery,e.Viewer)}(this,function(d,v){"use strict";if(d=d&&d.hasOwnProperty("default")?d.default:d,v=v&&v.hasOwnProperty("default")?v.default:v,d&&d.fn&&v){var e=d.fn.viewer,w="viewer";d.fn.viewer=function(o){for(var e=arguments.length,u=new Array(11){if("number"==typeof(i=e({path:"/"},t.defaults,i)).expires){var a=new Date;a.setMilliseconds(a.getMilliseconds()+864e5*i.expires),i.expires=a}i.expires=i.expires?i.expires.toUTCString():"";try{c=JSON.stringify(r),/^[\{\[]/.test(c)&&(r=c)}catch(e){}r=o.write?o.write(r,n):encodeURIComponent(r+"").replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),n=(n=(n=encodeURIComponent(n+"")).replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent)).replace(/[\(\)]/g,escape);var s="";for(var f in i)i[f]&&(s+="; "+f,!0!==i[f]&&(s+="="+i[f]));return document.cookie=n+"="+r+s}n||(c={});for(var p=document.cookie?document.cookie.split("; "):[],d=/(%[0-9A-Z]{2})+/g,u=0;u 10 | // +---------------------------------------------------------------------- 11 | use think\facade\Route; 12 | -------------------------------------------------------------------------------- /think: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | console->run(); --------------------------------------------------------------------------------