├── .gitignore
├── vue
├── README.md
├── .gitignore
├── config
│ ├── prod.env.js
│ ├── dev.env.js
│ └── index.js
├── src
│ ├── assets
│ │ ├── images
│ │ │ ├── logo.png
│ │ │ ├── logo1.png
│ │ │ ├── logo2.png
│ │ │ ├── logo3.png
│ │ │ ├── logo4.png
│ │ │ ├── logo5.png
│ │ │ ├── logout_16.png
│ │ │ ├── logout_24.png
│ │ │ └── logout_36.png
│ │ ├── fonts
│ │ │ ├── FontAwesome.otf
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ ├── fontawesome-webfont.woff
│ │ │ └── fontawesome-webfont.woff2
│ │ └── js
│ │ │ ├── form_com.js
│ │ │ ├── list_com.js
│ │ │ ├── global.js
│ │ │ └── filter.js
│ ├── vuex
│ │ ├── getters.js
│ │ ├── state.js
│ │ ├── store.js
│ │ ├── mutations.js
│ │ └── actions.js
│ ├── components
│ │ ├── base
│ │ │ ├── 404.vue
│ │ │ ├── refresh.vue
│ │ │ ├── changePwd.vue
│ │ │ └── login.vue
│ │ ├── configs
│ │ │ ├── preview.vue
│ │ │ └── add.vue
│ │ ├── common
│ │ │ ├── listStatus.vue
│ │ │ ├── pagination.vue
│ │ │ ├── leftMenu.vue
│ │ │ ├── listActions.vue
│ │ │ └── btnGroup.vue
│ │ ├── posts
│ │ │ ├── add.vue
│ │ │ ├── list.vue
│ │ │ └── edit.vue
│ │ ├── menus
│ │ │ ├── rule.vue
│ │ │ ├── list.vue
│ │ │ ├── add.vue
│ │ │ └── edit.vue
│ │ ├── groups
│ │ │ └── list.vue
│ │ ├── rules
│ │ │ ├── list.vue
│ │ │ ├── add.vue
│ │ │ └── edit.vue
│ │ ├── structures
│ │ │ ├── list.vue
│ │ │ ├── add.vue
│ │ │ └── edit.vue
│ │ └── users
│ │ │ ├── list.vue
│ │ │ └── add.vue
│ ├── App.vue
│ ├── main.js
│ └── routes.js
├── .babelrc
├── index.html
├── build
│ ├── dev-client.js
│ ├── build.js
│ ├── webpack.dev.conf.js
│ ├── check-versions.js
│ ├── utils.js
│ ├── dev-server.js
│ ├── webpack.base.conf.js
│ └── webpack.prod.conf.js
├── .eslintrc.json
└── package.json
├── hyperf
├── README.md
├── app
│ ├── Kernel
│ │ ├── Verify
│ │ │ └── assets
│ │ │ │ ├── bgs
│ │ │ │ ├── 1.jpg
│ │ │ │ ├── 2.jpg
│ │ │ │ ├── 3.jpg
│ │ │ │ ├── 4.jpg
│ │ │ │ ├── 5.jpg
│ │ │ │ ├── 6.jpg
│ │ │ │ ├── 7.jpg
│ │ │ │ └── 8.jpg
│ │ │ │ ├── ttfs
│ │ │ │ ├── 1.ttf
│ │ │ │ ├── 2.ttf
│ │ │ │ ├── 3.ttf
│ │ │ │ ├── 4.ttf
│ │ │ │ ├── 5.ttf
│ │ │ │ └── 6.ttf
│ │ │ │ └── zhttfs
│ │ │ │ └── 1.ttf
│ │ ├── Log
│ │ │ └── LoggerFactory.php
│ │ └── Http
│ │ │ ├── Response.php
│ │ │ └── Router.php
│ ├── Event
│ │ └── UserPermissionChanged.php
│ ├── Model
│ │ ├── Model.php
│ │ ├── AdminAccess.php
│ │ ├── AdminPost.php
│ │ ├── AdminStructure.php
│ │ ├── AdminGroup.php
│ │ ├── AdminRule.php
│ │ ├── SystemConfig.php
│ │ ├── AdminMenu.php
│ │ └── AdminUser.php
│ ├── Service
│ │ ├── StructureService.php
│ │ ├── GroupService.php
│ │ ├── PostService.php
│ │ ├── RuleService.php
│ │ ├── MenuService.php
│ │ └── SystemConfigService.php
│ ├── Request
│ │ ├── PostRequest.php
│ │ ├── DeletesRequest.php
│ │ ├── StructureRequest.php
│ │ ├── GroupRequest.php
│ │ ├── EnablesRequest.php
│ │ ├── LoginRequest.php
│ │ ├── ChangePwdRequest.php
│ │ ├── RuleRequest.php
│ │ ├── MenuRequest.php
│ │ ├── UserUpdateRequest.php
│ │ └── UserStoreRequest.php
│ ├── Controller
│ │ ├── SystemConfigsController.php
│ │ ├── IndexController.php
│ │ ├── AbstractController.php
│ │ ├── MenusController.php
│ │ ├── GroupsController.php
│ │ ├── StructuresController.php
│ │ ├── RulesController.php
│ │ ├── PostsController.php
│ │ ├── UsersController.php
│ │ └── BaseController.php
│ ├── Listener
│ │ ├── FetchModeListener.php
│ │ ├── DbQueryExecutedListener.php
│ │ └── FlushUserOwnRulesListener.php
│ ├── Exception
│ │ ├── BusinessException.php
│ │ └── Handler
│ │ │ ├── AppExceptionHandler.php
│ │ │ └── BusinessExceptionHandler.php
│ ├── Middleware
│ │ ├── ConfigMiddleware.php
│ │ ├── CorsMiddleware.php
│ │ └── PermissionMiddleware.php
│ └── Constants
│ │ └── ErrorCode.php
├── .gitignore
├── config
│ ├── autoload
│ │ ├── translation.php
│ │ ├── aspects.php
│ │ ├── commands.php
│ │ ├── processes.php
│ │ ├── listeners.php
│ │ ├── dependencies.php
│ │ ├── annotations.php
│ │ ├── middlewares.php
│ │ ├── exceptions.php
│ │ ├── cache.php
│ │ ├── redis.php
│ │ ├── logger.php
│ │ ├── devtool.php
│ │ ├── databases.php
│ │ └── server.php
│ ├── container.php
│ ├── config.php
│ └── routes.php
├── .phpstorm.meta.php
├── phpstan.neon
├── .env.example
├── test
│ ├── Cases
│ │ └── ExampleTest.php
│ ├── bootstrap.php
│ └── HttpTestCase.php
├── deploy.test.yml
├── phpunit.xml
├── bin
│ └── hyperf.php
├── .gitlab-ci.yml
├── Dockerfile
├── .php_cs
└── composer.json
├── .DS_Store
├── doc
└── img
│ ├── .DS_Store
│ ├── demo_auth.jpg
│ └── demo_menu.jpg
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
--------------------------------------------------------------------------------
/vue/README.md:
--------------------------------------------------------------------------------
1 | # HyperVue-vue
--------------------------------------------------------------------------------
/hyperf/README.md:
--------------------------------------------------------------------------------
1 | # HyperVue-hyperf
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/.DS_Store
--------------------------------------------------------------------------------
/vue/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
3 | yarn.lock
4 | dist
--------------------------------------------------------------------------------
/vue/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/doc/img/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/doc/img/.DS_Store
--------------------------------------------------------------------------------
/doc/img/demo_auth.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/doc/img/demo_auth.jpg
--------------------------------------------------------------------------------
/doc/img/demo_menu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/doc/img/demo_menu.jpg
--------------------------------------------------------------------------------
/vue/src/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logo.png
--------------------------------------------------------------------------------
/vue/src/assets/images/logo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logo1.png
--------------------------------------------------------------------------------
/vue/src/assets/images/logo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logo2.png
--------------------------------------------------------------------------------
/vue/src/assets/images/logo3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logo3.png
--------------------------------------------------------------------------------
/vue/src/assets/images/logo4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logo4.png
--------------------------------------------------------------------------------
/vue/src/assets/images/logo5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logo5.png
--------------------------------------------------------------------------------
/vue/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-3"],
3 | "plugins": ["transform-runtime"],
4 | "comments": false
5 | }
6 |
--------------------------------------------------------------------------------
/vue/src/assets/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/vue/src/assets/images/logout_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logout_16.png
--------------------------------------------------------------------------------
/vue/src/assets/images/logout_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logout_24.png
--------------------------------------------------------------------------------
/vue/src/assets/images/logout_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/images/logout_36.png
--------------------------------------------------------------------------------
/vue/src/vuex/getters.js:
--------------------------------------------------------------------------------
1 | const getters = {
2 | // getCount: state => state.count,
3 | }
4 |
5 | export default getters
6 |
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/1.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/2.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/3.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/4.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/5.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/6.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/7.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/bgs/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/bgs/8.jpg
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/ttfs/1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/ttfs/1.ttf
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/ttfs/2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/ttfs/2.ttf
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/ttfs/3.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/ttfs/3.ttf
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/ttfs/4.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/ttfs/4.ttf
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/ttfs/5.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/ttfs/5.ttf
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/ttfs/6.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/ttfs/6.ttf
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Verify/assets/zhttfs/1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/hyperf/app/Kernel/Verify/assets/zhttfs/1.ttf
--------------------------------------------------------------------------------
/vue/src/assets/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/vue/src/assets/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/vue/src/assets/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/vue/src/assets/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WarnerYang/HyperVue/HEAD/vue/src/assets/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/vue/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"'
6 | })
7 |
--------------------------------------------------------------------------------
/hyperf/.gitignore:
--------------------------------------------------------------------------------
1 | .buildpath
2 | .settings/
3 | .project
4 | *.patch
5 | .idea/
6 | .git/
7 | runtime/
8 | vendor/
9 | .phpintel/
10 | .env
11 | .DS_Store
12 | *.lock
13 | .phpunit*
--------------------------------------------------------------------------------
/hyperf/config/autoload/translation.php:
--------------------------------------------------------------------------------
1 | 'zh_CN',
6 | 'fallback_locale' => '',
7 | 'path' => BASE_PATH . '/storage/languages',
8 | ];
--------------------------------------------------------------------------------
/vue/src/assets/js/form_com.js:
--------------------------------------------------------------------------------
1 | const formMixin = {
2 | methods: {
3 | goback() {
4 | router.go(-1)
5 | },
6 | go(num) {
7 | router.go(num)
8 | }
9 | }
10 | }
11 |
12 | export default formMixin
13 |
--------------------------------------------------------------------------------
/vue/src/vuex/state.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | showLeftMenu: true,
3 | globalLoading: true,
4 | menus: [],
5 | rules: [],
6 | users: {},
7 | userGroups: [],
8 | organizes: []
9 | }
10 |
11 | export default state
12 |
--------------------------------------------------------------------------------
/vue/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | loading...
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/hyperf/.phpstorm.meta.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
页面未找到 404
4 |
登录
5 |
返回
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/aspects.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/vue/src/components/configs/preview.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/listeners.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ scope.row.status | status}}
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/dependencies.php:
--------------------------------------------------------------------------------
1 | App\Kernel\Log\LoggerFactory::class,
15 | ];
16 |
--------------------------------------------------------------------------------
/vue/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/hyperf/app/Event/UserPermissionChanged.php:
--------------------------------------------------------------------------------
1 | model = $model;
22 | $this->uid = $uid;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/hyperf/app/Model/Model.php:
--------------------------------------------------------------------------------
1 | [
15 | 'paths' => [
16 | BASE_PATH . '/app',
17 | ],
18 | 'ignore_annotations' => [
19 | 'mixin',
20 | ],
21 | ],
22 | ];
23 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/middlewares.php:
--------------------------------------------------------------------------------
1 | [
15 | \App\Middleware\CorsMiddleware::class,
16 | \App\Middleware\ConfigMiddleware::class,
17 | \Hyperf\Validation\Middleware\ValidationMiddleware::class,
18 | ],
19 | ];
20 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/exceptions.php:
--------------------------------------------------------------------------------
1 | [
15 | 'http' => [
16 | // App\Exception\Handler\AppExceptionHandler::class,
17 | App\Exception\Handler\BusinessExceptionHandler::class,
18 | ],
19 | ],
20 | ];
21 |
--------------------------------------------------------------------------------
/hyperf/app/Service/StructureService.php:
--------------------------------------------------------------------------------
1 | model, ['id', 'pid', 'name', 'title']);
22 | $data = $cat->getList([], 0, 'id');
23 | return $data;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/cache.php:
--------------------------------------------------------------------------------
1 | [
15 | 'driver' => Hyperf\Cache\Driver\RedisDriver::class,
16 | // 'driver' => Hyperf\Cache\Driver\FileSystemDriver::class,
17 | 'packer' => Hyperf\Utils\Packer\PhpSerializerPacker::class,
18 | 'prefix' => 'hyperVue:',
19 | ],
20 | ];
21 |
--------------------------------------------------------------------------------
/vue/src/vuex/mutations.js:
--------------------------------------------------------------------------------
1 | const mutations = {
2 | showLeftMenu(state, status) {
3 | state.showLeftMenu = status
4 | },
5 | showLoading(state, status) {
6 | state.globalLoading = status
7 | },
8 | setMenus(state, menus) {
9 | state.menus = menus
10 | },
11 | setRules(state, rules) {
12 | state.rules = rules
13 | },
14 | setUsers(state, users) {
15 | state.users = users
16 | },
17 | setUserGroups(state, userGroups) {
18 | state.userGroups = userGroups
19 | },
20 | setOrganizes(state, organizes) {
21 | state.organizes = organizes
22 | }
23 | }
24 |
25 | export default mutations
26 |
--------------------------------------------------------------------------------
/hyperf/app/Request/PostRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | ];
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/SystemConfigsController.php:
--------------------------------------------------------------------------------
1 | validated();
21 | $params = $this->request->all();
22 | $data = $this->service->createData($params);
23 | return success();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/hyperf/app/Request/DeletesRequest.php:
--------------------------------------------------------------------------------
1 | 'required|array',
26 | ];
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/hyperf/app/Request/StructureRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | ];
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Log/LoggerFactory.php:
--------------------------------------------------------------------------------
1 | get(HyperfLoggerFactory::class)->make();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/hyperf/app/Request/GroupRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | 'rules' => 'required',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/hyperf/test/Cases/ExampleTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(true);
26 | $this->assertTrue(is_array($this->get('/')));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/hyperf/app/Request/EnablesRequest.php:
--------------------------------------------------------------------------------
1 | 'required|array',
26 | 'status' => 'required|boolean',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/hyperf/app/Request/LoginRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | 'password' => 'required|between:6,12',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/vue/src/vuex/actions.js:
--------------------------------------------------------------------------------
1 | const actions = {
2 | showLeftMenu ({ commit }, status) {
3 | commit('showLeftMenu', status)
4 | },
5 | showLoading ({ commit }, status) {
6 | commit('showLoading', status)
7 | },
8 | setMenus({ commit }, menus) {
9 | commit('setMenus', menus)
10 | },
11 | setRules({ commit }, rules) {
12 | commit('setRules', rules)
13 | },
14 | setUsers({ commit }, users) {
15 | commit('setUsers', users)
16 | },
17 | setUserGroups({ commit }, userGroups) {
18 | commit('setUserGroups', userGroups)
19 | },
20 | setOrganizes({ commit }, organizes) {
21 | commit('setOrganizes', organizes)
22 | }
23 | }
24 |
25 | export default actions
26 |
--------------------------------------------------------------------------------
/hyperf/app/Service/GroupService.php:
--------------------------------------------------------------------------------
1 | model, ['id', 'pid', 'title', 'title']);
26 | $data = $cat->getList([], 0, 'id');
27 | return $data;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/hyperf/app/Request/ChangePwdRequest.php:
--------------------------------------------------------------------------------
1 | 'required|between:6,12',
26 | 'new_pwd' => 'required|between:6,12',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/hyperf/app/Request/RuleRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | 'name' => 'required',
27 | 'level' => 'required',
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/hyperf/app/Request/MenuRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | 'menu_type' => 'required',
27 | 'rule_id' => 'required',
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/IndexController.php:
--------------------------------------------------------------------------------
1 | request->input('user', 'Hyperf');
20 | $method = $this->request->getMethod();
21 |
22 | return [
23 | 'method' => $method,
24 | 'message' => "Hello {$user}.",
25 | ];
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/hyperf/deploy.test.yml:
--------------------------------------------------------------------------------
1 | version: '3.7'
2 | services:
3 | hyperf:
4 | image: $REGISTRY_URL/$PROJECT_NAME:test
5 | environment:
6 | - "APP_PROJECT=hyperf"
7 | - "APP_ENV=test"
8 | ports:
9 | - 9501:9501
10 | deploy:
11 | replicas: 1
12 | restart_policy:
13 | condition: on-failure
14 | delay: 5s
15 | max_attempts: 5
16 | update_config:
17 | parallelism: 2
18 | delay: 5s
19 | order: start-first
20 | networks:
21 | - hyperf_net
22 | configs:
23 | - source: hyperf_v1.0
24 | target: /opt/www/.env
25 | configs:
26 | hyperf_v1.0:
27 | external: true
28 | networks:
29 | hyperf_net:
30 | external: true
31 |
--------------------------------------------------------------------------------
/hyperf/app/Listener/FetchModeListener.php:
--------------------------------------------------------------------------------
1 | statement->setFetchMode(PDO::FETCH_ASSOC);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/vue/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "vue",
4 | "env": {
5 | "browser": true,
6 | "es6": true
7 | },
8 | "parserOptions": {
9 | "sourceType": "module"
10 | },
11 | "rules": {
12 | "linebreak-style": 0, // 换行风格
13 | "quotes": 0, // 引号类型
14 | "semi": 0, // 分号作为语句结尾
15 | "eqeqeq": 0, // 强制使用 '===' 和 '!==' 来做判断比较
16 | "no-unused-vars": 0, // 强制声明未使用变量
17 | "space-before-function-paren": 0, // 函数名后的空格
18 | "prefer-const": 0, // 首选const
19 | "no-undef": 0, // 不能使用未定义变量
20 | "camelcase": 0,
21 | "object-curly-spacing": 0,
22 | "indent": 0, // 缩进
23 | "eol-last": 0
24 | }
25 | }
--------------------------------------------------------------------------------
/hyperf/app/Request/UserUpdateRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
26 | 'realname' => 'required',
27 | 'groups' => 'required',
28 | 'password' => 'between:6,12'
29 | ];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/hyperf/app/Service/PostService.php:
--------------------------------------------------------------------------------
1 | model;
25 | if ($keywords) {
26 | $keywords = rtrim(ltrim($keywords));
27 | $query = $query->where('name', 'like', "%{$keywords}%");
28 | }
29 | $data = $query->get();
30 | return $data;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/hyperf/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | ./test
14 |
15 |
16 |
17 |
18 | ./app
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/hyperf/app/Request/UserStoreRequest.php:
--------------------------------------------------------------------------------
1 | 'required|unique:admin_user',
26 | 'realname' => 'required',
27 | 'groups' => 'required',
28 | 'password' => 'required|between:6,12'
29 | ];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/hyperf/bin/hyperf.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | get(\Hyperf\Contract\ApplicationInterface::class);
21 | $application->run();
22 | })();
23 |
--------------------------------------------------------------------------------
/hyperf/app/Model/AdminAccess.php:
--------------------------------------------------------------------------------
1 | 'integer', 'user_id' => 'integer', 'group_id' => 'integer'];
32 | }
--------------------------------------------------------------------------------
/hyperf/app/Exception/BusinessException.php:
--------------------------------------------------------------------------------
1 | get(Hyperf\Contract\ApplicationInterface::class);
29 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/redis.php:
--------------------------------------------------------------------------------
1 | [
15 | 'host' => env('REDIS_HOST', 'localhost'),
16 | 'auth' => env('REDIS_AUTH', null),
17 | 'port' => (int) env('REDIS_PORT', 6379),
18 | 'db' => (int) env('REDIS_DB', 0),
19 | 'pool' => [
20 | 'min_connections' => 1,
21 | 'max_connections' => 10,
22 | 'connect_timeout' => 10.0,
23 | 'wait_timeout' => 3.0,
24 | 'heartbeat' => -1,
25 | 'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60),
26 | ],
27 | ],
28 | ];
29 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/logger.php:
--------------------------------------------------------------------------------
1 | [
15 | 'handler' => [
16 | 'class' => Monolog\Handler\StreamHandler::class,
17 | 'constructor' => [
18 | 'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
19 | 'level' => Monolog\Logger::DEBUG,
20 | ],
21 | ],
22 | 'formatter' => [
23 | 'class' => Monolog\Formatter\LineFormatter::class,
24 | 'constructor' => [
25 | 'format' => null,
26 | 'dateFormat' => null,
27 | 'allowInlineLineBreaks' => true,
28 | ],
29 | ],
30 | ],
31 | ];
32 |
--------------------------------------------------------------------------------
/hyperf/config/config.php:
--------------------------------------------------------------------------------
1 | env('APP_NAME', 'skeleton'),
18 | 'app_secret' => env('APP_SECRET', 'Tn2YbxQ37PFUBMd6'),
19 | 'logged_info_cache_key' => env('LOGGED_INFO_CACHE_KEY', 'loggedInfo:'),
20 | StdoutLoggerInterface::class => [
21 | 'log_level' => [
22 | LogLevel::ALERT,
23 | LogLevel::CRITICAL,
24 | // LogLevel::DEBUG,
25 | LogLevel::EMERGENCY,
26 | LogLevel::ERROR,
27 | LogLevel::INFO,
28 | LogLevel::NOTICE,
29 | LogLevel::WARNING,
30 | ],
31 | ],
32 | ];
33 |
--------------------------------------------------------------------------------
/vue/src/assets/js/list_com.js:
--------------------------------------------------------------------------------
1 | const listMixin = {
2 | data() {
3 | return {
4 | currentPage: null, // 分页当前页
5 | keywords: '', // 关键字搜索
6 | multipleSelection: [], // 列表当前已勾选项
7 | limit: 15, // 每页数据数目
8 | dataCount: 0
9 | }
10 | },
11 | methods: {
12 | selectItem(val) {
13 | this.multipleSelection = val
14 | },
15 | getCurrentPage() {
16 | let data = this.$route.query
17 | if (data) {
18 | if (data.page) {
19 | this.currentPage = parseInt(data.page)
20 | } else {
21 | this.currentPage = 1
22 | }
23 | }
24 | },
25 | getKeywords() {
26 | let data = this.$route.query
27 | if (data) {
28 | if (data.keywords) {
29 | this.keywords = data.keywords
30 | } else {
31 | this.keywords = ''
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
38 | export default listMixin
39 |
--------------------------------------------------------------------------------
/hyperf/app/Model/AdminPost.php:
--------------------------------------------------------------------------------
1 | 'integer', 'status' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
35 | }
--------------------------------------------------------------------------------
/hyperf/app/Model/AdminStructure.php:
--------------------------------------------------------------------------------
1 | 'integer', 'pid' => 'integer', 'status' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
35 | }
--------------------------------------------------------------------------------
/hyperf/app/Controller/AbstractController.php:
--------------------------------------------------------------------------------
1 | 'integer', 'pid' => 'integer', 'status' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
37 | }
--------------------------------------------------------------------------------
/hyperf/app/Service/RuleService.php:
--------------------------------------------------------------------------------
1 | model, ['id', 'pid', 'title', 'title']);
35 | $data = $cat->getList([], 0, 'id');
36 | if ($type == 'tree') {
37 | foreach ($data as $k => $v) {
38 | $data[$k]['check'] = false;
39 | }
40 | $data = $this->tree->list_to_tree($data, 'id', 'pid', 'child', 0, true, ['pid']);
41 | }
42 | return $data;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/hyperf/app/Model/AdminRule.php:
--------------------------------------------------------------------------------
1 | 'integer', 'level' => 'integer', 'pid' => 'integer', 'status' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
37 | }
--------------------------------------------------------------------------------
/hyperf/app/Model/SystemConfig.php:
--------------------------------------------------------------------------------
1 | 'integer', 'group' => 'integer', 'need_auth' => 'integer'];
43 | }
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 WarnerYang
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 |
--------------------------------------------------------------------------------
/hyperf/app/Middleware/ConfigMiddleware.php:
--------------------------------------------------------------------------------
1 | systemConfigService->getDataList();
32 | if (is_array($data)) {
33 | foreach ($data as $key => $value) {
34 | $this->config->set($key, $value);
35 | }
36 | }
37 | return $handler->handle($request);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/hyperf/test/HttpTestCase.php:
--------------------------------------------------------------------------------
1 | client = make(Client::class);
36 | }
37 |
38 | public function __call($name, $arguments)
39 | {
40 | return $this->client->{$name}(...$arguments);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/hyperf/app/Middleware/CorsMiddleware.php:
--------------------------------------------------------------------------------
1 | withHeader('Access-Control-Allow-Origin', env('APP_ALLOW_ORIGIN', '*'))
20 | ->withHeader('Access-Control-Allow-Credentials', 'true')
21 | ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
22 | ->withHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, authKey, sessionId');
23 | Context::set(ResponseInterface::class, $response);
24 |
25 | if ($request->getMethod() == 'OPTIONS') {
26 | return $response;
27 | }
28 |
29 | return $handler->handle($request);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/hyperf/app/Model/AdminMenu.php:
--------------------------------------------------------------------------------
1 | 'integer', 'pid' => 'integer', 'menu_type' => 'integer', 'sort' => 'integer', 'status' => 'integer', 'rule_id' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
40 | }
--------------------------------------------------------------------------------
/hyperf/config/autoload/devtool.php:
--------------------------------------------------------------------------------
1 | [
15 | 'amqp' => [
16 | 'consumer' => [
17 | 'namespace' => 'App\\Amqp\\Consumer',
18 | ],
19 | 'producer' => [
20 | 'namespace' => 'App\\Amqp\\Producer',
21 | ],
22 | ],
23 | 'aspect' => [
24 | 'namespace' => 'App\\Aspect',
25 | ],
26 | 'command' => [
27 | 'namespace' => 'App\\Command',
28 | ],
29 | 'controller' => [
30 | 'namespace' => 'App\\Controller',
31 | ],
32 | 'job' => [
33 | 'namespace' => 'App\\Job',
34 | ],
35 | 'listener' => [
36 | 'namespace' => 'App\\Listener',
37 | ],
38 | 'middleware' => [
39 | 'namespace' => 'App\\Middleware',
40 | ],
41 | 'Process' => [
42 | 'namespace' => 'App\\Processes',
43 | ],
44 | ],
45 | ];
46 |
--------------------------------------------------------------------------------
/vue/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'static',
10 | assetsPublicPath: '/',
11 | productionSourceMap: true,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css']
18 | },
19 | dev: {
20 | env: require('./dev.env'),
21 | port: 8888,
22 | assetsSubDirectory: 'static',
23 | assetsPublicPath: '/',
24 | proxyTable: {},
25 | // CSS Sourcemaps off by default because relative paths are "buggy"
26 | // with this option, according to the CSS-Loader README
27 | // (https://github.com/webpack/css-loader#sourcemaps)
28 | // In our experience, they generally work as expected,
29 | // just be aware of this issue when enabling this option.
30 | cssSourceMap: false
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/vue/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | var config = require('../config')
2 | var webpack = require('webpack')
3 | var merge = require('webpack-merge')
4 | var utils = require('./utils')
5 | var baseWebpackConfig = require('./webpack.base.conf')
6 | var HtmlWebpackPlugin = require('html-webpack-plugin')
7 |
8 | // add hot-reload related code to entry chunks
9 | Object.keys(baseWebpackConfig.entry).forEach(function (name) {
10 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
11 | })
12 |
13 | module.exports = merge(baseWebpackConfig, {
14 | module: {
15 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
16 | },
17 | // eval-source-map is faster for development
18 | devtool: '#eval-source-map',
19 | plugins: [
20 | new webpack.DefinePlugin({
21 | 'process.env': config.dev.env
22 | }),
23 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
24 | new webpack.optimize.OccurenceOrderPlugin(),
25 | new webpack.HotModuleReplacementPlugin(),
26 | new webpack.NoErrorsPlugin(),
27 | // https://github.com/ampedandwired/html-webpack-plugin
28 | new HtmlWebpackPlugin({
29 | filename: 'index.html',
30 | template: 'index.html',
31 | inject: true
32 | })
33 | ]
34 | })
35 |
--------------------------------------------------------------------------------
/hyperf/app/Service/MenuService.php:
--------------------------------------------------------------------------------
1 | model, ['id', 'pid', 'title', 'title']);
35 | $data = $cat->getList([], 0, 'sort');
36 | return $data;
37 | }
38 |
39 | public function getDataById($id)
40 | {
41 | $result = $this->model
42 | ->leftJoin('admin_rule as rule', 'admin_menu.rule_id', '=', 'rule.id')
43 | ->select('admin_menu.*', 'rule.title as rule_name')
44 | ->find($id);
45 | if (!$result) {
46 | throw new BusinessException(ErrorCode::RECORD_NOT_EXIST);
47 | }
48 | return $result;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/vue/build/check-versions.js:
--------------------------------------------------------------------------------
1 | var semver = require('semver')
2 | var chalk = require('chalk')
3 | var packageConfig = require('../package.json')
4 | var exec = function (cmd) {
5 | return require('child_process')
6 | .execSync(cmd).toString().trim()
7 | }
8 |
9 | var versionRequirements = [
10 | {
11 | name: 'node',
12 | currentVersion: semver.clean(process.version),
13 | versionRequirement: packageConfig.engines.node
14 | },
15 | {
16 | name: 'npm',
17 | currentVersion: exec('npm --version'),
18 | versionRequirement: packageConfig.engines.npm
19 | }
20 | ]
21 |
22 | module.exports = function () {
23 | var warnings = []
24 | for (var i = 0; i < versionRequirements.length; i++) {
25 | var mod = versionRequirements[i]
26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
27 | warnings.push(mod.name + ': ' +
28 | chalk.red(mod.currentVersion) + ' should be ' +
29 | chalk.green(mod.versionRequirement)
30 | )
31 | }
32 | }
33 |
34 | if (warnings.length) {
35 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
36 | for (var i = 0; i < warnings.length; i++) {
37 | var warning = warnings[i]
38 | console.log(' ' + warning)
39 | }
40 | process.exit(1)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/databases.php:
--------------------------------------------------------------------------------
1 | [
15 | 'driver' => env('DB_DRIVER', 'mysql'),
16 | 'host' => env('DB_HOST', 'localhost'),
17 | 'database' => env('DB_DATABASE', 'hyperf'),
18 | 'port' => env('DB_PORT', 3306),
19 | 'username' => env('DB_USERNAME', 'root'),
20 | 'password' => env('DB_PASSWORD', ''),
21 | 'charset' => env('DB_CHARSET', 'utf8'),
22 | 'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),
23 | 'prefix' => env('DB_PREFIX', ''),
24 | 'pool' => [
25 | 'min_connections' => 1,
26 | 'max_connections' => 10,
27 | 'connect_timeout' => 10.0,
28 | 'wait_timeout' => 3.0,
29 | 'heartbeat' => -1,
30 | 'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
31 | ],
32 | 'commands' => [
33 | 'db:model' => [
34 | 'path' => 'app/Model',
35 | 'force_casts' => true,
36 | 'inheritance' => 'Model',
37 | ],
38 | ],
39 | ],
40 | ];
41 |
--------------------------------------------------------------------------------
/hyperf/app/Exception/Handler/AppExceptionHandler.php:
--------------------------------------------------------------------------------
1 | logger = $logger;
31 | }
32 |
33 | public function handle(Throwable $throwable, ResponseInterface $response)
34 | {
35 | $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
36 | $this->logger->error($throwable->getTraceAsString());
37 | return $response->withStatus(500)->withBody(new SwooleStream('Internal Server Error.'));
38 | }
39 |
40 | public function isValid(Throwable $throwable): bool
41 | {
42 | return true;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/hyperf/app/Model/AdminUser.php:
--------------------------------------------------------------------------------
1 | 'integer', 'structure_id' => 'integer', 'post_id' => 'integer', 'status' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
40 |
41 | public function groups()
42 | {
43 | return $this->belongsToMany(AdminGroup::class, 'admin_access', 'user_id', 'group_id');
44 | }
45 | }
--------------------------------------------------------------------------------
/vue/src/assets/js/global.js:
--------------------------------------------------------------------------------
1 | const commonFn = {
2 | j2s(obj) {
3 | return JSON.stringify(obj)
4 | },
5 | shallowRefresh(name, query) {
6 | router.replace({ path: '/refresh', query: { name: name, query: query } })
7 | },
8 | closeGlobalLoading() {
9 | setTimeout(() => {
10 | store.dispatch('showLoading', false)
11 | })
12 | },
13 | openGlobalLoading() {
14 | setTimeout(() => {
15 | store.dispatch('showLoading', true)
16 | })
17 | },
18 | cloneJson(obj) {
19 | return JSON.parse(JSON.stringify(obj))
20 | },
21 | toastMsg(type, msg) {
22 | switch (type) {
23 | case 'normal':
24 | bus.$message(msg)
25 | break
26 | case 'success':
27 | bus.$message({
28 | message: msg,
29 | type: 'success'
30 | })
31 | break
32 | case 'warning':
33 | bus.$message({
34 | message: msg,
35 | type: 'warning'
36 | })
37 | break
38 | case 'error':
39 | bus.$message.error(msg)
40 | break
41 | }
42 | },
43 | clearVuex(cate) {
44 | store.dispatch(cate, [])
45 | },
46 | getHasRule(val) {
47 | const userInfo = Lockr.get('userInfo')
48 | if (userInfo.id == 1) {
49 | return true
50 | } else {
51 | const authList = Lockr.get('authList')
52 | return _.includes(authList, val)
53 | }
54 | }
55 | }
56 |
57 | export default commonFn
58 |
--------------------------------------------------------------------------------
/hyperf/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | # usermod -aG docker gitlab-runner
2 |
3 | stages:
4 | - build
5 | - deploy
6 |
7 | variables:
8 | PROJECT_NAME: hyperf
9 | REGISTRY_URL: registry-docker.org
10 |
11 | build_test_docker:
12 | stage: build
13 | before_script:
14 | # - git submodule sync --recursive
15 | # - git submodule update --init --recursive
16 | script:
17 | - docker build . -t $PROJECT_NAME
18 | - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:test
19 | - docker push $REGISTRY_URL/$PROJECT_NAME:test
20 | only:
21 | - test
22 | tags:
23 | - builder
24 |
25 | deploy_test_docker:
26 | stage: deploy
27 | script:
28 | - docker stack deploy -c deploy.test.yml --with-registry-auth $PROJECT_NAME
29 | only:
30 | - test
31 | tags:
32 | - test
33 |
34 | build_docker:
35 | stage: build
36 | before_script:
37 | # - git submodule sync --recursive
38 | # - git submodule update --init --recursive
39 | script:
40 | - docker build . -t $PROJECT_NAME
41 | - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME
42 | - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:latest
43 | - docker push $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME
44 | - docker push $REGISTRY_URL/$PROJECT_NAME:latest
45 | only:
46 | - tags
47 | tags:
48 | - builder
49 |
50 | deploy_docker:
51 | stage: deploy
52 | script:
53 | - echo SUCCESS
54 | only:
55 | - tags
56 | tags:
57 | - builder
58 |
--------------------------------------------------------------------------------
/vue/src/components/common/pagination.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
59 |
--------------------------------------------------------------------------------
/hyperf/app/Service/SystemConfigService.php:
--------------------------------------------------------------------------------
1 | model->get();
31 | if ($systemConfig) {
32 | foreach ($systemConfig as $config) {
33 | $data[$config['key']] = $config['value'];
34 | }
35 | }
36 |
37 | return $data;
38 | }
39 |
40 | /**
41 | * @CacheEvict(prefix="systemConfig", value="")
42 | */
43 | public function createData($params)
44 | {
45 | Db::beginTransaction();
46 | try {
47 | foreach ($params as $key => $value) {
48 | $this->model->where('key', $key)->update(['value' => $value]);
49 | }
50 | Db::commit();
51 | return true;
52 | } catch (\Throwable $th) {
53 | Db::rollback();
54 | throw new BusinessException(ErrorCode::UPDATE_ERROR, $th->getMessage());
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/hyperf/config/autoload/server.php:
--------------------------------------------------------------------------------
1 | SWOOLE_PROCESS,
18 | 'servers' => [
19 | [
20 | 'name' => 'http',
21 | 'type' => Server::SERVER_HTTP,
22 | 'host' => '0.0.0.0',
23 | 'port' => 9501,
24 | 'sock_type' => SWOOLE_SOCK_TCP,
25 | 'callbacks' => [
26 | SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
27 | ],
28 | ],
29 | ],
30 | 'settings' => [
31 | 'enable_coroutine' => true,
32 | 'worker_num' => swoole_cpu_num(),
33 | 'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
34 | 'open_tcp_nodelay' => true,
35 | 'max_coroutine' => 100000,
36 | 'open_http2_protocol' => true,
37 | 'max_request' => 100000,
38 | 'socket_buffer_size' => 2 * 1024 * 1024,
39 | ],
40 | 'callbacks' => [
41 | SwooleEvent::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'],
42 | SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
43 | SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
44 | ],
45 | ];
46 |
--------------------------------------------------------------------------------
/hyperf/app/Listener/DbQueryExecutedListener.php:
--------------------------------------------------------------------------------
1 | logger = $container->get(LoggerFactory::class)->get('sql');
37 | }
38 |
39 | public function listen(): array
40 | {
41 | return [
42 | QueryExecuted::class,
43 | ];
44 | }
45 |
46 | /**
47 | * @param QueryExecuted $event
48 | */
49 | public function process(object $event)
50 | {
51 | if ($event instanceof QueryExecuted) {
52 | $sql = $event->sql;
53 | if (! Arr::isAssoc($event->bindings)) {
54 | foreach ($event->bindings as $key => $value) {
55 | $sql = Str::replaceFirst('?', "'{$value}'", $sql);
56 | }
57 | }
58 |
59 | $this->logger->info(sprintf('[%s] %s', $event->time, $sql));
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/hyperf/app/Listener/FlushUserOwnRulesListener.php:
--------------------------------------------------------------------------------
1 | uid;
40 | $model = $event->model;
41 |
42 | // 变更用户信息 清理相应用户拥有的权限列表缓存
43 | if ($model instanceof AdminUser) {
44 | $uid = $event->uid;
45 | if (!is_array($uid)) $uid = [$uid];
46 | }
47 |
48 | // 变更用户组或者权限 清理所有用户拥有的权限列表缓存
49 | if ($model instanceof AdminGroup || $model instanceof AdminRule) {
50 | $uid = $userService->getOrSetUserOwnRulesIds();
51 | }
52 |
53 | foreach ($uid as $id) {
54 | $eventDispatcher->dispatch(new DeleteListenerEvent('getUserOwnRulesUpdate', [$id]));
55 | }
56 |
57 | return true;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/vue/src/main.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import Vue from 'vue'
3 | import App from './App'
4 | import axios from 'axios'
5 | import Lockr from 'lockr'
6 | import Cookies from 'js-cookie'
7 | import _ from 'lodash'
8 | import moment from 'moment'
9 | import ElementUI from 'element-ui'
10 | import 'element-ui/lib/theme-chalk/index.css'
11 | import routes from './routes'
12 | import VueRouter from 'vue-router'
13 | import store from './vuex/store'
14 | import filter from './assets/js/filter'
15 | import _g from './assets/js/global'
16 | import NProgress from 'nprogress'
17 | import 'nprogress/nprogress.css'
18 | import 'assets/css/global.css'
19 | import 'assets/css/base.css'
20 |
21 | axios.defaults.baseURL = HOST
22 | axios.defaults.timeout = 1000 * 15
23 | axios.defaults.headers.authKey = Lockr.get('authKey') || ''
24 | axios.defaults.headers.sessionId = Lockr.get('sessionId') || ''
25 | axios.defaults.headers['Content-Type'] = 'application/json'
26 |
27 | const router = new VueRouter({
28 | mode: 'hash',
29 | base: __dirname,
30 | routes
31 | })
32 |
33 | router.beforeEach((to, from, next) => {
34 | store.dispatch('showLoading', true)
35 | NProgress.start()
36 | next()
37 | })
38 |
39 | router.afterEach(transition => {
40 | NProgress.done()
41 | })
42 |
43 | Vue.use(ElementUI)
44 | Vue.use(VueRouter)
45 |
46 | window.router = router
47 | window.store = store
48 | window.HOST = HOST
49 | window.axios = axios
50 | window._ = _
51 | window.moment = moment
52 | window.Lockr = Lockr
53 | window.Cookies = Cookies
54 | window._g = _g
55 | window.pageSize = 15
56 |
57 | const bus = new Vue()
58 | window.bus = bus
59 |
60 | new Vue({
61 | el: '#app',
62 | template: '',
63 | filters: filter,
64 | router,
65 | store,
66 | components: { App }
67 | // render: h => h(Login)
68 | }).$mount('#app')
69 |
--------------------------------------------------------------------------------
/hyperf/Dockerfile:
--------------------------------------------------------------------------------
1 | # Default Dockerfile
2 | #
3 | # @link https://www.hyperf.io
4 | # @document https://doc.hyperf.io
5 | # @contact group@hyperf.io
6 | # @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
7 |
8 | FROM hyperf/hyperf:7.2-alpine-cli
9 | LABEL maintainer="Hyperf Developers " version="1.0" license="MIT"
10 |
11 | ##
12 | # ---------- env settings ----------
13 | ##
14 | # --build-arg timezone=Asia/Shanghai
15 | ARG timezone
16 |
17 | ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
18 | COMPOSER_VERSION=1.8.6 \
19 | APP_ENV=prod
20 |
21 | # update
22 | RUN set -ex \
23 | && apk update \
24 | # install composer
25 | && cd /tmp \
26 | && wget https://github.com/composer/composer/releases/download/${COMPOSER_VERSION}/composer.phar \
27 | && chmod u+x composer.phar \
28 | && mv composer.phar /usr/local/bin/composer \
29 | # show php version and extensions
30 | && php -v \
31 | && php -m \
32 | # ---------- some config ----------
33 | && cd /etc/php7 \
34 | # - config PHP
35 | && { \
36 | echo "upload_max_filesize=100M"; \
37 | echo "post_max_size=108M"; \
38 | echo "memory_limit=1024M"; \
39 | echo "date.timezone=${TIMEZONE}"; \
40 | } | tee conf.d/99-overrides.ini \
41 | # - config timezone
42 | && ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
43 | && echo "${TIMEZONE}" > /etc/timezone \
44 | # ---------- clear works ----------
45 | && rm -rf /var/cache/apk/* /tmp/* /usr/share/man \
46 | && echo -e "\033[42;37m Build Completed :).\033[0m\n"
47 |
48 | COPY . /opt/www
49 |
50 | WORKDIR /opt/www
51 |
52 | RUN composer install --no-dev \
53 | && composer dump-autoload -o \
54 | && php /opt/www/bin/hyperf.php di:init-proxy
55 |
56 | EXPOSE 9501
57 |
58 | ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]
59 |
--------------------------------------------------------------------------------
/vue/src/components/common/leftMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/vue/src/components/posts/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 | 提交
18 | 返回
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/vue/src/components/menus/rule.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 已绑定
16 | 绑定
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/MenusController.php:
--------------------------------------------------------------------------------
1 | service->getDataList();
24 | return success($data);
25 | }
26 |
27 | public function show($id)
28 | {
29 | $data = $this->service->getDataById((int) $id);
30 | return success($data);
31 | }
32 |
33 | public function store(MenuRequest $request)
34 | {
35 | $validated = $request->validated();
36 | $params = $this->request->all();
37 | $data = $this->service->createData($params);
38 | return success($data);
39 | }
40 |
41 | public function update($id, MenuRequest $request)
42 | {
43 | $validated = $request->validated();
44 | $params = $this->request->all();
45 | $data = $this->service->updateDataById($params, (int) $id);
46 | return success($data);
47 | }
48 |
49 | public function destroy($id)
50 | {
51 | $data = $this->service->delDataById((int) $id);
52 | return success($data);
53 | }
54 |
55 | public function deletes(DeletesRequest $request)
56 | {
57 | $validated = $request->validated();
58 | $ids = $this->request->input('ids');
59 | $data = $this->service->delDatas($ids);
60 | return success($data);
61 | }
62 |
63 | public function enables(EnablesRequest $request)
64 | {
65 | $validated = $request->validated();
66 | $ids = $this->request->input('ids');
67 | $status = $this->request->input('status');
68 | $data = $this->service->enableDatas($ids, $status);
69 | return success($data);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/GroupsController.php:
--------------------------------------------------------------------------------
1 | service->getDataList();
24 | return success($data);
25 | }
26 |
27 | public function show($id)
28 | {
29 | $data = $this->service->getDataById((int) $id);
30 | return success($data);
31 | }
32 |
33 | public function store(GroupRequest $request)
34 | {
35 | $validated = $request->validated();
36 | $params = $this->request->all();
37 | $data = $this->service->createData($params);
38 | return success($data);
39 | }
40 |
41 | public function update($id, GroupRequest $request)
42 | {
43 | $validated = $request->validated();
44 | $params = $this->request->all();
45 | $data = $this->service->updateDataById($params, (int) $id);
46 | return success($data);
47 | }
48 |
49 | public function destroy($id)
50 | {
51 | $data = $this->service->delDataById((int) $id);
52 | return success($data);
53 | }
54 |
55 | public function deletes(DeletesRequest $request)
56 | {
57 | $validated = $request->validated();
58 | $ids = $this->request->input('ids');
59 | $data = $this->service->delDatas($ids);
60 | return success($data);
61 | }
62 |
63 | public function enables(EnablesRequest $request)
64 | {
65 | $validated = $request->validated();
66 | $ids = $this->request->input('ids');
67 | $status = $this->request->input('status');
68 | $data = $this->service->enableDatas($ids, $status);
69 | return success($data);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Http/Response.php:
--------------------------------------------------------------------------------
1 | container = $container;
36 | $this->response = $container->get(ResponseInterface::class);
37 | }
38 |
39 | public function success($data = [])
40 | {
41 | return $this->response->json([
42 | 'code' => 200,
43 | 'data' => $data,
44 | ]);
45 | }
46 |
47 | public function fail($code, $message = '')
48 | {
49 | return $this->response->json([
50 | 'code' => $code,
51 | 'message' => $message,
52 | ]);
53 | }
54 |
55 | public function redirect($url, $status = 302)
56 | {
57 | return $this->response()
58 | ->withAddedHeader('Location', (string) $url)
59 | ->withStatus($status);
60 | }
61 |
62 | public function cookie(Cookie $cookie)
63 | {
64 | $response = $this->response()->withCookie($cookie);
65 | Context::set(PsrResponseInterface::class, $response);
66 | return $this;
67 | }
68 |
69 | /**
70 | * @return \Hyperf\HttpMessage\Server\Response
71 | */
72 | public function response()
73 | {
74 | return Context::get(PsrResponseInterface::class);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/StructuresController.php:
--------------------------------------------------------------------------------
1 | service->getDataList();
24 | return success($data);
25 | }
26 |
27 | public function show($id)
28 | {
29 | $data = $this->service->getDataById((int) $id);
30 | return success($data);
31 | }
32 |
33 | public function store(StructureRequest $request)
34 | {
35 | $validated = $request->validated();
36 | $params = $this->request->all();
37 | $data = $this->service->createData($params);
38 | return success($data);
39 | }
40 |
41 | public function update($id, StructureRequest $request)
42 | {
43 | $validated = $request->validated();
44 | $params = $this->request->all();
45 | $data = $this->service->updateDataById($params, (int) $id);
46 | return success($data);
47 | }
48 |
49 | public function destroy($id)
50 | {
51 | $data = $this->service->delDataById((int) $id);
52 | return success($data);
53 | }
54 |
55 | public function deletes(DeletesRequest $request)
56 | {
57 | $validated = $request->validated();
58 | $ids = $this->request->input('ids');
59 | $data = $this->service->delDatas($ids);
60 | return success($data);
61 | }
62 |
63 | public function enables(EnablesRequest $request)
64 | {
65 | $validated = $request->validated();
66 | $ids = $this->request->input('ids');
67 | $status = $this->request->input('status');
68 | $data = $this->service->enableDatas($ids, $status);
69 | return success($data);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/RulesController.php:
--------------------------------------------------------------------------------
1 | request->input('type');
24 | $data = $this->service->getDataList($type);
25 | return success($data);
26 | }
27 |
28 | public function show($id)
29 | {
30 | $data = $this->service->getDataById((int) $id);
31 | return success($data);
32 | }
33 |
34 | public function store(RuleRequest $request)
35 | {
36 | $validated = $request->validated();
37 | $params = $this->request->all();
38 | $data = $this->service->createData($params);
39 | return success($data);
40 | }
41 |
42 | public function update($id, RuleRequest $request)
43 | {
44 | $validated = $request->validated();
45 | $params = $this->request->all();
46 | $data = $this->service->updateDataById($params, (int) $id);
47 | return success($data);
48 | }
49 |
50 | public function destroy($id)
51 | {
52 | $data = $this->service->delDataById((int) $id);
53 | return success($data);
54 | }
55 |
56 | public function deletes(DeletesRequest $request)
57 | {
58 | $validated = $request->validated();
59 | $ids = $this->request->input('ids');
60 | $data = $this->service->delDatas($ids);
61 | return success($data);
62 | }
63 |
64 | public function enables(EnablesRequest $request)
65 | {
66 | $validated = $request->validated();
67 | $ids = $this->request->input('ids');
68 | $status = $this->request->input('status');
69 | $data = $this->service->enableDatas($ids, $status);
70 | return success($data);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/PostsController.php:
--------------------------------------------------------------------------------
1 | request->input('keywords');
24 | $data = $this->service->getDataList($keywords);
25 | return success($data);
26 | }
27 |
28 | public function show($id)
29 | {
30 | $data = $this->service->getDataById((int) $id);
31 | return success($data);
32 | }
33 |
34 | public function store(PostRequest $request)
35 | {
36 | $validated = $request->validated();
37 | $params = $this->request->all();
38 | $data = $this->service->createData($params);
39 | return success($data);
40 | }
41 |
42 | public function update($id, PostRequest $request)
43 | {
44 | $validated = $request->validated();
45 | $params = $this->request->all();
46 | $data = $this->service->updateDataById($params, (int) $id);
47 | return success($data);
48 | }
49 |
50 | public function destroy($id)
51 | {
52 | $data = $this->service->delDataById((int) $id);
53 | return success($data);
54 | }
55 |
56 | public function deletes(DeletesRequest $request)
57 | {
58 | $validated = $request->validated();
59 | $ids = $this->request->input('ids');
60 | $data = $this->service->delDatas($ids);
61 | return success($data);
62 | }
63 |
64 | public function enables(EnablesRequest $request)
65 | {
66 | $validated = $request->validated();
67 | $ids = $this->request->input('ids');
68 | $status = $this->request->input('status');
69 | $data = $this->service->enableDatas($ids, $status);
70 | return success($data);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/vue/src/components/posts/list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 添加岗位
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/vue/src/components/groups/list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 添加用户组
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/vue/src/components/rules/list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 添加权限
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/hyperf/app/Exception/Handler/BusinessExceptionHandler.php:
--------------------------------------------------------------------------------
1 | container = $container;
45 | $this->response = $container->get(Response::class);
46 | $this->logger = $container->get(StdoutLoggerInterface::class);
47 | }
48 |
49 | public function handle(Throwable $throwable, ResponseInterface $response)
50 | {
51 | if ($throwable instanceof BusinessException) {
52 | $this->logger->warning(format_throwable($throwable));
53 | return $this->response->fail($throwable->getCode(), $throwable->getMessage());
54 | }
55 |
56 | if ($throwable instanceof ValidationException) {
57 | $message = $throwable->validator->errors()->first();
58 | return $this->response->fail(ErrorCode::PARAMS_INVALID, $message);
59 | }
60 |
61 | $this->logger->error(format_throwable($throwable));
62 | return $this->response->fail(ErrorCode::SERVER_ERROR, 'Server Error');
63 | }
64 |
65 | public function isValid(Throwable $throwable): bool
66 | {
67 | return true;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/vue/src/components/structures/list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 添加部门
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/vue/build/utils.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
4 |
5 | exports.assetsPath = function (_path) {
6 | var assetsSubDirectory = process.env.NODE_ENV === 'production'
7 | ? config.build.assetsSubDirectory
8 | : config.dev.assetsSubDirectory
9 | return path.posix.join(assetsSubDirectory, _path)
10 | }
11 |
12 | exports.cssLoaders = function (options) {
13 | options = options || {}
14 | // generate loader string to be used with extract text plugin
15 | function generateLoaders (loaders) {
16 | var sourceLoader = loaders.map(function (loader) {
17 | var extraParamChar
18 | if (/\?/.test(loader)) {
19 | loader = loader.replace(/\?/, '-loader?')
20 | extraParamChar = '&'
21 | } else {
22 | loader = loader + '-loader'
23 | extraParamChar = '?'
24 | }
25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
26 | }).join('!')
27 |
28 | // Extract CSS when that option is specified
29 | // (which is the case during production build)
30 | if (options.extract) {
31 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
32 | } else {
33 | return ['vue-style-loader', sourceLoader].join('!')
34 | }
35 | }
36 |
37 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
38 | return {
39 | css: generateLoaders(['css']),
40 | postcss: generateLoaders(['css']),
41 | less: generateLoaders(['css', 'less']),
42 | sass: generateLoaders(['css', 'sass?indentedSyntax']),
43 | scss: generateLoaders(['css', 'sass']),
44 | stylus: generateLoaders(['css', 'stylus']),
45 | styl: generateLoaders(['css', 'stylus']),
46 | // 额外添加
47 | // js: 'babel!eslint'
48 | }
49 | }
50 |
51 | // Generate loaders for standalone style files (outside of .vue)
52 | exports.styleLoaders = function (options) {
53 | var output = []
54 | var loaders = exports.cssLoaders(options)
55 | for (var extension in loaders) {
56 | var loader = loaders[extension]
57 | output.push({
58 | test: new RegExp('\\.' + extension + '$'),
59 | loader: loader
60 | })
61 | }
62 | return output
63 | }
64 |
--------------------------------------------------------------------------------
/vue/build/dev-server.js:
--------------------------------------------------------------------------------
1 | require('./check-versions')()
2 | var config = require('../config')
3 | if (!process.env.NODE_ENV) process.env.NODE_ENV = config.dev.env
4 | var path = require('path')
5 | var express = require('express')
6 | var webpack = require('webpack')
7 | var opn = require('opn')
8 | var proxyMiddleware = require('http-proxy-middleware')
9 | var webpackConfig = require('./webpack.dev.conf')
10 |
11 | // default port where dev server listens for incoming traffic
12 | var port = process.env.PORT || config.dev.port
13 | // Define HTTP proxies to your custom API backend
14 | // https://github.com/chimurai/http-proxy-middleware
15 | var proxyTable = config.dev.proxyTable
16 |
17 | var app = express()
18 | var compiler = webpack(webpackConfig)
19 |
20 | var devMiddleware = require('webpack-dev-middleware')(compiler, {
21 | publicPath: webpackConfig.output.publicPath,
22 | stats: {
23 | colors: true,
24 | chunks: false
25 | }
26 | })
27 |
28 | var hotMiddleware = require('webpack-hot-middleware')(compiler)
29 | // force page reload when html-webpack-plugin template changes
30 | compiler.plugin('compilation', function (compilation) {
31 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
32 | hotMiddleware.publish({ action: 'reload' })
33 | cb()
34 | })
35 | })
36 |
37 | // proxy api requests
38 | Object.keys(proxyTable).forEach(function (context) {
39 | var options = proxyTable[context]
40 | if (typeof options === 'string') {
41 | options = { target: options }
42 | }
43 | app.use(proxyMiddleware(context, options))
44 | })
45 |
46 | // handle fallback for HTML5 history API
47 | app.use(require('connect-history-api-fallback')())
48 |
49 | // serve webpack bundle output
50 | app.use(devMiddleware)
51 |
52 | // enable hot-reload and state-preserving
53 | // compilation error display
54 | app.use(hotMiddleware)
55 |
56 | // serve pure static assets
57 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
58 | app.use(staticPath, express.static('./static'))
59 |
60 | module.exports = app.listen(port, function (err) {
61 | if (err) {
62 | console.log(err)
63 | return
64 | }
65 | var uri = 'http://localhost:' + port
66 | console.log('Listening at ' + uri + '\n')
67 | opn(uri)
68 | })
69 |
--------------------------------------------------------------------------------
/hyperf/app/Constants/ErrorCode.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | 编辑
10 |
11 | 删除
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/vue/src/components/structures/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 提交
14 | 返回
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/UsersController.php:
--------------------------------------------------------------------------------
1 | request->input('keywords');
25 | $page = $this->request->input('page', 1);
26 | $limit = $this->request->input('limit', $this->limit);
27 | $data = $this->service->getDataList($keywords, (int) $page, (int) $limit);
28 | return success($data);
29 | }
30 |
31 | public function show($id)
32 | {
33 | $data = $this->service->getDataById((int) $id);
34 | return success($data);
35 | }
36 |
37 | public function store(UserStoreRequest $request)
38 | {
39 | $validated = $request->validated();
40 | $params = $this->request->all();
41 | $data = $this->service->createData($params);
42 | return success($data);
43 | }
44 |
45 | public function update($id, UserUpdateRequest $request)
46 | {
47 | $validated = $request->validated();
48 | $params = $this->request->all();
49 | $data = $this->service->updateDataById($params, (int) $id);
50 | return success($data);
51 | }
52 |
53 | public function destroy($id)
54 | {
55 | $data = $this->service->delDataById((int) $id);
56 | return success($data);
57 | }
58 |
59 | public function deletes(DeletesRequest $request)
60 | {
61 | $validated = $request->validated();
62 | $ids = $this->request->input('ids');
63 | $data = $this->service->delDatas($ids);
64 | return success($data);
65 | }
66 |
67 | public function enables(EnablesRequest $request)
68 | {
69 | $validated = $request->validated();
70 | $ids = $this->request->input('ids');
71 | $status = $this->request->input('status');
72 | $data = $this->service->enableDatas($ids, $status);
73 | return success($data);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hyper_vue",
3 | "version": "1.0.0",
4 | "description": "",
5 | "scripts": {
6 | "dev": "node build/dev-server.js",
7 | "build": "node build/build.js"
8 | },
9 | "dependencies": {
10 | "axios": "^0.19.0",
11 | "element-ui": "^2.12.0",
12 | "font-awesome": "^4.7.0",
13 | "js-cookie": "^2.2.1",
14 | "lockr": "^0.8.4",
15 | "lodash": "^4.17.15",
16 | "moment": "^2.17.1",
17 | "nprogress": "^0.2.0",
18 | "query-string": "^4.3.4",
19 | "vee-validate": "^2.2.15",
20 | "vue": "^2.0.7",
21 | "vuex": "^2.0.0-rc.6"
22 | },
23 | "devDependencies": {
24 | "autoprefixer": "^6.4.0",
25 | "babel-cli": "^6.18.0",
26 | "babel-core": "^6.0.0",
27 | "babel-eslint": "^7.1.1",
28 | "babel-loader": "^6.2.8",
29 | "babel-plugin-transform-runtime": "^6.0.0",
30 | "babel-polyfill": "^6.20.0",
31 | "babel-preset-es2015": "^6.0.0",
32 | "babel-preset-stage-3": "^6.17.0",
33 | "babel-register": "^6.0.0",
34 | "babel-runtime": "^6.26.0",
35 | "chalk": "^1.1.3",
36 | "connect-history-api-fallback": "^1.1.0",
37 | "css-loader": "^0.26.0",
38 | "eslint": "^3.12.2",
39 | "eslint-config-vue": "^2.0.1",
40 | "eslint-loader": "^1.6.1",
41 | "eslint-plugin-vue": "^1.0.0",
42 | "eventsource-polyfill": "^0.9.6",
43 | "express": "^4.13.3",
44 | "extract-text-webpack-plugin": "^1.0.1",
45 | "file-loader": "^0.9.0",
46 | "function-bind": "^1.0.2",
47 | "html-webpack-plugin": "^2.8.1",
48 | "http-proxy-middleware": "^0.17.2",
49 | "json-loader": "^0.5.4",
50 | "opn": "^4.0.2",
51 | "ora": "^0.3.0",
52 | "semver": "^5.7.1",
53 | "shelljs": "^0.7.4",
54 | "url-loader": "^0.5.7",
55 | "vue-loader": "^9.9.5",
56 | "vue-router": "^2.0.3",
57 | "vue-style-loader": "^1.0.0",
58 | "webpack": "^1.13.2",
59 | "webpack-dev-middleware": "^1.8.3",
60 | "webpack-hot-middleware": "^2.12.2",
61 | "webpack-merge": "^0.17.0"
62 | },
63 | "engines": {
64 | "node": ">= 4.0.0",
65 | "npm": ">= 3.0.0"
66 | },
67 | "repository": {
68 | "type": "git",
69 | "url": "https://github.com/WarnerYang/HyperVue/vue"
70 | },
71 | "keywords": [
72 | "backoffice",
73 | "hyperf",
74 | "vue"
75 | ],
76 | "author": "https://github.com/WarnerYang",
77 | "license": "MIT"
78 | }
--------------------------------------------------------------------------------
/vue/src/components/menus/list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 添加菜单
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | {{scope.row.menu_type | menuType}}
18 |
19 |
20 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/vue/src/components/posts/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 | 提交
18 | 返回
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/hyperf/app/Controller/BaseController.php:
--------------------------------------------------------------------------------
1 | systemConfigService->getDataList();
30 | return success($data);
31 | }
32 |
33 | public function login(LoginRequest $request)
34 | {
35 | $validated = $request->validated();
36 | $username = $this->request->input('username');
37 | $password = $this->request->input('password');
38 | $verifyCode = $this->request->input('verifyCode');
39 | $isRemember = $this->request->input('isRemember', 0);
40 | $data = $this->userService->login($username, $password, $verifyCode, $isRemember);
41 | return success($data);
42 | }
43 |
44 | public function relogin()
45 | {
46 | $rememberKey = $this->request->input('rememberKey');
47 | $decrypt = decrypt($rememberKey);
48 | $username = $decrypt['username'];
49 | $password = $decrypt['password'];
50 | $data = $this->userService->login($username, $password, '', true, true);
51 | return success($data);
52 | }
53 |
54 | public function logout()
55 | {
56 | $authkey = $this->request->header('authkey');
57 | $data = $this->userService->removeLoggedInfo($authkey);
58 | return success();
59 | }
60 |
61 | public function changePwd(ChangePwdRequest $request)
62 | {
63 | $validated = $request->validated();
64 | $oldPwd = $this->request->input('old_pwd');
65 | $newPwd = $this->request->input('new_pwd');
66 | $authKey = $this->request->header('authKey');
67 | $data = $this->userService->changePwd($authKey, $oldPwd, $newPwd);
68 | return success($data);
69 | }
70 |
71 | public function getVerify()
72 | {
73 | // $captcha = new HonrayVerify(config('captcha'));
74 | // return $captcha->entry();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/vue/src/components/base/changePwd.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 | 提交
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/vue/src/components/structures/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 | 提交
20 | 返回
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/hyperf/.php_cs:
--------------------------------------------------------------------------------
1 | setRiskyAllowed(true)
14 | ->setRules([
15 | '@PSR2' => true,
16 | '@Symfony' => true,
17 | '@DoctrineAnnotation' => true,
18 | '@PhpCsFixer' => true,
19 | 'header_comment' => [
20 | 'commentType' => 'PHPDoc',
21 | 'header' => $header,
22 | 'separate' => 'none',
23 | 'location' => 'after_declare_strict',
24 | ],
25 | 'array_syntax' => [
26 | 'syntax' => 'short'
27 | ],
28 | 'list_syntax' => [
29 | 'syntax' => 'short'
30 | ],
31 | 'concat_space' => [
32 | 'spacing' => 'one'
33 | ],
34 | 'blank_line_before_statement' => [
35 | 'statements' => [
36 | 'declare',
37 | ],
38 | ],
39 | 'general_phpdoc_annotation_remove' => [
40 | 'annotations' => [
41 | 'author'
42 | ],
43 | ],
44 | 'ordered_imports' => [
45 | 'imports_order' => [
46 | 'class', 'function', 'const',
47 | ],
48 | 'sort_algorithm' => 'alpha',
49 | ],
50 | 'single_line_comment_style' => [
51 | 'comment_types' => [
52 | ],
53 | ],
54 | 'yoda_style' => [
55 | 'always_move_variable' => false,
56 | 'equal' => false,
57 | 'identical' => false,
58 | ],
59 | 'phpdoc_align' => [
60 | 'align' => 'left',
61 | ],
62 | 'multiline_whitespace_before_semicolons' => [
63 | 'strategy' => 'no_multi_line',
64 | ],
65 | 'class_attributes_separation' => true,
66 | 'combine_consecutive_unsets' => true,
67 | 'declare_strict_types' => true,
68 | 'linebreak_after_opening_tag' => true,
69 | 'lowercase_constants' => true,
70 | 'lowercase_static_reference' => true,
71 | 'no_useless_else' => true,
72 | 'no_unused_imports' => true,
73 | 'not_operator_with_successor_space' => true,
74 | 'not_operator_with_space' => false,
75 | 'ordered_class_elements' => true,
76 | 'php_unit_strict' => false,
77 | 'phpdoc_separation' => false,
78 | 'single_quote' => true,
79 | 'standardize_not_equals' => true,
80 | 'multiline_comment_opening_closing' => true,
81 | ])
82 | ->setFinder(
83 | PhpCsFixer\Finder::create()
84 | ->exclude('public')
85 | ->exclude('runtime')
86 | ->exclude('vendor')
87 | ->in(__DIR__)
88 | )
89 | ->setUsingCache(false);
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HyperVue
2 | 🚀 基于 Hyperf + Vue + ElementUI 前后端分离的通用型管理后台
3 |
4 | - [hyperf 1.1](https://github.com/hyperf/hyperf)
5 | - [vue 2.0](https://github.com/vuejs/vue)
6 | - [element-ui 2.12](https://github.com/ElemeFE/element)
7 |
8 | ## 预览
9 | 
10 | 
11 |
12 | ## 如何使用
13 | 获取源码
14 | ```
15 | git clone https://github.com/WarnerYang/HyperVue.git
16 | ```
17 |
18 | #### hyperf 部署
19 |
20 | ```
21 | # 下载并运行 hyperf/hyperf 镜像,并将镜像内的项目目录绑定到宿主机的hyperVue下的hyperf目录(windows用powershell)
22 | # 我的目录是 /Users/yhq/wwwroot/learn/HyperVue/hyperf
23 | cd hyperf
24 |
25 | docker run --name hyperVue-hyperf -v /Users/yhq/wwwroot/learn/HyperVue/hyperf:/hyperVue-hyperf -p 9501:9501 -it --entrypoint /bin/sh hyperf/hyperf:7.2-alpine-cli
26 |
27 | ```
28 | 以下在容器中操作
29 | ```
30 | # 镜像容器运行后,在容器内安装 Composer
31 | wget https://github.com/composer/composer/releases/download/1.8.6/composer.phar
32 | chmod u+x composer.phar
33 | mv composer.phar /usr/local/bin/composer
34 |
35 | # 将 Composer 镜像设置为阿里云镜像,加速国内下载速度
36 | composer config -g repo.packagist composer https://mirrors.aliyun.com/composer
37 |
38 | # 进入安装好的 Hyperf 项目目录
39 | cd hyperVue-hyperf
40 |
41 | # 安装依赖
42 | composer install
43 |
44 | # 复制env文件
45 | cp .env.example .env
46 |
47 | # 导入数据库 hyperVue.sql
48 |
49 | # 修改env文件里面的相关参数,保存退出
50 | vi .env
51 |
52 | # 启动 Hyperf
53 | php bin/hyperf.php start
54 | ```
55 |
56 | #### vue 部署
57 | ```
58 | # 下载并运行node镜像,并将镜像内的项目目录绑定到宿主机的hyperVue下的vue目录
59 | # 我的目录是 /Users/yhq/wwwroot/learn/HyperVue/vue
60 | docker run --name hyperVue-vue -v /Users/yhq/wwwroot/learn/HyperVue/vue:/hyperVue-vue -it --entrypoint /bin/sh node:latest
61 | ```
62 | 以下在容器中运行
63 | ```
64 | # 安装vim
65 | apt-get update
66 | apt-get install vim
67 |
68 | # 修改接口地址
69 | vim /hyperVue-vue/build/webpack.base.conf.js
70 | # 改成对应接口地址
71 | var PUB_HOST = JSON.stringify('http://127.0.0.1:9501/')
72 |
73 | # 将 npm 镜像设置为淘宝镜像cnpm,加速国内下载速度
74 | npm install -g cnpm --registry=https://registry.npm.taobao.org
75 |
76 | # 安装依赖
77 | cnpm install
78 |
79 | # 本地调试
80 | npm run dev
81 |
82 | # 构建
83 | npm run build
84 | ```
85 |
86 | ## 一些常用命令
87 | ```
88 | #进入容器
89 | docker exec -it hyperVue-vue /bin/sh
90 |
91 | 查看扩展信息
92 | php --ri swoole
93 |
94 | 查看composer包信息
95 | composer info | grep hyperf
96 |
97 | 请求
98 | curl 127.0.0.1:9501/admin/base/getConfigs -w %{http_code}
99 |
100 | 参数:
101 | -w %{http_code}
102 | -X POST
103 |
104 | 自动化测试
105 | https://phpunit.readthedocs.io/zh_CN/latest/writing-tests-for-phpunit.html
106 | # 重新生成代理类
107 | php bin/hyperf.php di:init-proxy
108 | # 运行单元测试
109 | composer test
110 | composer test -- --filter=testFoo
111 |
112 | # 类名: class FooTest extends HttpTestCase
113 |
114 | # 方法名:
115 | public function testFoo(){}
116 | 或者
117 | /**
118 | * @test
119 | */
120 | public function foo(){}
121 | ```
122 | > 免责声明: 该项目仅作为学习使用,如投入生产所产生的损失由使用者自己承担!!!
--------------------------------------------------------------------------------
/hyperf/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hyperf/hyperf-skeleton",
3 | "type": "project",
4 | "keywords": [
5 | "php",
6 | "swoole",
7 | "framework",
8 | "hyperf",
9 | "microservice",
10 | "middleware"
11 | ],
12 | "description": "A coroutine framework that focuses on hyperspeed and flexible, specifically use for build microservices and middlewares.",
13 | "license": "Apache-2.0",
14 | "require": {
15 | "php": ">=7.2",
16 | "ext-swoole": ">=4.4",
17 | "hyperf/cache": "~1.1.0",
18 | "hyperf/command": "~1.1.0",
19 | "hyperf/config": "~1.1.0",
20 | "hyperf/contract": "~1.1.0",
21 | "hyperf/database": "~1.1.0",
22 | "hyperf/db-connection": "~1.1.0",
23 | "hyperf/devtool": "~1.1.0",
24 | "hyperf/di": "~1.1.0",
25 | "hyperf/dispatcher": "~1.1.0",
26 | "hyperf/event": "~1.1.0",
27 | "hyperf/exception-handler": "~1.1.0",
28 | "hyperf/framework": "~1.1.0",
29 | "hyperf/guzzle": "~1.1.0",
30 | "hyperf/http-server": "~1.1.0",
31 | "hyperf/logger": "~1.1.0",
32 | "hyperf/memory": "~1.1.0",
33 | "hyperf/paginator": "~1.1.0",
34 | "hyperf/pool": "~1.1.0",
35 | "hyperf/process": "~1.1.0",
36 | "hyperf/redis": "~1.1.0",
37 | "hyperf/utils": "~1.1.0",
38 | "hyperf/constants": "~1.1.0",
39 | "hyperf/validation": "^1.1",
40 | "hyperf/translation": "^1.1"
41 | },
42 | "require-dev": {
43 | "swoft/swoole-ide-helper": "^4.2",
44 | "phpmd/phpmd": "^2.6",
45 | "friendsofphp/php-cs-fixer": "^2.14",
46 | "mockery/mockery": "^1.0",
47 | "doctrine/common": "^2.9",
48 | "phpstan/phpstan": "^0.11.2",
49 | "hyperf/testing": "~1.1.0",
50 | "symfony/var-dumper": "^4.3"
51 | },
52 | "suggest": {
53 | "ext-openssl": "Required to use HTTPS.",
54 | "ext-json": "Required to use JSON.",
55 | "ext-pdo": "Required to use MySQL Client.",
56 | "ext-pdo_mysql": "Required to use MySQL Client.",
57 | "ext-redis": "Required to use Redis Client."
58 | },
59 | "autoload": {
60 | "psr-4": {
61 | "App\\": "app/"
62 | },
63 | "files": [
64 | "app/Kernel/Functions.php"
65 | ]
66 | },
67 | "autoload-dev": {
68 | "psr-4": {
69 | "HyperfTest\\": "./test/"
70 | }
71 | },
72 | "minimum-stability": "dev",
73 | "prefer-stable": true,
74 | "extra": [],
75 | "scripts": {
76 | "post-root-package-install": [
77 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
78 | ],
79 | "test": "co-phpunit -c phpunit.xml --colors=always",
80 | "cs-fix": "php-cs-fixer fix $1",
81 | "analyze": "phpstan analyse --memory-limit 300M -l 0 -c phpstan.neon ./app ./config",
82 | "start": "php ./bin/hyperf.php start"
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/vue/src/components/rules/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{1 | ruleLevel}}
13 | {{2 | ruleLevel}}
14 | {{3 | ruleLevel}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | 提交
24 | 返回
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/hyperf/config/routes.php:
--------------------------------------------------------------------------------
1 | [PermissionMiddleware::class]]);
26 |
27 | Router::resource('/admin/users', 'App\Controller\UsersController', ['middleware' => [PermissionMiddleware::class]]);
28 | Router::post('/admin/users/deletes', 'App\Controller\UsersController@deletes', ['middleware' => [PermissionMiddleware::class]]);
29 | Router::post('/admin/users/enables', 'App\Controller\UsersController@enables', ['middleware' => [PermissionMiddleware::class]]);
30 |
31 | Router::resource('/admin/groups', 'App\Controller\GroupsController', ['middleware' => [PermissionMiddleware::class]]);
32 | Router::post('/admin/groups/deletes', 'App\Controller\GroupsController@deletes', ['middleware' => [PermissionMiddleware::class]]);
33 | Router::post('/admin/groups/enables', 'App\Controller\GroupsController@enables', ['middleware' => [PermissionMiddleware::class]]);
34 |
35 | Router::resource('/admin/menus', 'App\Controller\MenusController', ['middleware' => [PermissionMiddleware::class]]);
36 | Router::post('/admin/menus/deletes', 'App\Controller\MenusController@deletes', ['middleware' => [PermissionMiddleware::class]]);
37 | Router::post('/admin/menus/enables', 'App\Controller\MenusController@enables', ['middleware' => [PermissionMiddleware::class]]);
38 |
39 | Router::resource('/admin/posts', 'App\Controller\PostsController', ['middleware' => [PermissionMiddleware::class]]);
40 | Router::post('/admin/posts/deletes', 'App\Controller\PostsController@deletes', ['middleware' => [PermissionMiddleware::class]]);
41 | Router::post('/admin/posts/enables', 'App\Controller\PostsController@enables', ['middleware' => [PermissionMiddleware::class]]);
42 |
43 | Router::resource('/admin/rules', 'App\Controller\RulesController', ['middleware' => [PermissionMiddleware::class]]);
44 | Router::post('/admin/rules/deletes', 'App\Controller\RulesController@deletes', ['middleware' => [PermissionMiddleware::class]]);
45 | Router::post('/admin/rules/enables', 'App\Controller\RulesController@enables', ['middleware' => [PermissionMiddleware::class]]);
46 |
47 | Router::resource('/admin/structures', 'App\Controller\StructuresController', ['middleware' => [PermissionMiddleware::class]]);
48 | Router::post('/admin/structures/deletes', 'App\Controller\StructuresController@deletes', ['middleware' => [PermissionMiddleware::class]]);
49 | Router::post('/admin/structures/enables', 'App\Controller\StructuresController@enables', ['middleware' => [PermissionMiddleware::class]]);
50 |
--------------------------------------------------------------------------------
/vue/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var utils = require('./utils')
4 | var webpack = require('webpack')
5 | var projectRoot = path.resolve(__dirname, '../')
6 |
7 | var env = process.env.NODE_ENV
8 | // check env & config/index.js to decide weither to enable CSS Sourcemaps for the
9 | // various preprocessor loaders added to vue-loader at the end of this file
10 | var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
11 | var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
12 | var useCssSourceMap = cssSourceMapDev || cssSourceMapProd
13 |
14 | // define the different HOST between development and production environment
15 | var DEV_HOST = JSON.stringify('http://127.0.0.1:9501/')
16 | // var DEV_HOST = JSON.stringify('http://hypervue.test/')
17 | var PUB_HOST = JSON.stringify('https://hypervue.yanghuaqiang.com/api/')
18 |
19 | module.exports = {
20 | entry: {
21 | app: './src/main.js'
22 | },
23 | output: {
24 | path: config.build.assetsRoot,
25 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
26 | filename: '[name].js'
27 | },
28 | eslint: {
29 | // configFile: './.eslintrc.json'
30 | },
31 | plugins: [
32 | new webpack.DefinePlugin({
33 | HOST: process.env.NODE_ENV === 'production' ? PUB_HOST : DEV_HOST
34 | })
35 | ],
36 | resolve: {
37 | extensions: ['', '.js', '.vue'],
38 | fallback: [path.join(__dirname, '../node_modules')],
39 | alias: {
40 | 'vue$': 'vue/dist/vue',
41 | 'src': path.resolve(__dirname, '../src'),
42 | 'assets': path.resolve(__dirname, '../src/assets'),
43 | 'components': path.resolve(__dirname, '../src/components')
44 | }
45 | },
46 | resolveLoader: {
47 | fallback: [path.join(__dirname, '../node_modules')]
48 | },
49 | module: {
50 | // preLoaders: [
51 | // {
52 | // test: /\.js$/,
53 | // exclude: /node_modules/,
54 | // loader: 'eslint'
55 | // },
56 | // {
57 | // test: /\.vue$/,
58 | // exclude: /node_modules/,
59 | // loader: 'eslint'
60 | // }
61 | // ],
62 | loaders: [
63 | {
64 | test: /\.vue$/,
65 | loader: 'vue'
66 | },
67 | {
68 | test: /\.js$/,
69 | loader: 'babel',
70 | include: projectRoot,
71 | exclude: /node_modules/,
72 | query: {
73 | presets: ['es2015', 'stage-3']
74 | }
75 | },
76 | {
77 | test: /\.json$/,
78 | loader: 'json'
79 | },
80 | {
81 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
82 | loader: 'url',
83 | query: {
84 | limit: 10000,
85 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
86 | }
87 | },
88 | {
89 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
90 | loader: 'url',
91 | query: {
92 | limit: 10000,
93 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
94 | }
95 | }
96 | ]
97 | },
98 | vue: {
99 | loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }),
100 | postcss: [
101 | require('autoprefixer')({
102 | browsers: ['last 2 versions']
103 | })
104 | ]
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/vue/src/components/common/btnGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 启用
4 | 禁用
5 | 删除
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/vue/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var utils = require('./utils')
4 | var webpack = require('webpack')
5 | var merge = require('webpack-merge')
6 | var baseWebpackConfig = require('./webpack.base.conf')
7 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
8 | var HtmlWebpackPlugin = require('html-webpack-plugin')
9 | var env = config.build.env
10 |
11 | var webpackConfig = merge(baseWebpackConfig, {
12 | module: {
13 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true })
14 | },
15 | devtool: config.build.productionSourceMap ? '#source-map' : false,
16 | output: {
17 | path: config.build.assetsRoot,
18 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
19 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
20 | },
21 | vue: {
22 | loaders: utils.cssLoaders({
23 | sourceMap: config.build.productionSourceMap,
24 | extract: true
25 | })
26 | },
27 | plugins: [
28 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
29 | new webpack.DefinePlugin({
30 | 'process.env': env
31 | }),
32 | new webpack.optimize.UglifyJsPlugin({
33 | compress: {
34 | warnings: false
35 | }
36 | }),
37 | new webpack.optimize.OccurenceOrderPlugin(),
38 | // extract css into its own file
39 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')),
40 | // generate dist index.html with correct asset hash for caching.
41 | // you can customize output by editing /index.html
42 | // see https://github.com/ampedandwired/html-webpack-plugin
43 | new HtmlWebpackPlugin({
44 | filename: config.build.index,
45 | template: 'index.html',
46 | inject: true,
47 | minify: {
48 | removeComments: true,
49 | collapseWhitespace: true,
50 | removeAttributeQuotes: true
51 | // more options:
52 | // https://github.com/kangax/html-minifier#options-quick-reference
53 | },
54 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
55 | chunksSortMode: 'dependency'
56 | }),
57 | // split vendor js into its own file
58 | new webpack.optimize.CommonsChunkPlugin({
59 | name: 'vendor',
60 | minChunks: function (module, count) {
61 | // any required modules inside node_modules are extracted to vendor
62 | return (
63 | module.resource &&
64 | /\.js$/.test(module.resource) &&
65 | module.resource.indexOf(
66 | path.join(__dirname, '../node_modules')
67 | ) === 0
68 | )
69 | }
70 | }),
71 | // extract webpack runtime and module manifest to its own file in order to
72 | // prevent vendor hash from being updated whenever app bundle is updated
73 | new webpack.optimize.CommonsChunkPlugin({
74 | name: 'manifest',
75 | chunks: ['vendor']
76 | })
77 | ]
78 | })
79 |
80 | if (config.build.productionGzip) {
81 | var CompressionWebpackPlugin = require('compression-webpack-plugin')
82 |
83 | webpackConfig.plugins.push(
84 | new CompressionWebpackPlugin({
85 | asset: '[path].gz[query]',
86 | algorithm: 'gzip',
87 | test: new RegExp(
88 | '\\.(' +
89 | config.build.productionGzipExtensions.join('|') +
90 | ')$'
91 | ),
92 | threshold: 10240,
93 | minRatio: 0.8
94 | })
95 | )
96 | }
97 |
98 | module.exports = webpackConfig
99 |
--------------------------------------------------------------------------------
/vue/src/components/rules/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{1 | ruleLevel}}
13 | {{2 | ruleLevel}}
14 | {{3 | ruleLevel}}
15 |
16 |
17 |
18 |
19 |
26 |
27 |
28 |
29 | 提交
30 | 返回
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/hyperf/app/Kernel/Http/Router.php:
--------------------------------------------------------------------------------
1 | getAttributes()['Hyperf\HttpServer\Router\Dispatched']->handler->callback;
117 | [$class, $method] = explode('@', $action);
118 |
119 | return ['controller' => $class, 'method' => $method];
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/vue/src/assets/js/filter.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | export default (function () {
3 | Vue.filter('status', function (value) {
4 | if (value == 1) {
5 | return '启用'
6 | } else if (value == 0) {
7 | return '禁用'
8 | } else {
9 | return '未知状态'
10 | }
11 | })
12 | Vue.filter('tagType', function (value) {
13 | if (value == 1) {
14 | return 'success'
15 | } else if (value == 0) {
16 | return 'danger'
17 | } else {
18 | return ''
19 | }
20 | })
21 | Vue.filter('rules', function (value) {
22 | return value
23 | })
24 | Vue.filter('fileLink', function (value) {
25 | const link = window.imgUrl + value
26 | return link
27 | })
28 | Vue.filter('toolType', function (value) {
29 | let type = ''
30 | if (value == 1) {
31 | type = '系统工具'
32 | } else if (value == 2) {
33 | type = '说明指导'
34 | }
35 | return type
36 | })
37 | Vue.filter('numToString', function (value) {
38 | const string = value.toString()
39 | return string
40 | })
41 | Vue.filter('projectState', function (value) {
42 | let string = ''
43 | switch (value) {
44 | case '1':
45 | string = '售前项目'
46 | break
47 | case '2':
48 | string = '服务中项目'
49 | break
50 | case '3':
51 | string = '已结束项目'
52 | break
53 | }
54 | return string
55 | })
56 | Vue.filter('time', function (value) {
57 | let day = moment.unix(value)
58 | let date = moment(day).format('YYYY/MM/DD H:mm')
59 | return date
60 | })
61 | Vue.filter('date', function (value) {
62 | let day = moment.unix(value)
63 | let date = moment(day).format('YYYY/MM/DD')
64 | return date
65 | })
66 | Vue.filter('abstract', function (value) {
67 | let abstract = ''
68 | if (value.length > 70) {
69 | abstract = value.substr(0, 70) + '...'
70 | } else {
71 | abstract = value
72 | }
73 | return abstract
74 | })
75 | Vue.filter('posStatus', function (value) {
76 | let status = ''
77 | switch (value) {
78 | case 1:
79 | status = '在职'
80 | break
81 | case 2:
82 | status = '待入职'
83 | break
84 | case 3:
85 | status = '离职'
86 | break
87 | }
88 | return status
89 | })
90 | Vue.filter('template', function (value) {
91 | let template = ''
92 | if (value == '') {
93 | template = '上传'
94 | } else {
95 | template = '上传更新'
96 | }
97 | return template
98 | })
99 | Vue.filter('menuType', function (value) {
100 | let title = ''
101 | switch (value) {
102 | case 1:
103 | title = '普通菜单'
104 | break
105 | case 2:
106 | title = '外链'
107 | break
108 | }
109 | return title
110 | })
111 | Vue.filter('ruleLevel', function (value) {
112 | let title = ''
113 | switch (value) {
114 | case 1:
115 | title = '模块'
116 | break
117 | case 2:
118 | title = '控制器'
119 | break
120 | case 3:
121 | title = '操作'
122 | break
123 | }
124 | return title
125 | })
126 | })()
--------------------------------------------------------------------------------
/hyperf/app/Middleware/PermissionMiddleware.php:
--------------------------------------------------------------------------------
1 | request->header('authKey');
36 | $sessionId = $this->request->header('sessionId');
37 |
38 | //获取用户信息
39 | $getLoggedInfo = $this->userService->getLoggedInfo($authKey);
40 | if (!$getLoggedInfo) {
41 | throw new BusinessException(ErrorCode::LOGIN_INVALID);
42 | }
43 |
44 | $userInfo = $getLoggedInfo['userInfo'];
45 | $uid = $userInfo['id'];
46 | $username = $userInfo['username'];
47 | // 检查用户状态
48 | if (!$this->userService->isEnable($uid)) {
49 | throw new BusinessException(ErrorCode::USER_DELETED_OR_DISABLED);
50 | }
51 |
52 | // 多处登录校验
53 | if ($getLoggedInfo['sessionId'] !== $sessionId && !config('ALLOW_MULTIPLE_LOGINS')) {
54 | throw new BusinessException(ErrorCode::LOGGED_ELSEWHERE);
55 | }
56 |
57 | // 获取路由名
58 | $ruleName = Router::getCurrentRuleName();
59 |
60 | // // 用户id 写入日志
61 | // $data['uid'] = $uid;
62 | // $data['name'] = $username;
63 | // Log::record($data, 'admin_param');
64 |
65 | // 权限校验
66 | $isSupperUser = $this->userService->isSupperUser($uid);
67 | if (!$isSupperUser && !$this->check($ruleName, $uid)) {
68 | throw new BusinessException(ErrorCode::PERMISSION_DENIED);
69 | }
70 |
71 | // 保存用户信息到上下文
72 | Context::set('userInfo', $userInfo);
73 |
74 | return $handler->handle($request);
75 | }
76 |
77 | /**
78 | * 权限校验
79 | *
80 | * @param string|array $name 需要验证的规则列表,支持逗号分隔的权限规则或索引数组
81 | * @param integer $uid 认证用户的id
82 | * @return boolean 通过验证返回true 失败返回false
83 | */
84 | private function check($name, $uid, $relation = 'or'): bool
85 | {
86 | // 获取用户具有权限的规则列表
87 | $getUserOwnRules = $this->userService->getUserOwnRules($uid);
88 | $rulesList = $getUserOwnRules['rulesList'];
89 |
90 | if (is_string($name)) {
91 | $name = strtolower($name);
92 | if (strpos($name, ',') !== false) {
93 | $name = explode(',', $name);
94 | } else {
95 | $name = array($name);
96 | }
97 | }
98 | if (is_array($name)) {
99 | foreach ($name as $k => $v) {
100 | $name[$k] = strtolower($v);
101 | }
102 | }
103 |
104 | // 保存验证通过的规则名
105 | $list = [];
106 | foreach ($rulesList as $rule) {
107 | if (in_array($rule, $name)) {
108 | $list[] = $rule;
109 | }
110 | }
111 | if ($relation == 'or' && !empty($list)) {
112 | return true;
113 | }
114 | $diff = array_diff($name, $list);
115 | if ($relation == 'and' && empty($diff)) {
116 | return true;
117 | }
118 | return false;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/vue/src/components/menus/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 查找
10 |
11 |
12 |
13 | {{1 | menuType}}
14 | {{2 | menuType}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | 提交
33 | 返回
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/vue/src/components/users/list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 添加用户
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
38 |
39 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/vue/src/routes.js:
--------------------------------------------------------------------------------
1 | import login from './components/base/login'
2 | import refresh from './components/base/refresh'
3 | import home from './components/home'
4 | import menusList from './components/menus/list'
5 | import menusAdd from './components/menus/add'
6 | import menusEdit from './components/menus/edit'
7 | import configs from './components/configs/add'
8 | import rulesList from './components/rules/list'
9 | import rulesAdd from './components/rules/add'
10 | import rulesEdit from './components/rules/edit'
11 | import postsList from './components/posts/list'
12 | import postsAdd from './components/posts/add'
13 | import postsEdit from './components/posts/edit'
14 | import structuresList from './components/structures/list'
15 | import structuresAdd from './components/structures/add'
16 | import structuresEdit from './components/structures/edit'
17 | import groupsList from './components/groups/list'
18 | import groupsAdd from './components/groups/add'
19 | import groupsEdit from './components/groups/edit'
20 | import usersList from './components/users/list'
21 | import usersAdd from './components/users/add'
22 | import usersEdit from './components/users/edit'
23 |
24 | /**
25 | * meta参数解析
26 | * activeMenu 高亮菜单
27 | */
28 |
29 | const routes = [
30 | { path: '/', component: login, name: 'login' },
31 | {
32 | path: '/refresh',
33 | component: home,
34 | children: [
35 | { path: '/refresh', component: refresh, name: 'refresh' }
36 | ]
37 | },
38 | {
39 | path: '/home',
40 | component: home,
41 | children: [
42 | { path: 'menus/list', component: menusList, name: 'menusList', meta: { activeMenu: '/home/menus/list' } },
43 | { path: 'menus/add', component: menusAdd, name: 'menusAdd', meta: { activeMenu: '/home/menus/list' } },
44 | { path: 'menus/edit/:id', component: menusEdit, name: 'menusEdit', meta: { activeMenu: '/home/menus/list' } }
45 | ]
46 | },
47 | {
48 | path: '/home',
49 | component: home,
50 | children: [
51 | { path: 'configs/add', component: configs, name: 'configs', meta: { activeMenu: '/home/configs/add' } }
52 | ]
53 | },
54 |
55 | {
56 | path: '/home',
57 | component: home,
58 | children: [
59 | { path: 'rules/list', component: rulesList, name: 'rulesList', meta: { activeMenu: '/home/rules/list' } },
60 | { path: 'rules/add', component: rulesAdd, name: 'rulesAdd', meta: { activeMenu: '/home/rules/list' } },
61 | { path: 'rules/edit/:id', component: rulesEdit, name: 'rulesEdit', meta: { activeMenu: '/home/rules/list' } }
62 | ]
63 | },
64 | {
65 | path: '/home',
66 | component: home,
67 | children: [
68 | { path: 'posts/list', component: postsList, name: 'postsList', meta: { activeMenu: '/home/posts/list' } },
69 | { path: 'posts/add', component: postsAdd, name: 'postsAdd', meta: { activeMenu: '/home/posts/list' } },
70 | { path: 'posts/edit/:id', component: postsEdit, name: 'postsEdit', meta: { activeMenu: '/home/posts/list' } }
71 | ]
72 | },
73 | {
74 | path: '/home',
75 | component: home,
76 | children: [
77 | { path: 'structures/list', component: structuresList, name: 'structuresList', meta: { activeMenu: '/home/structures/list' } },
78 | { path: 'structures/add', component: structuresAdd, name: 'structuresAdd', meta: { activeMenu: '/home/structures/list' } },
79 | { path: 'structures/edit/:id', component: structuresEdit, name: 'structuresEdit', meta: { activeMenu: '/home/structures/list' } }
80 | ]
81 | },
82 | {
83 | path: '/home',
84 | component: home,
85 | children: [
86 | { path: 'groups/list', component: groupsList, name: 'groupsList', meta: { activeMenu: '/home/groups/list' } },
87 | { path: 'groups/add', component: groupsAdd, name: 'groupsAdd', meta: { activeMenu: '/home/groups/list' } },
88 | { path: 'groups/edit/:id', component: groupsEdit, name: 'groupsEdit', meta: { activeMenu: '/home/groups/list' } }
89 | ]
90 | },
91 | {
92 | path: '/home',
93 | component: home,
94 | children: [
95 | { path: 'users/list', component: usersList, name: 'usersList', meta: { activeMenu: '/home/users/list' } },
96 | { path: 'users/add', component: usersAdd, name: 'usersAdd', meta: { activeMenu: '/home/users/list' } },
97 | { path: 'users/edit/:id', component: usersEdit, name: 'usersEdit', meta: { activeMenu: '/home/users/list' } }
98 | ]
99 | },
100 | ]
101 | export default routes
102 |
--------------------------------------------------------------------------------
/vue/src/components/menus/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 查找
10 |
11 |
12 |
13 | {{1 | menuType}}
14 | {{2 | menuType}}
15 |
16 |
17 |
18 |
19 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | 提交
39 | 返回
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/vue/src/components/configs/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
18 |
19 |
20 | 将文件拖到此处,或
21 | 点击上传
22 |
23 | 只能上传jpg/png文件
24 |
25 |
26 |
27 |
28 | 图片
29 | 文字
30 |
31 |
32 |
33 |
34 | 打开
35 | 关闭
36 |
37 |
38 |
39 |
40 |
41 |
42 | 提交
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/vue/src/components/base/login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 | {{systemName}}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
26 |
27 |
28 | 记住密码
29 |
30 | 登录
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/vue/src/components/users/add.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 | 提交
43 | 返回
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------