├── .babelrc
├── .dockerignore
├── .editorconfig
├── .env.example
├── .eslintrc.js
├── .gitattributes
├── .gitignore
├── .gitlab-ci.yml
├── .postcssrc.js
├── .prettierrc.js
├── .styleci.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── Envoy.blade.php
├── LICENSE
├── README.md
├── app
├── Console
│ └── Kernel.php
├── Exceptions
│ └── Handler.php
├── Http
│ ├── Controllers
│ │ ├── Api
│ │ │ ├── AuthController.php
│ │ │ ├── BaseController.php
│ │ │ ├── PermissionController.php
│ │ │ ├── RoleController.php
│ │ │ └── UserController.php
│ │ ├── Controller.php
│ │ └── LaravueController.php
│ ├── Kernel.php
│ ├── Middleware
│ │ ├── Authenticate.php
│ │ ├── CheckForMaintenanceMode.php
│ │ ├── EncryptCookies.php
│ │ ├── RedirectIfAuthenticated.php
│ │ ├── TrimStrings.php
│ │ ├── TrustHosts.php
│ │ ├── TrustProxies.php
│ │ └── VerifyCsrfToken.php
│ └── Resources
│ │ ├── PermissionResource.php
│ │ ├── RoleResource.php
│ │ └── UserResource.php
├── Laravue
│ ├── Acl.php
│ ├── Faker.php
│ ├── JsonResponse.php
│ └── Models
│ │ ├── Permission.php
│ │ ├── Role.php
│ │ └── User.php
├── Providers
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ ├── BroadcastServiceProvider.php
│ ├── EventServiceProvider.php
│ └── RouteServiceProvider.php
└── User.php
├── artisan
├── bootstrap
├── app.php
└── cache
│ └── .gitignore
├── composer.json
├── composer.lock
├── config
├── app.php
├── auth.php
├── broadcasting.php
├── cache.php
├── cors.php
├── database.php
├── filesystems.php
├── hashing.php
├── jwt.php
├── logging.php
├── mail.php
├── permission.php
├── queue.php
├── sanctum.php
├── services.php
├── session.php
└── view.php
├── database
├── .gitignore
├── factories
│ └── UserFactory.php
├── migrations
│ ├── 2014_10_12_000000_create_users_table.php
│ ├── 2014_10_12_100000_create_password_resets_table.php
│ ├── 2019_03_16_102314_add_simple_role_to_user_table.php
│ ├── 2019_04_20_125200_create_permission_tables.php
│ ├── 2019_04_20_130706_setup_role_permissions.php
│ ├── 2019_08_19_000000_create_failed_jobs_table.php
│ ├── 2019_12_14_000001_create_personal_access_tokens_table.php
│ └── 2020_03_25_170854_remove_passport.php
└── seeds
│ ├── DatabaseSeeder.php
│ └── UsersTableSeeder.php
├── docker-compose.yml
├── docker
├── .gitignore
└── docker.env
├── laravue-entrypoint.sh
├── package-lock.json
├── package.json
├── phpunit.xml
├── public
├── .gitignore
├── .htaccess
├── favicon.ico
├── favicon
│ ├── android-icon-144x144.png
│ ├── android-icon-192x192.png
│ ├── android-icon-36x36.png
│ ├── android-icon-48x48.png
│ ├── android-icon-72x72.png
│ ├── android-icon-96x96.png
│ ├── apple-icon-114x114.png
│ ├── apple-icon-120x120.png
│ ├── apple-icon-144x144.png
│ ├── apple-icon-152x152.png
│ ├── apple-icon-180x180.png
│ ├── apple-icon-57x57.png
│ ├── apple-icon-60x60.png
│ ├── apple-icon-72x72.png
│ ├── apple-icon-76x76.png
│ ├── apple-icon-precomposed.png
│ ├── apple-icon.png
│ ├── browserconfig.xml
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-96x96.png
│ ├── favicon.ico
│ ├── manifest.json
│ ├── ms-icon-144x144.png
│ ├── ms-icon-150x150.png
│ ├── ms-icon-310x310.png
│ └── ms-icon-70x70.png
├── images
│ └── .gitignore
├── index.php
├── robots.txt
├── static
│ └── tinymce4.7.5
│ │ ├── langs
│ │ └── zh_CN.js
│ │ ├── plugins
│ │ ├── codesample
│ │ │ └── css
│ │ │ │ └── prism.css
│ │ ├── emoticons
│ │ │ └── img
│ │ │ │ ├── smiley-cool.gif
│ │ │ │ ├── smiley-cry.gif
│ │ │ │ ├── smiley-embarassed.gif
│ │ │ │ ├── smiley-foot-in-mouth.gif
│ │ │ │ ├── smiley-frown.gif
│ │ │ │ ├── smiley-innocent.gif
│ │ │ │ ├── smiley-kiss.gif
│ │ │ │ ├── smiley-laughing.gif
│ │ │ │ ├── smiley-money-mouth.gif
│ │ │ │ ├── smiley-sealed.gif
│ │ │ │ ├── smiley-smile.gif
│ │ │ │ ├── smiley-surprised.gif
│ │ │ │ ├── smiley-tongue-out.gif
│ │ │ │ ├── smiley-undecided.gif
│ │ │ │ ├── smiley-wink.gif
│ │ │ │ └── smiley-yell.gif
│ │ └── visualblocks
│ │ │ └── css
│ │ │ └── visualblocks.css
│ │ ├── skins
│ │ └── lightgray
│ │ │ ├── content.inline.min.css
│ │ │ ├── content.min.css
│ │ │ ├── fonts
│ │ │ ├── tinymce-mobile.woff
│ │ │ ├── tinymce-small.eot
│ │ │ ├── tinymce-small.svg
│ │ │ ├── tinymce-small.ttf
│ │ │ ├── tinymce-small.woff
│ │ │ ├── tinymce.eot
│ │ │ ├── tinymce.svg
│ │ │ ├── tinymce.ttf
│ │ │ └── tinymce.woff
│ │ │ ├── img
│ │ │ ├── anchor.gif
│ │ │ ├── loader.gif
│ │ │ ├── object.gif
│ │ │ └── trans.gif
│ │ │ ├── skin.min.css
│ │ │ └── skin.min.css.map
│ │ └── tinymce.min.js
├── svg
│ ├── 403.svg
│ ├── 404.svg
│ ├── 500.svg
│ ├── 503.svg
│ └── logo.svg
└── web.config
├── resources
├── js
│ ├── api
│ │ ├── article.js
│ │ ├── auth.js
│ │ ├── order.js
│ │ ├── resource.js
│ │ ├── role.js
│ │ ├── search.js
│ │ └── user.js
│ ├── app.js
│ ├── assets
│ │ ├── 401_images
│ │ │ └── 401.gif
│ │ ├── 404_images
│ │ │ ├── 404.png
│ │ │ └── 404_cloud.png
│ │ ├── custom-theme
│ │ │ ├── fonts
│ │ │ │ ├── element-icons.ttf
│ │ │ │ └── element-icons.woff
│ │ │ └── index.css
│ │ └── login
│ │ │ ├── login_background.jpg
│ │ │ └── logo.png
│ ├── bootstrap.js
│ ├── components
│ │ ├── BackToTop
│ │ │ └── index.vue
│ │ ├── Breadcrumb
│ │ │ └── index.vue
│ │ ├── Charts
│ │ │ ├── Keyboard.vue
│ │ │ ├── LineMarker.vue
│ │ │ ├── MixChart.vue
│ │ │ └── mixins
│ │ │ │ └── resize.js
│ │ ├── DndList
│ │ │ └── index.vue
│ │ ├── DragSelect
│ │ │ └── index.vue
│ │ ├── Dropzone
│ │ │ └── index.vue
│ │ ├── ExampleComponent.vue
│ │ ├── GithubCorner
│ │ │ └── index.vue
│ │ ├── Hamburger
│ │ │ └── index.vue
│ │ ├── HeaderSearch
│ │ │ └── index.vue
│ │ ├── ImageCropper
│ │ │ ├── index.vue
│ │ │ └── utils
│ │ │ │ ├── data2blob.js
│ │ │ │ ├── effect-ripple.js
│ │ │ │ ├── language.js
│ │ │ │ └── mimes.js
│ │ ├── JsonEditor
│ │ │ └── index.vue
│ │ ├── Kanban
│ │ │ └── index.vue
│ │ ├── LangSelect
│ │ │ └── index.vue
│ │ ├── MDinput
│ │ │ └── index.vue
│ │ ├── MarkdownEditor
│ │ │ ├── default-options.js
│ │ │ └── index.vue
│ │ ├── Pagination
│ │ │ └── index.vue
│ │ ├── PanThumb
│ │ │ └── index.vue
│ │ ├── RightPanel
│ │ │ └── index.vue
│ │ ├── Screenfull
│ │ │ └── index.vue
│ │ ├── ScrollPane
│ │ │ └── index.vue
│ │ ├── Share
│ │ │ └── DropdownMenu.vue
│ │ ├── SizeSelect
│ │ │ └── index.vue
│ │ ├── Sticky
│ │ │ └── index.vue
│ │ ├── SvgIcon
│ │ │ └── index.vue
│ │ ├── TextHoverEffect
│ │ │ └── Mallki.vue
│ │ ├── ThemePicker
│ │ │ └── index.vue
│ │ ├── Tinymce
│ │ │ ├── components
│ │ │ │ └── EditorImage.vue
│ │ │ ├── index.vue
│ │ │ ├── plugins.js
│ │ │ └── toolbar.js
│ │ ├── Upload
│ │ │ └── SingleImage.vue
│ │ └── UploadExcel
│ │ │ └── index.vue
│ ├── directive
│ │ ├── clipboard
│ │ │ ├── clipboard.js
│ │ │ └── index.js
│ │ ├── el-drag-dialog
│ │ │ ├── drag.js
│ │ │ └── index.js
│ │ ├── el-table
│ │ │ ├── adaptive.js
│ │ │ └── index.js
│ │ ├── permission
│ │ │ ├── index.js
│ │ │ └── permission.js
│ │ ├── role
│ │ │ ├── index.js
│ │ │ └── role.js
│ │ └── waves
│ │ │ ├── index.js
│ │ │ ├── waves.css
│ │ │ └── waves.js
│ ├── filters
│ │ └── index.js
│ ├── icons
│ │ ├── index.js
│ │ ├── svg
│ │ │ ├── 404.svg
│ │ │ ├── admin.svg
│ │ │ ├── bug.svg
│ │ │ ├── chart.svg
│ │ │ ├── clipboard.svg
│ │ │ ├── comment.svg
│ │ │ ├── component.svg
│ │ │ ├── create-user.svg
│ │ │ ├── dashboard.svg
│ │ │ ├── documentation.svg
│ │ │ ├── dollar.svg
│ │ │ ├── drag.svg
│ │ │ ├── edit.svg
│ │ │ ├── education.svg
│ │ │ ├── email.svg
│ │ │ ├── example.svg
│ │ │ ├── excel.svg
│ │ │ ├── exit-fullscreen.svg
│ │ │ ├── eye-open.svg
│ │ │ ├── eye.svg
│ │ │ ├── form.svg
│ │ │ ├── fullscreen.svg
│ │ │ ├── guide 2.svg
│ │ │ ├── guide.svg
│ │ │ ├── icon.svg
│ │ │ ├── international.svg
│ │ │ ├── language.svg
│ │ │ ├── layout.svg
│ │ │ ├── like.svg
│ │ │ ├── link.svg
│ │ │ ├── list.svg
│ │ │ ├── lock.svg
│ │ │ ├── message.svg
│ │ │ ├── money.svg
│ │ │ ├── nested.svg
│ │ │ ├── password.svg
│ │ │ ├── pdf.svg
│ │ │ ├── people.svg
│ │ │ ├── peoples.svg
│ │ │ ├── qq.svg
│ │ │ ├── role.svg
│ │ │ ├── search.svg
│ │ │ ├── shopping.svg
│ │ │ ├── size.svg
│ │ │ ├── skill.svg
│ │ │ ├── star.svg
│ │ │ ├── tab.svg
│ │ │ ├── table.svg
│ │ │ ├── theme.svg
│ │ │ ├── tree-table.svg
│ │ │ ├── tree.svg
│ │ │ ├── user.svg
│ │ │ ├── wechat.svg
│ │ │ └── zip.svg
│ │ └── svgo.yml
│ ├── lang
│ │ ├── en.js
│ │ ├── index.js
│ │ ├── ru.js
│ │ ├── vi.js
│ │ └── zh.js
│ ├── layout
│ │ ├── components
│ │ │ ├── AppMain.vue
│ │ │ ├── Navbar.vue
│ │ │ ├── Settings
│ │ │ │ └── index.vue
│ │ │ ├── Sidebar
│ │ │ │ ├── Item.vue
│ │ │ │ ├── Link.vue
│ │ │ │ ├── Logo.vue
│ │ │ │ ├── SidebarItem.vue
│ │ │ │ └── index.vue
│ │ │ ├── TagsView
│ │ │ │ ├── ScrollPane.vue
│ │ │ │ └── index.vue
│ │ │ └── index.js
│ │ ├── index.vue
│ │ └── mixin
│ │ │ └── resize-handler.js
│ ├── permission.js
│ ├── router
│ │ ├── index.js
│ │ └── modules
│ │ │ ├── admin.js
│ │ │ ├── charts.js
│ │ │ ├── components.js
│ │ │ ├── element-ui.js
│ │ │ ├── error.js
│ │ │ ├── example.js
│ │ │ ├── excel.js
│ │ │ ├── nested.js
│ │ │ ├── permission.js
│ │ │ └── table.js
│ ├── settings.js
│ ├── store
│ │ ├── getters.js
│ │ ├── index.js
│ │ └── modules
│ │ │ ├── app.js
│ │ │ ├── permission.js
│ │ │ ├── settings.js
│ │ │ ├── tags-view.js
│ │ │ └── user.js
│ ├── styles
│ │ ├── btn.scss
│ │ ├── element-ui.scss
│ │ ├── element-variables.scss
│ │ ├── index.scss
│ │ ├── laravue.scss
│ │ ├── mixin.scss
│ │ ├── sidebar.scss
│ │ ├── transition.scss
│ │ └── variables.scss
│ ├── utils
│ │ ├── auth.js
│ │ ├── clipboard.js
│ │ ├── get-page-title.js
│ │ ├── i18n.js
│ │ ├── index.js
│ │ ├── permission.js
│ │ ├── request.js
│ │ ├── role.js
│ │ ├── scroll-to.js
│ │ └── validate.js
│ ├── vendor
│ │ ├── Export2Excel.js
│ │ └── Export2Zip.js
│ └── views
│ │ ├── App.vue
│ │ ├── articles
│ │ ├── Create.vue
│ │ ├── Edit.vue
│ │ ├── List.vue
│ │ └── components
│ │ │ ├── ArticleDetail.vue
│ │ │ └── Dropdown
│ │ │ ├── Comment.vue
│ │ │ ├── Platform.vue
│ │ │ ├── SourceUrl.vue
│ │ │ └── index.js
│ │ ├── charts
│ │ ├── Keyboard.vue
│ │ ├── Line.vue
│ │ └── MixChart.vue
│ │ ├── clipboard
│ │ └── index.vue
│ │ ├── components-demo
│ │ ├── AvatarUpload.vue
│ │ ├── BackToTop.vue
│ │ ├── CountTo.vue
│ │ ├── DndList.vue
│ │ ├── DragDialog.vue
│ │ ├── DragKanban.vue
│ │ ├── DragSelect.vue
│ │ ├── Dropzone.vue
│ │ ├── JsonEditor.vue
│ │ ├── Markdown.vue
│ │ ├── Mixin.vue
│ │ ├── SplitPane.vue
│ │ ├── Sticky.vue
│ │ └── Tinymce.vue
│ │ ├── dashboard
│ │ ├── admin
│ │ │ ├── components
│ │ │ │ ├── BarChart.vue
│ │ │ │ ├── BoxCard.vue
│ │ │ │ ├── LineChart.vue
│ │ │ │ ├── PanelGroup.vue
│ │ │ │ ├── PieChart.vue
│ │ │ │ ├── RaddarChart.vue
│ │ │ │ ├── TodoList
│ │ │ │ │ ├── Todo.vue
│ │ │ │ │ ├── index.scss
│ │ │ │ │ └── index.vue
│ │ │ │ └── TransactionTable.vue
│ │ │ └── index.vue
│ │ ├── editor
│ │ │ └── index.vue
│ │ └── index.vue
│ │ ├── documentation
│ │ └── index.vue
│ │ ├── error-page
│ │ ├── 401.vue
│ │ └── 404.vue
│ │ ├── excel
│ │ ├── ExportExcel.vue
│ │ ├── MergeHeader.vue
│ │ ├── SelectExcel.vue
│ │ ├── UploadExcel.vue
│ │ └── components
│ │ │ ├── AutoWidthOption.vue
│ │ │ ├── BookTypeOption.vue
│ │ │ └── FilenameOption.vue
│ │ ├── form
│ │ └── index.vue
│ │ ├── guide
│ │ ├── define-steps.js
│ │ └── index.vue
│ │ ├── i18n
│ │ ├── index.vue
│ │ └── local.js
│ │ ├── icons
│ │ ├── components
│ │ │ ├── ElementUI
│ │ │ │ ├── index.vue
│ │ │ │ └── require-icons.js
│ │ │ └── IconFont
│ │ │ │ ├── index.vue
│ │ │ │ └── require-icons.js
│ │ ├── element-icons.js
│ │ ├── index.vue
│ │ └── svg-icons.js
│ │ ├── login
│ │ ├── AuthRedirect.vue
│ │ └── index.vue
│ │ ├── nested
│ │ ├── menu1
│ │ │ ├── index.vue
│ │ │ ├── menu1-1
│ │ │ │ └── index.vue
│ │ │ ├── menu1-2
│ │ │ │ ├── index.vue
│ │ │ │ ├── menu1-2-1
│ │ │ │ │ └── index.vue
│ │ │ │ └── menu1-2-2
│ │ │ │ │ └── index.vue
│ │ │ └── menu1-3
│ │ │ │ └── index.vue
│ │ └── menu2
│ │ │ └── index.vue
│ │ ├── pdf
│ │ ├── Download.vue
│ │ ├── content.js
│ │ └── index.vue
│ │ ├── permission
│ │ ├── Directive.vue
│ │ ├── Page.vue
│ │ ├── Role.vue
│ │ └── components
│ │ │ └── SwitchRoles.vue
│ │ ├── redirect
│ │ └── index.vue
│ │ ├── role-permission
│ │ └── List.vue
│ │ ├── tab
│ │ ├── components
│ │ │ └── TabPane.vue
│ │ └── index.vue
│ │ ├── table
│ │ ├── ComplexTable.vue
│ │ ├── DragTable.vue
│ │ ├── DynamicTable
│ │ │ ├── FixedThead.vue
│ │ │ ├── UnfixedThead.vue
│ │ │ └── index.vue
│ │ └── InlineEditTable.vue
│ │ ├── theme
│ │ └── index.vue
│ │ ├── users
│ │ ├── List.vue
│ │ ├── SelfProfile.vue
│ │ ├── UserProfile.vue
│ │ └── components
│ │ │ ├── UserActivity.vue
│ │ │ ├── UserBio.vue
│ │ │ └── UserCard.vue
│ │ └── zip
│ │ └── index.vue
├── lang
│ └── en
│ │ ├── auth.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ └── validation.php
├── sass
│ ├── _variables.scss
│ └── app.scss
└── views
│ ├── laravue.blade.php
│ ├── spa.blade.php
│ └── welcome.blade.php
├── routes
├── api.php
├── channels.php
├── console.php
└── web.php
├── server.php
├── storage
├── app
│ ├── .gitignore
│ └── public
│ │ └── .gitignore
├── framework
│ ├── .gitignore
│ ├── cache
│ │ ├── .gitignore
│ │ └── data
│ │ │ └── .gitignore
│ ├── sessions
│ │ └── .gitignore
│ ├── testing
│ │ └── .gitignore
│ └── views
│ │ └── .gitignore
└── logs
│ └── .gitignore
├── tests
├── Bootstrap.php
├── CreatesApplication.php
├── Feature
│ └── ExampleTest.php
├── TestCase.php
└── Unit
│ └── ExampleTest.php
├── webpack.config.js
├── webpack.mix.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "corejs": "3",
7 | "useBuiltIns": "entry"
8 | }
9 | ]
10 | ],
11 | "plugins": [
12 | "babel-plugin-syntax-dynamic-import",
13 | "@babel/plugin-syntax-dynamic-import",
14 | "@babel/plugin-transform-runtime",
15 | "babel-plugin-transform-vue-jsx"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | docker
2 |
3 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_style = space
8 | indent_size = 4
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
14 | [*.{yml,yaml,js,vue}]
15 | indent_size = 2
16 | [*.php]
17 | indent_size = 4
18 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | APP_NAME=Laravel
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_URL=http://localhost
6 |
7 | LOG_CHANNEL=stack
8 |
9 | DB_CONNECTION=mysql
10 | DB_HOST=127.0.0.1
11 | DB_PORT=3306
12 | DB_DATABASE=laravel
13 | DB_USERNAME=root
14 | DB_PASSWORD=
15 |
16 | BROADCAST_DRIVER=log
17 | CACHE_DRIVER=file
18 | QUEUE_CONNECTION=sync
19 | SESSION_DRIVER=cookie
20 | SESSION_LIFETIME=120
21 |
22 | REDIS_HOST=127.0.0.1
23 | REDIS_PASSWORD=null
24 | REDIS_PORT=6379
25 |
26 | MAIL_MAILER=smtp
27 | MAIL_HOST=smtp.mailtrap.io
28 | MAIL_PORT=2525
29 | MAIL_USERNAME=null
30 | MAIL_PASSWORD=null
31 | MAIL_ENCRYPTION=null
32 | MAIL_FROM_ADDRESS=null
33 | MAIL_FROM_NAME="${APP_NAME}"
34 |
35 | AWS_ACCESS_KEY_ID=
36 | AWS_SECRET_ACCESS_KEY=
37 | AWS_DEFAULT_REGION=us-east-1
38 | AWS_BUCKET=
39 |
40 | PUSHER_APP_ID=
41 | PUSHER_APP_KEY=
42 | PUSHER_APP_SECRET=
43 | PUSHER_APP_CLUSTER=mt1
44 | SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1,localhost:8000,127.0.0.1:8000
45 |
46 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
47 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
48 |
49 | BASE_API=/api
50 | LARAVUE_USE_ESLINT=true
51 | LARAVUE_PATH=
52 | MIX_BASE_API="${BASE_API}"
53 | MIX_LARAVUE_PATH="${LARAVUE_PATH}"
54 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.css linguist-vendored
3 | *.scss linguist-vendored
4 | *.js linguist-vendored
5 | CHANGELOG.md export-ignore
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /public/hot
3 | /public/storage
4 | /storage/*.key
5 | /vendor
6 | .env
7 | .env.backup
8 | .phpunit.result.cache
9 | Homestead.json
10 | Homestead.yaml
11 | npm-debug.log
12 | yarn-error.log
13 | /public/js
14 | /public/css/*.css
15 | /public/css/*.map
16 | /public/css/*.gz
17 | /public/css/fonts/
18 | /public/images/*
19 | /public/images/*.gif
20 | /public/stats.html
21 | /public/*.js
22 | /public/*.js.map
23 | .idea
24 | .DS_Store
25 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | image: registry.gitlab.com/bacduong/laravue:latest
2 |
3 | services:
4 | - mysql:5.7
5 |
6 | variables:
7 | MYSQL_DATABASE: homestead
8 | MYSQL_ROOT_PASSWORD: secret
9 | DB_HOST: mysql
10 | DB_USERNAME: root
11 |
12 | stages:
13 | - test
14 | - deploy
15 |
16 | unit_test:
17 | stage: test
18 | script:
19 | - cp .env.example .env
20 | - composer install
21 | - php artisan key:generate
22 | - php artisan migrate
23 | - vendor/bin/phpunit
24 |
25 | deploy_staging:
26 | stage: deploy
27 | script:
28 | - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
29 | - eval $(ssh-agent -s)
30 | - ssh-add <(echo "$SSH_PRIVATE_KEY")
31 | - mkdir -p ~/.ssh
32 | - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
33 |
34 | - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
35 | environment:
36 | name: staging
37 | url: http://laravue.cipherpols.com
38 | when: on_success
39 | only:
40 | - master
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | // to edit target browsers: use "browserslist" field in package.json
6 | "autoprefixer": {}
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | singleQuote: true,
3 | semi: true,
4 | tabWidth: 2,
5 | trailingComma: 'es5',
6 | }
7 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | php:
2 | preset: laravel
3 | disabled:
4 | - unused_use
5 | finder:
6 | not-name:
7 | - index.php
8 | - server.php
9 | js:
10 | finder:
11 | not-name:
12 | - webpack.mix.js
13 | css: true
14 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Set the base image for subsequent instructions
2 | FROM php:7.3
3 |
4 | WORKDIR /var/www
5 |
6 | # Update packages
7 |
8 | RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - \
9 | && apt-get update \
10 | && apt-get install -y nodejs netcat libmcrypt-dev libjpeg-dev libpng-dev libzip-dev libfreetype6-dev libbz2-dev nodejs git \
11 | && apt-get clean
12 |
13 | # Install extensions
14 | RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
15 | RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
16 | RUN docker-php-ext-install gd
17 |
18 | # Install composer
19 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
20 |
21 | COPY . .
22 | COPY .env.example .env
23 |
24 | CMD ["bash", "./laravue-entrypoint.sh"]
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Tuan Duong
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 |
--------------------------------------------------------------------------------
/app/Console/Kernel.php:
--------------------------------------------------------------------------------
1 | command('inspire')->hourly();
28 | }
29 |
30 | /**
31 | * Register the commands for the application.
32 | *
33 | * @return void
34 | */
35 | protected function commands()
36 | {
37 | $this->load(__DIR__.'/Commands');
38 |
39 | require base_path('routes/console.php');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/Exceptions/Handler.php:
--------------------------------------------------------------------------------
1 |
6 | * @package Laravue
7 | * @version 1.0
8 | */
9 | namespace App\Http\Controllers\Api;
10 |
11 | use App\Http\Resources\UserResource;
12 | use App\Laravue\JsonResponse;
13 | use Illuminate\Http\Request;
14 | use Illuminate\Http\Response;
15 | use Illuminate\Support\Facades\Auth;
16 |
17 | /**
18 | * Class AuthController
19 | *
20 | * @package App\Http\Controllers\Api
21 | */
22 | class AuthController extends BaseController
23 | {
24 | /**
25 | * @param Request $request
26 | * @return \Illuminate\Http\JsonResponse
27 | */
28 | public function login(Request $request)
29 | {
30 | $credentials = $request->only('email', 'password');
31 | if (!Auth::attempt($credentials)) {
32 | return response()->json(new JsonResponse([], 'login_error'), Response::HTTP_UNAUTHORIZED);
33 | }
34 |
35 | $user = $request->user();
36 |
37 | return response()->json(new JsonResponse(new UserResource($user)), Response::HTTP_OK);
38 | }
39 |
40 | /**
41 | * @param Request $request
42 | * @return \Illuminate\Http\JsonResponse
43 | */
44 | public function logout(Request $request)
45 | {
46 | Auth::guard('web')->logout();
47 | return response()->json((new JsonResponse())->success([]), Response::HTTP_OK);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/BaseController.php:
--------------------------------------------------------------------------------
1 |
6 | * @package Laravue
7 | * @version 1.0
8 | */
9 | namespace App\Http\Controllers\Api;
10 |
11 | use App\Http\Controllers\Controller;
12 |
13 | /**
14 | * Class BaseController
15 | *
16 | * @package App\Http\Controllers\Api
17 | */
18 | class BaseController extends Controller
19 | {
20 | //
21 | }
22 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Controller.php:
--------------------------------------------------------------------------------
1 |
6 | * @package Laravue
7 | * @version 1.0
8 | */
9 |
10 | namespace App\Http\Controllers;
11 |
12 | /**
13 | * Class LaravueController
14 | *
15 | * @package App\Http\Controllers
16 | */
17 | class LaravueController extends Controller
18 | {
19 | /**
20 | * Entry point for Laravue Dashboard
21 | *
22 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
23 | */
24 | public function index()
25 | {
26 | return view('laravue');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/Http/Middleware/Authenticate.php:
--------------------------------------------------------------------------------
1 | expectsJson()) {
18 | return route('login');
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Http/Middleware/CheckForMaintenanceMode.php:
--------------------------------------------------------------------------------
1 | check()) {
22 | return redirect(RouteServiceProvider::HOME);
23 | }
24 |
25 | return $next($request);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/Http/Middleware/TrimStrings.php:
--------------------------------------------------------------------------------
1 | allSubdomainsOfApplicationUrl(),
18 | ];
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/Http/Middleware/TrustProxies.php:
--------------------------------------------------------------------------------
1 | $this->id,
19 | 'name' => $this->name,
20 | ];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Http/Resources/RoleResource.php:
--------------------------------------------------------------------------------
1 | $this->id,
19 | 'name' => $this->name,
20 | 'permissions' => PermissionResource::collection($this->permissions),
21 | ];
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/Http/Resources/UserResource.php:
--------------------------------------------------------------------------------
1 | $this->id,
19 | 'name' => $this->name,
20 | 'email' => $this->email,
21 | 'roles' => array_map(
22 | function ($role) {
23 | return $role['name'];
24 | },
25 | $this->roles->toArray()
26 | ),
27 | 'permissions' => array_map(
28 | function ($permission) {
29 | return $permission['name'];
30 | },
31 | $this->getAllPermissions()->toArray()
32 | ),
33 | 'avatar' => 'https://i.pravatar.cc',
34 | ];
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/Laravue/Models/Permission.php:
--------------------------------------------------------------------------------
1 |
6 | * @package Laravue
7 | * @version 1.0
8 | */
9 |
10 | namespace App\Laravue\Models;
11 | use App\Laravue\Acl;
12 | use Illuminate\Database\Query\Builder;
13 |
14 | /**
15 | * Class Permission
16 | *
17 | * @package App\Laravue\Models
18 | */
19 | class Permission extends \Spatie\Permission\Models\Permission
20 | {
21 | public $guard_name = 'api';
22 |
23 | /**
24 | * To exclude permission management from the list
25 | *
26 | * @param $query
27 | * @return Builder
28 | */
29 | public function scopeAllowed($query)
30 | {
31 | return $query->where('name', '!=', Acl::PERMISSION_PERMISSION_MANAGE);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Laravue/Models/Role.php:
--------------------------------------------------------------------------------
1 |
6 | * @package Laravue
7 | * @version
8 | */
9 | namespace App\Laravue\Models;
10 |
11 | use App\Laravue\Acl;
12 | use Spatie\Permission\Models\Permission;
13 |
14 | /**
15 | * Class Role
16 | *
17 | * @property Permission[] $permissions
18 | * @property string $name
19 | * @package App\Laravue\Models
20 | */
21 | class Role extends \Spatie\Permission\Models\Role
22 | {
23 | public $guard_name = 'api';
24 |
25 | /**
26 | * Check whether current role is admin
27 | * @return bool
28 | */
29 | public function isAdmin(): bool
30 | {
31 | return $this->name === Acl::ROLE_ADMIN;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Providers/AppServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'App\Policies\ModelPolicy',
17 | ];
18 |
19 | /**
20 | * Register any authentication / authorization services.
21 | *
22 | * @return void
23 | */
24 | public function boot()
25 | {
26 | $this->registerPolicies();
27 |
28 | //
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/Providers/BroadcastServiceProvider.php:
--------------------------------------------------------------------------------
1 | [
19 | SendEmailVerificationNotification::class,
20 | ],
21 | ];
22 |
23 | /**
24 | * Register any events for your application.
25 | *
26 | * @return void
27 | */
28 | public function boot()
29 | {
30 | parent::boot();
31 |
32 | //
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/User.php:
--------------------------------------------------------------------------------
1 | 'datetime',
38 | ];
39 | }
40 |
--------------------------------------------------------------------------------
/bootstrap/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/config/cors.php:
--------------------------------------------------------------------------------
1 | [
19 | 'api/*'
20 | ],
21 |
22 | 'allowed_methods' => ['*'],
23 |
24 | 'allowed_origins' => ['*'],
25 |
26 | 'allowed_origins_patterns' => [],
27 |
28 | 'allowed_headers' => ['*'],
29 |
30 | 'exposed_headers' => [],
31 |
32 | 'max_age' => 0,
33 |
34 | 'supports_credentials' => true,
35 |
36 | ];
37 |
--------------------------------------------------------------------------------
/config/services.php:
--------------------------------------------------------------------------------
1 | [
18 | 'domain' => env('MAILGUN_DOMAIN'),
19 | 'secret' => env('MAILGUN_SECRET'),
20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
21 | ],
22 |
23 | 'postmark' => [
24 | 'token' => env('POSTMARK_TOKEN'),
25 | ],
26 |
27 | 'ses' => [
28 | 'key' => env('AWS_ACCESS_KEY_ID'),
29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
31 | ],
32 |
33 | ];
34 |
--------------------------------------------------------------------------------
/config/view.php:
--------------------------------------------------------------------------------
1 | [
17 | resource_path('views'),
18 | ],
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Compiled View Path
23 | |--------------------------------------------------------------------------
24 | |
25 | | This option determines where all the compiled Blade templates will be
26 | | stored for your application. Typically, this is within the storage
27 | | directory. However, as usual, you are free to change this value.
28 | |
29 | */
30 |
31 | 'compiled' => env(
32 | 'VIEW_COMPILED_PATH',
33 | realpath(storage_path('framework/views'))
34 | ),
35 |
36 | ];
37 |
--------------------------------------------------------------------------------
/database/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite
2 | *.sqlite-journal
3 |
--------------------------------------------------------------------------------
/database/factories/UserFactory.php:
--------------------------------------------------------------------------------
1 | define(User::class, function (Faker $faker) {
21 | return [
22 | 'name' => $faker->name,
23 | 'email' => $faker->unique()->safeEmail,
24 | 'email_verified_at' => now(),
25 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
26 | 'remember_token' => Str::random(10),
27 | ];
28 | });
29 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->string('name');
19 | $table->string('email')->unique();
20 | $table->timestamp('email_verified_at')->nullable();
21 | $table->string('password');
22 | $table->rememberToken();
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('users');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_100000_create_password_resets_table.php:
--------------------------------------------------------------------------------
1 | string('email')->index();
18 | $table->string('token');
19 | $table->timestamp('created_at')->nullable();
20 | });
21 | }
22 |
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down()
29 | {
30 | Schema::dropIfExists('password_resets');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/database/migrations/2019_03_16_102314_add_simple_role_to_user_table.php:
--------------------------------------------------------------------------------
1 | string('role')->default('editor');
19 | });
20 | }
21 | }
22 |
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down()
29 | {
30 | Schema::table('users', function (Blueprint $table) {
31 | $table->dropColumn('role');
32 | });
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/database/migrations/2019_08_19_000000_create_failed_jobs_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->text('connection');
19 | $table->text('queue');
20 | $table->longText('payload');
21 | $table->longText('exception');
22 | $table->timestamp('failed_at')->useCurrent();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('failed_jobs');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->morphs('tokenable');
19 | $table->string('name');
20 | $table->string('token', 64)->unique();
21 | $table->text('abilities')->nullable();
22 | $table->timestamp('last_used_at')->nullable();
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('personal_access_tokens');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/migrations/2020_03_25_170854_remove_passport.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | ./tests/Unit
10 |
11 |
12 | ./tests/Feature
13 |
14 |
15 |
16 |
17 | ./app
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/public/.gitignore:
--------------------------------------------------------------------------------
1 | mix-manifest.json
2 |
--------------------------------------------------------------------------------
/public/.htaccess:
--------------------------------------------------------------------------------
1 |
2 |
3 | Options -MultiViews -Indexes
4 |
5 |
6 | RewriteEngine On
7 |
8 | # Handle Authorization Header
9 | RewriteCond %{HTTP:Authorization} .
10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
11 |
12 | # Redirect Trailing Slashes If Not A Folder...
13 | RewriteCond %{REQUEST_FILENAME} !-d
14 | RewriteCond %{REQUEST_URI} (.+)/$
15 | RewriteRule ^ %1 [L,R=301]
16 |
17 | # Send Requests To Front Controller...
18 | RewriteCond %{REQUEST_FILENAME} !-d
19 | RewriteCond %{REQUEST_FILENAME} !-f
20 | RewriteRule ^ index.php [L]
21 |
22 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon.ico
--------------------------------------------------------------------------------
/public/favicon/android-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/android-icon-144x144.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/android-icon-192x192.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/android-icon-36x36.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/android-icon-48x48.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/android-icon-72x72.png
--------------------------------------------------------------------------------
/public/favicon/android-icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/android-icon-96x96.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-114x114.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-120x120.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-144x144.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-152x152.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-180x180.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-57x57.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-60x60.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-72x72.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-76x76.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon-precomposed.png
--------------------------------------------------------------------------------
/public/favicon/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/apple-icon.png
--------------------------------------------------------------------------------
/public/favicon/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 | #ffffff
--------------------------------------------------------------------------------
/public/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/public/favicon/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/favicon-96x96.png
--------------------------------------------------------------------------------
/public/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/favicon.ico
--------------------------------------------------------------------------------
/public/favicon/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Laravue",
3 | "icons": [
4 | {
5 | "src": "\/favicon/android-icon-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image\/png",
8 | "density": "0.75"
9 | },
10 | {
11 | "src": "\/favicon/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image\/png",
14 | "density": "1.0"
15 | },
16 | {
17 | "src": "\/favicon/android-icon-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image\/png",
20 | "density": "1.5"
21 | },
22 | {
23 | "src": "\/favicon/android-icon-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image\/png",
26 | "density": "2.0"
27 | },
28 | {
29 | "src": "\/favicon/android-icon-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image\/png",
32 | "density": "3.0"
33 | },
34 | {
35 | "src": "\/favicon/android-icon-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image\/png",
38 | "density": "4.0"
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/public/favicon/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/ms-icon-144x144.png
--------------------------------------------------------------------------------
/public/favicon/ms-icon-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/ms-icon-150x150.png
--------------------------------------------------------------------------------
/public/favicon/ms-icon-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/ms-icon-310x310.png
--------------------------------------------------------------------------------
/public/favicon/ms-icon-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/favicon/ms-icon-70x70.png
--------------------------------------------------------------------------------
/public/images/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
5 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cool.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cool.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cry.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-cry.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-embarassed.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-embarassed.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-foot-in-mouth.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-foot-in-mouth.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-frown.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-frown.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-innocent.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-innocent.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-kiss.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-kiss.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-laughing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-laughing.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-money-mouth.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-money-mouth.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-sealed.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-sealed.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-smile.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-smile.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-surprised.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-surprised.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-tongue-out.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-tongue-out.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-undecided.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-undecided.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-wink.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-wink.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-yell.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/plugins/emoticons/img/smiley-yell.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-mobile.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-mobile.woff
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.eot
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.ttf
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.woff
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.eot
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.ttf
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/fonts/tinymce.woff
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/img/anchor.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/img/anchor.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/img/loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/img/loader.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/img/object.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/img/object.gif
--------------------------------------------------------------------------------
/public/static/tinymce4.7.5/skins/lightgray/img/trans.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/public/static/tinymce4.7.5/skins/lightgray/img/trans.gif
--------------------------------------------------------------------------------
/public/web.config:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/resources/js/api/article.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | export function fetchList(query) {
4 | return request({
5 | url: '/articles',
6 | method: 'get',
7 | params: query,
8 | });
9 | }
10 |
11 | export function fetchArticle(id) {
12 | return request({
13 | url: '/articles/' + id,
14 | method: 'get',
15 | });
16 | }
17 |
18 | export function fetchPv(id) {
19 | return request({
20 | url: '/articles/' + id + '/pageviews',
21 | method: 'get',
22 | });
23 | }
24 |
25 | export function createArticle(data) {
26 | return request({
27 | url: '/article/create',
28 | method: 'post',
29 | data,
30 | });
31 | }
32 |
33 | export function updateArticle(data) {
34 | return request({
35 | url: '/article/update',
36 | method: 'post',
37 | data,
38 | });
39 | }
40 |
--------------------------------------------------------------------------------
/resources/js/api/auth.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | export function login(data) {
4 | return request({
5 | url: '/auth/login',
6 | method: 'post',
7 | data: data,
8 | });
9 | }
10 |
11 | export function getInfo(token) {
12 | return request({
13 | url: '/user',
14 | method: 'get',
15 | });
16 | }
17 |
18 | export function logout() {
19 | return request({
20 | url: '/auth/logout',
21 | method: 'post',
22 | });
23 | }
24 |
25 | export function csrf() {
26 | return request({
27 | url: '/sanctum/csrf-cookie',
28 | method: 'get',
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/resources/js/api/order.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | export function fetchList(query) {
4 | return request({
5 | url: '/orders',
6 | method: 'get',
7 | params: query,
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/resources/js/api/resource.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | /**
4 | * Simple RESTful resource class
5 | */
6 | class Resource {
7 | constructor(uri) {
8 | this.uri = uri;
9 | }
10 | list(query) {
11 | return request({
12 | url: '/' + this.uri,
13 | method: 'get',
14 | params: query,
15 | });
16 | }
17 | get(id) {
18 | return request({
19 | url: '/' + this.uri + '/' + id,
20 | method: 'get',
21 | });
22 | }
23 | store(resource) {
24 | return request({
25 | url: '/' + this.uri,
26 | method: 'post',
27 | data: resource,
28 | });
29 | }
30 | update(id, resource) {
31 | return request({
32 | url: '/' + this.uri + '/' + id,
33 | method: 'put',
34 | data: resource,
35 | });
36 | }
37 | destroy(id) {
38 | return request({
39 | url: '/' + this.uri + '/' + id,
40 | method: 'delete',
41 | });
42 | }
43 | }
44 |
45 | export { Resource as default };
46 |
--------------------------------------------------------------------------------
/resources/js/api/role.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 | import Resource from '@/api/resource';
3 |
4 | class RoleResource extends Resource {
5 | constructor() {
6 | super('roles');
7 | }
8 |
9 | permissions(id) {
10 | return request({
11 | url: '/' + this.uri + '/' + id + '/permissions',
12 | method: 'get',
13 | });
14 | }
15 | }
16 |
17 | export { RoleResource as default };
18 |
--------------------------------------------------------------------------------
/resources/js/api/search.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | export function userSearch(name) {
4 | return request({
5 | url: '/search/user',
6 | method: 'get',
7 | params: { name },
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/resources/js/api/user.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 | import Resource from '@/api/resource';
3 |
4 | class UserResource extends Resource {
5 | constructor() {
6 | super('users');
7 | }
8 |
9 | permissions(id) {
10 | return request({
11 | url: '/' + this.uri + '/' + id + '/permissions',
12 | method: 'get',
13 | });
14 | }
15 |
16 | updatePermission(id, permissions) {
17 | return request({
18 | url: '/' + this.uri + '/' + id + '/permissions',
19 | method: 'put',
20 | data: permissions,
21 | });
22 | }
23 | }
24 |
25 | export { UserResource as default };
26 |
--------------------------------------------------------------------------------
/resources/js/app.js:
--------------------------------------------------------------------------------
1 | import '@/styles/index.scss';
2 | import 'core-js';
3 | import Vue from 'vue';
4 | import Cookies from 'js-cookie';
5 | import ElementUI from 'element-ui';
6 | import App from './views/App';
7 | import store from './store';
8 | import router from '@/router';
9 | import i18n from './lang'; // Internationalization
10 | import '@/icons'; // icon
11 | import '@/permission'; // permission control
12 |
13 | import * as filters from './filters'; // global filters
14 |
15 | Vue.use(ElementUI, {
16 | size: Cookies.get('size') || 'medium', // set element-ui default size
17 | i18n: (key, value) => i18n.t(key, value),
18 | });
19 |
20 | // register global utility filters.
21 | Object.keys(filters).forEach(key => {
22 | Vue.filter(key, filters[key]);
23 | });
24 |
25 | Vue.config.productionTip = false;
26 |
27 | new Vue({
28 | el: '#app',
29 | router,
30 | store,
31 | i18n,
32 | render: h => h(App),
33 | });
34 |
--------------------------------------------------------------------------------
/resources/js/assets/401_images/401.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/resources/js/assets/401_images/401.gif
--------------------------------------------------------------------------------
/resources/js/assets/404_images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/resources/js/assets/404_images/404.png
--------------------------------------------------------------------------------
/resources/js/assets/404_images/404_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/resources/js/assets/404_images/404_cloud.png
--------------------------------------------------------------------------------
/resources/js/assets/custom-theme/fonts/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/resources/js/assets/custom-theme/fonts/element-icons.ttf
--------------------------------------------------------------------------------
/resources/js/assets/custom-theme/fonts/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/resources/js/assets/custom-theme/fonts/element-icons.woff
--------------------------------------------------------------------------------
/resources/js/assets/login/login_background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/resources/js/assets/login/login_background.jpg
--------------------------------------------------------------------------------
/resources/js/assets/login/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuandm/laravue/b56ec7526e47f06a37ca79cc356f545fcef21f34/resources/js/assets/login/logo.png
--------------------------------------------------------------------------------
/resources/js/bootstrap.js:
--------------------------------------------------------------------------------
1 | window._ = require('lodash');
2 |
3 | /**
4 | * We'll load the axios HTTP library which allows us to easily issue requests
5 | * to our Laravel back-end. This library automatically handles sending the
6 | * CSRF token as a header based on the value of the "XSRF" token cookie.
7 | */
8 |
9 | window.axios = require('axios');
10 |
11 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
12 | window.axios.defaults.withCredentials = true;
13 |
14 | /**
15 | * Echo exposes an expressive API for subscribing to channels and listening
16 | * for events that are broadcast by Laravel. Echo and event broadcasting
17 | * allows your team to easily build robust real-time web applications.
18 | */
19 |
20 | // import Echo from 'laravel-echo';
21 |
22 | // window.Pusher = require('pusher-js');
23 |
24 | // window.Echo = new Echo({
25 | // broadcaster: 'pusher',
26 | // key: process.env.MIX_PUSHER_APP_KEY,
27 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER,
28 | // forceTLS: true
29 | // });
30 |
--------------------------------------------------------------------------------
/resources/js/components/Charts/mixins/resize.js:
--------------------------------------------------------------------------------
1 | import { debounce } from '@/utils';
2 |
3 | export default {
4 | data() {
5 | return {
6 | sidebarElm: null,
7 | };
8 | },
9 | mounted() {
10 | this.__resizeHandler = debounce(() => {
11 | if (this.chart) {
12 | this.chart.resize();
13 | }
14 | }, 100);
15 | window.addEventListener('resize', this.__resizeHandler);
16 |
17 | this.sidebarElm = document.getElementsByClassName('sidebar-container')[0];
18 | this.sidebarElm && this.sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler);
19 | },
20 | beforeDestroy() {
21 | window.removeEventListener('resize', this.__resizeHandler);
22 |
23 | this.sidebarElm && this.sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler);
24 | },
25 | methods: {
26 | sidebarResizeHandler(e) {
27 | if (e.propertyName === 'width') {
28 | this.__resizeHandler();
29 | }
30 | },
31 | },
32 | };
33 |
--------------------------------------------------------------------------------
/resources/js/components/DragSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
48 |
49 |
60 |
--------------------------------------------------------------------------------
/resources/js/components/ExampleComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 | I'm an example component.
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
26 |
--------------------------------------------------------------------------------
/resources/js/components/Hamburger/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
32 |
33 |
45 |
--------------------------------------------------------------------------------
/resources/js/components/ImageCropper/utils/data2blob.js:
--------------------------------------------------------------------------------
1 | /**
2 | * database64文件格式转换为2进制
3 | *
4 | * @param {[String]} data The format of the dataURL is "data:image/png;base64,****". The comma is preceded by some descriptive text. We only need the comma after the line.
5 | * @param {[String]} mime [description]
6 | * @return {[blob]} [description]
7 | */
8 | export default function(data, mime) {
9 | data = data.split(',')[1];
10 | data = window.atob(data);
11 | var ia = new Uint8Array(data.length);
12 | for (var i = 0; i < data.length; i++) {
13 | ia[i] = data.charCodeAt(i);
14 | }
15 | // The default format returned by canvas.toDataURL is image/png
16 | return new Blob([ia], {
17 | type: mime,
18 | });
19 | }
20 |
--------------------------------------------------------------------------------
/resources/js/components/ImageCropper/utils/effect-ripple.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Click ripple effect
3 | *
4 | * @param {[event]} e [description]
5 | * @param {[Object]} argOpts [description]
6 | * @return {[bollean]} [description]
7 | */
8 | export default function(e, argOpts) {
9 | var opts = Object.assign({
10 | ele: e.target, // Corrugated element
11 | type: 'hit', // Hit click position spread center center point expansion
12 | bgc: 'rgba(0, 0, 0, 0.15)', // Ripple color
13 | }, argOpts);
14 | var target = opts.ele;
15 | if (target) {
16 | var rect = target.getBoundingClientRect();
17 | var ripple = target.querySelector('.e-ripple');
18 | if (!ripple) {
19 | ripple = document.createElement('span');
20 | ripple.className = 'e-ripple';
21 | ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px';
22 | target.appendChild(ripple);
23 | } else {
24 | ripple.className = 'e-ripple';
25 | }
26 | switch (opts.type) {
27 | case 'center':
28 | ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px';
29 | ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px';
30 | break;
31 | default:
32 | ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px';
33 | ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px';
34 | }
35 | ripple.style.backgroundColor = opts.bgc;
36 | ripple.className = 'e-ripple z-active';
37 | return false;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/resources/js/components/ImageCropper/utils/mimes.js:
--------------------------------------------------------------------------------
1 | export default {
2 | 'jpg': 'image/jpeg',
3 | 'png': 'image/png',
4 | 'gif': 'image/gif',
5 | 'svg': 'image/svg+xml',
6 | 'psd': 'image/photoshop',
7 | };
8 |
--------------------------------------------------------------------------------
/resources/js/components/LangSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Tiếng Việt
9 |
10 |
11 | English
12 |
13 |
14 | 中文
15 |
16 |
17 | Русский
18 |
19 |
20 |
21 |
22 |
23 |
42 |
43 |
50 |
51 |
--------------------------------------------------------------------------------
/resources/js/components/MarkdownEditor/default-options.js:
--------------------------------------------------------------------------------
1 | // doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
2 | export default {
3 | minHeight: '200px',
4 | previewStyle: 'vertical',
5 | useCommandShortcut: true,
6 | useDefaultHTMLSanitizer: true,
7 | usageStatistics: false,
8 | hideModeSwitch: false,
9 | toolbarItems: [
10 | 'heading',
11 | 'bold',
12 | 'italic',
13 | 'strike',
14 | 'divider',
15 | 'hr',
16 | 'quote',
17 | 'divider',
18 | 'ul',
19 | 'ol',
20 | 'task',
21 | 'indent',
22 | 'outdent',
23 | 'divider',
24 | 'table',
25 | 'image',
26 | 'link',
27 | 'divider',
28 | 'code',
29 | 'codeblock',
30 | ],
31 | };
32 |
--------------------------------------------------------------------------------
/resources/js/components/Screenfull/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
41 |
42 |
52 |
--------------------------------------------------------------------------------
/resources/js/components/SizeSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ item.label }}
9 |
10 |
11 |
12 |
13 |
14 |
56 |
--------------------------------------------------------------------------------
/resources/js/components/SvgIcon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
34 |
35 |
44 |
--------------------------------------------------------------------------------
/resources/js/components/Tinymce/plugins.js:
--------------------------------------------------------------------------------
1 | // Any plugins you want to use has to be imported
2 | // Detail plugins list see https://www.tinymce.com/docs/plugins/
3 | // Custom builds see https://www.tinymce.com/download/custom-builds/
4 |
5 | const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount'];
6 |
7 | export default plugins;
8 |
--------------------------------------------------------------------------------
/resources/js/components/Tinymce/toolbar.js:
--------------------------------------------------------------------------------
1 | // Here is a list of the toolbar
2 | // Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
3 |
4 | const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'];
5 |
6 | export default toolbar;
7 |
--------------------------------------------------------------------------------
/resources/js/directive/clipboard/index.js:
--------------------------------------------------------------------------------
1 | import Clipboard from './clipboard';
2 |
3 | const install = function(Vue) {
4 | Vue.directive('Clipboard', Clipboard);
5 | };
6 |
7 | if (window.Vue) {
8 | window.clipboard = Clipboard;
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | Clipboard.install = install;
13 | export default Clipboard;
14 |
--------------------------------------------------------------------------------
/resources/js/directive/el-drag-dialog/index.js:
--------------------------------------------------------------------------------
1 | import drag from './drag';
2 |
3 | const install = function(Vue) {
4 | Vue.directive('el-drag-dialog', drag);
5 | };
6 |
7 | if (window.Vue) {
8 | window['el-drag-dialog'] = drag;
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | drag.install = install;
13 | export default drag;
14 |
--------------------------------------------------------------------------------
/resources/js/directive/el-table/adaptive.js:
--------------------------------------------------------------------------------
1 |
2 | import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
3 |
4 | /**
5 | * How to use
6 | * ...
7 | * el-table height is must be set
8 | * bottomOffset: 30(default) // The height of the table from the bottom of the page.
9 | */
10 |
11 | const doResize = (el, binding, vnode) => {
12 | const { componentInstance: $table } = vnode;
13 |
14 | const { value } = binding;
15 |
16 | if (!$table.height) {
17 | throw new Error(`el-$table must set the height. Such as height='100px'`);
18 | }
19 | const bottomOffset = (value && value.bottomOffset) || 30;
20 |
21 | if (!$table) {
22 | return;
23 | }
24 |
25 | const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset;
26 | $table.layout.setHeight(height);
27 | $table.doLayout();
28 | };
29 |
30 | export default {
31 | bind(el, binding, vnode) {
32 | el.resizeListener = () => {
33 | doResize(el, binding, vnode);
34 | };
35 |
36 | addResizeListener(el, el.resizeListener);
37 | },
38 | inserted(el, binding, vnode) {
39 | doResize(el, binding, vnode);
40 | },
41 | unbind(el) {
42 | removeResizeListener(el, el.resizeListener);
43 | },
44 | };
45 |
--------------------------------------------------------------------------------
/resources/js/directive/el-table/index.js:
--------------------------------------------------------------------------------
1 |
2 | import adaptive from './adaptive';
3 |
4 | const install = function(Vue) {
5 | Vue.directive('el-height-adaptive-table', adaptive);
6 | };
7 |
8 | if (window.Vue) {
9 | window['el-height-adaptive-table'] = adaptive;
10 | Vue.use(install); // eslint-disable-line
11 | }
12 |
13 | adaptive.install = install;
14 | export default adaptive;
15 |
--------------------------------------------------------------------------------
/resources/js/directive/permission/index.js:
--------------------------------------------------------------------------------
1 | import permission from './permission';
2 |
3 | const install = function(Vue) {
4 | Vue.directive('permission', permission);
5 | };
6 |
7 | if (window.Vue) {
8 | window['permission'] = permission;
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | permission.install = install;
13 | export default permission;
14 |
--------------------------------------------------------------------------------
/resources/js/directive/permission/permission.js:
--------------------------------------------------------------------------------
1 | import store from '@/store';
2 |
3 | export default {
4 | inserted(el, binding, vnode) {
5 | const { value } = binding;
6 | const permissions = store.getters && store.getters.permissions;
7 |
8 | if (value && value instanceof Array && value.length > 0) {
9 | const requiredPermissions = value;
10 | const hasPermission = permissions.some(permission => {
11 | return requiredPermissions.includes(permission);
12 | });
13 |
14 | if (!hasPermission) {
15 | el.parentNode && el.parentNode.removeChild(el);
16 | }
17 | } else {
18 | throw new Error(`Permissions are required! Example: v-permission="['manage user','manage permission']"`);
19 | }
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/resources/js/directive/role/index.js:
--------------------------------------------------------------------------------
1 | import role from './role';
2 |
3 | const install = function(Vue) {
4 | Vue.directive('role', role);
5 | };
6 |
7 | if (window.Vue) {
8 | window['role'] = role;
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | role.install = install;
13 | export default role;
14 |
--------------------------------------------------------------------------------
/resources/js/directive/role/role.js:
--------------------------------------------------------------------------------
1 | import store from '@/store';
2 |
3 | export default {
4 | inserted(el, binding, vnode) {
5 | const { value } = binding;
6 | const roles = store.getters && store.getters.roles;
7 |
8 | if (value && value instanceof Array && value.length > 0) {
9 | const requiredRoles = value;
10 | const hasRole = roles.some(role => {
11 | return requiredRoles.includes(role);
12 | });
13 |
14 | if (!hasRole) {
15 | el.parentNode && el.parentNode.removeChild(el);
16 | }
17 | } else {
18 | throw new Error(`Roles are required! Example: v-role="['admin','editor']"`);
19 | }
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/resources/js/directive/waves/index.js:
--------------------------------------------------------------------------------
1 | import waves from './waves';
2 |
3 | const install = function(Vue) {
4 | Vue.directive('waves', waves);
5 | };
6 |
7 | if (window.Vue) {
8 | window.waves = waves;
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | waves.install = install;
13 | export default waves;
14 |
--------------------------------------------------------------------------------
/resources/js/directive/waves/waves.css:
--------------------------------------------------------------------------------
1 | .waves-ripple {
2 | position: absolute;
3 | border-radius: 100%;
4 | background-color: rgba(0, 0, 0, 0.15);
5 | background-clip: padding-box;
6 | pointer-events: none;
7 | -webkit-user-select: none;
8 | -moz-user-select: none;
9 | -ms-user-select: none;
10 | user-select: none;
11 | -webkit-transform: scale(0);
12 | -ms-transform: scale(0);
13 | transform: scale(0);
14 | opacity: 1;
15 | }
16 |
17 | .waves-ripple.z-active {
18 | opacity: 0;
19 | -webkit-transform: scale(2);
20 | -ms-transform: scale(2);
21 | transform: scale(2);
22 | -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
23 | transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
24 | transition: opacity 1.2s ease-out, transform 0.6s ease-out;
25 | transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
26 | }
--------------------------------------------------------------------------------
/resources/js/filters/index.js:
--------------------------------------------------------------------------------
1 | // set function parseTime,formatTime to filter
2 | export { parseTime, formatTime } from '@/utils';
3 |
4 | export function pluralize(time, label) {
5 | if (time === 1) {
6 | return time + label;
7 | }
8 | return time + label + 's';
9 | }
10 |
11 | export function timeAgo(time) {
12 | const between = Date.now() / 1000 - Number(time);
13 | if (between < 3600) {
14 | return pluralize(~~(between / 60), ' minute');
15 | } else if (between < 86400) {
16 | return pluralize(~~(between / 3600), ' hour');
17 | } else {
18 | return pluralize(~~(between / 86400), ' day');
19 | }
20 | }
21 |
22 | /* Number formating*/
23 | export function numberFormatter(num, digits) {
24 | const si = [
25 | { value: 1E18, symbol: 'E' },
26 | { value: 1E15, symbol: 'P' },
27 | { value: 1E12, symbol: 'T' },
28 | { value: 1E9, symbol: 'G' },
29 | { value: 1E6, symbol: 'M' },
30 | { value: 1E3, symbol: 'k' },
31 | ];
32 | for (let i = 0; i < si.length; i++) {
33 | if (num >= si[i].value) {
34 | return (num / si[i].value + 0.1).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol;
35 | }
36 | }
37 | return num.toString();
38 | }
39 |
40 | export function toThousandFilter(num) {
41 | return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','));
42 | }
43 |
44 | export function uppercaseFirst(string) {
45 | return string.charAt(0).toUpperCase() + string.slice(1);
46 | }
47 |
--------------------------------------------------------------------------------
/resources/js/icons/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import SvgIcon from '@/components/SvgIcon';
3 |
4 | // register globally
5 | // eslint-disable-next-line vue/component-definition-name-casing
6 | Vue.component('svg-icon', SvgIcon);
7 |
8 | const requireAll = requireContext => requireContext.keys().map(requireContext);
9 | const req = require.context('./svg', false, /\.svg$/);
10 | requireAll(req);
11 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/404.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/bug.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/clipboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/comment.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/component.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/create-user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/documentation.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/drag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/education.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/email.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/example.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/excel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/eye-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/fullscreen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/guide 2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/guide.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/international.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/language.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/layout.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/like.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/list.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/lock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/money.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/nested.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/password.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/pdf.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/people.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/peoples.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/role.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/size.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/skill.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/star.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/tab.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/theme.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/tree-table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/wechat.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svg/zip.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/js/icons/svgo.yml:
--------------------------------------------------------------------------------
1 | # replace default config
2 |
3 | # multipass: true
4 | # full: true
5 |
6 | plugins:
7 |
8 | # - name
9 | #
10 | # or:
11 | # - name: false
12 | # - name: true
13 | #
14 | # or:
15 | # - name:
16 | # param1: 1
17 | # param2: 2
18 |
19 | - removeAttrs:
20 | attrs:
21 | - 'fill'
22 | - 'fill-rule'
23 |
--------------------------------------------------------------------------------
/resources/js/lang/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VueI18n from 'vue-i18n';
3 | import Cookies from 'js-cookie';
4 | import elementEnLocale from 'element-ui/lib/locale/lang/en'; // element-ui lang
5 | import elementRuLocale from 'element-ui/lib/locale/lang/ru-RU'; // element-ui lang
6 | import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN';// element-ui lang
7 | import elementViLocale from 'element-ui/lib/locale/lang/vi';// element-ui lang
8 | import enLocale from './en';
9 | import ruLocale from './ru';
10 | import zhLocale from './zh';
11 | import viLocale from './vi';
12 |
13 | Vue.use(VueI18n);
14 |
15 | const messages = {
16 | en: {
17 | ...enLocale,
18 | ...elementEnLocale,
19 | },
20 | ru: {
21 | ...ruLocale,
22 | ...elementRuLocale,
23 | },
24 | zh: {
25 | ...zhLocale,
26 | ...elementZhLocale,
27 | },
28 | vi: {
29 | ...viLocale,
30 | ...elementViLocale,
31 | },
32 | };
33 |
34 | export function getLanguage() {
35 | const chooseLanguage = Cookies.get('language');
36 | if (chooseLanguage) {
37 | return chooseLanguage;
38 | }
39 |
40 | // if has not choose language
41 | const language = (navigator.language || navigator.browserLanguage).toLowerCase();
42 | const locales = Object.keys(messages);
43 | for (const locale of locales) {
44 | if (language.indexOf(locale) > -1) {
45 | return locale;
46 | }
47 | }
48 | return 'en';
49 | }
50 | const i18n = new VueI18n({
51 | // set locale
52 | // options: en | ru | vi | zh
53 | locale: getLanguage(),
54 | // set locale messages
55 | messages,
56 | });
57 |
58 | export default i18n;
59 |
--------------------------------------------------------------------------------
/resources/js/layout/components/AppMain.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
24 |
25 |
49 |
50 |
--------------------------------------------------------------------------------
/resources/js/layout/components/Sidebar/Item.vue:
--------------------------------------------------------------------------------
1 |
32 |
33 |
38 |
--------------------------------------------------------------------------------
/resources/js/layout/components/Sidebar/Link.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
40 |
--------------------------------------------------------------------------------
/resources/js/layout/components/Sidebar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
51 |
54 |
--------------------------------------------------------------------------------
/resources/js/layout/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as Navbar } from './Navbar';
2 | export { default as Sidebar } from './Sidebar';
3 | export { default as AppMain } from './AppMain';
4 | export { default as TagsView } from './TagsView';
5 | export { default as Settings } from './Settings';
6 |
--------------------------------------------------------------------------------
/resources/js/layout/mixin/resize-handler.js:
--------------------------------------------------------------------------------
1 | import store from '@/store';
2 |
3 | const { body } = document;
4 | const WIDTH = 992; // refer to Bootstrap's responsive design
5 |
6 | export default {
7 | watch: {
8 | $route(route) {
9 | if (this.device === 'mobile' && this.sidebar.opened) {
10 | store.dispatch('app/closeSideBar', { withoutAnimation: false });
11 | }
12 | },
13 | },
14 | beforeMount() {
15 | window.addEventListener('resize', this.resizeHandler);
16 | },
17 | beforeDestroy() {
18 | window.removeEventListener('resize', this.resizeHandler);
19 | },
20 | mounted() {
21 | const isMobile = this.isMobile();
22 | if (isMobile) {
23 | store.dispatch('app/toggleDevice', 'mobile');
24 | store.dispatch('app/closeSideBar', { withoutAnimation: true });
25 | }
26 | },
27 | methods: {
28 | isMobile() {
29 | const rect = body.getBoundingClientRect();
30 | return rect.width - 1 < WIDTH;
31 | },
32 | resizeHandler() {
33 | if (!document.hidden) {
34 | const isMobile = this.isMobile();
35 | store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop');
36 |
37 | if (isMobile) {
38 | store.dispatch('app/closeSideBar', { withoutAnimation: true });
39 | }
40 | }
41 | },
42 | },
43 | };
44 |
--------------------------------------------------------------------------------
/resources/js/router/modules/charts.js:
--------------------------------------------------------------------------------
1 | /** When your routing table is too long, you can split it into small modules**/
2 | import Layout from '@/layout';
3 |
4 | const chartsRoutes = {
5 | path: '/charts',
6 | component: Layout,
7 | redirect: 'noredirect',
8 | name: 'Charts',
9 | meta: {
10 | title: 'charts',
11 | icon: 'chart',
12 | permissions: ['view menu charts'],
13 | },
14 | children: [
15 | {
16 | path: 'keyboard',
17 | component: () => import('@/views/charts/Keyboard'),
18 | name: 'KeyboardChart',
19 | meta: { title: 'keyboardChart', noCache: true },
20 | },
21 | {
22 | path: 'line',
23 | component: () => import('@/views/charts/Line'),
24 | name: 'LineChart',
25 | meta: { title: 'lineChart', noCache: true },
26 | },
27 | {
28 | path: 'mixchart',
29 | component: () => import('@/views/charts/MixChart'),
30 | name: 'MixChart',
31 | meta: { title: 'mixChart', noCache: true },
32 | },
33 | ],
34 | };
35 |
36 | export default chartsRoutes;
37 |
--------------------------------------------------------------------------------
/resources/js/router/modules/element-ui.js:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout';
2 |
3 | const elementUiRoutes = {
4 | path: '/element-ui',
5 | component: Layout,
6 | redirect: '/element-ui/form',
7 | name: 'Element UI',
8 | meta: {
9 | title: 'elementUi',
10 | icon: 'layout',
11 | permissions: ['view menu element ui'],
12 | },
13 | children: [
14 | {
15 | path: 'form',
16 | name: 'Form',
17 | component: () => import('@/views/form/index'),
18 | meta: { title: 'form', icon: 'form' },
19 | },
20 | {
21 | path: 'icons',
22 | component: () => import('@/views/icons/index'),
23 | name: 'Icons',
24 | meta: { title: 'icons', icon: 'el-icon-info', noCache: true },
25 | },
26 | {
27 | path: 'tab',
28 | component: () => import('@/views/tab'),
29 | name: 'Tab',
30 | meta: { title: 'tab', icon: 'tab' },
31 | },
32 | ],
33 | };
34 |
35 | export default elementUiRoutes;
36 |
--------------------------------------------------------------------------------
/resources/js/router/modules/error.js:
--------------------------------------------------------------------------------
1 | /** When your routing table is too long, you can split it into small modules**/
2 | import Layout from '@/layout';
3 |
4 | const errorRoutes = {
5 | path: '/error',
6 | component: Layout,
7 | redirect: 'noredirect',
8 | name: 'ErrorPages',
9 | meta: {
10 | title: 'errorPages',
11 | icon: '404',
12 | },
13 | children: [
14 | {
15 | path: '401',
16 | component: () => import('@/views/error-page/401'),
17 | name: 'Page401',
18 | meta: { title: 'page401', noCache: true },
19 | },
20 | {
21 | path: '404',
22 | component: () => import('@/views/error-page/404'),
23 | name: 'Page404',
24 | meta: { title: 'page404', noCache: true },
25 | },
26 | ],
27 | };
28 |
29 | export default errorRoutes;
30 |
--------------------------------------------------------------------------------
/resources/js/router/modules/example.js:
--------------------------------------------------------------------------------
1 | /** When your routing table is too long, you can split it into small modules**/
2 | import Layout from '@/layout';
3 |
4 | const exampleRoutes = {
5 | path: '/example',
6 | component: Layout,
7 | redirect: '/example/list',
8 | name: 'Example',
9 | meta: {
10 | title: 'example',
11 | icon: 'example',
12 | },
13 | children: [
14 | {
15 | path: 'create',
16 | component: () => import('@/views/example/Create'),
17 | name: 'CreateArticle',
18 | meta: { title: 'createArticle', icon: 'edit' },
19 | },
20 | {
21 | path: 'edit/:id(\\d+)',
22 | component: () => import('@/views/example/Edit'),
23 | name: 'EditArticle',
24 | meta: { title: 'editArticle', noCache: true },
25 | hidden: true,
26 | },
27 | {
28 | path: 'list',
29 | component: () => import('@/views/example/List'),
30 | name: 'ArticleList',
31 | meta: { title: 'articleList', icon: 'list' },
32 | },
33 | ],
34 | };
35 |
36 | export default exampleRoutes;
37 |
--------------------------------------------------------------------------------
/resources/js/router/modules/excel.js:
--------------------------------------------------------------------------------
1 | /** When your routing table is too long, you can split it into small modules**/
2 | import Layout from '@/layout';
3 |
4 | const excelRoutes = {
5 | path: '/excel',
6 | component: Layout,
7 | redirect: '/excel/export-excel',
8 | name: 'Excel',
9 | meta: {
10 | title: 'excel',
11 | icon: 'excel',
12 | permissions: ['view menu excel'],
13 | },
14 | children: [
15 | {
16 | path: 'export-excel',
17 | component: () => import('@/views/excel/ExportExcel'),
18 | name: 'exportExcel',
19 | meta: { title: 'exportExcel' },
20 | },
21 | {
22 | path: 'export-selected-excel',
23 | component: () => import('@/views/excel/SelectExcel'),
24 | name: 'SelectExcel',
25 | meta: { title: 'selectExcel' },
26 | },
27 | {
28 | path: 'export-merge-header',
29 | component: () => import('@/views/excel/MergeHeader'),
30 | name: 'MergeHeader',
31 | meta: { title: 'mergeHeader' },
32 | },
33 | {
34 | path: 'upload-excel',
35 | component: () => import('@/views/excel/UploadExcel'),
36 | name: 'UploadExcel',
37 | meta: { title: 'uploadExcel' },
38 | },
39 | ],
40 | };
41 |
42 | export default excelRoutes;
43 |
--------------------------------------------------------------------------------
/resources/js/router/modules/permission.js:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout';
2 |
3 | const permissionRoutes = {
4 | path: '/permission',
5 | component: Layout,
6 | redirect: '/permission/index',
7 | alwaysShow: true, // will always show the root menu
8 | meta: {
9 | title: 'permission',
10 | icon: 'lock',
11 | permissions: ['view menu permission'],
12 | },
13 | children: [
14 | {
15 | path: 'page',
16 | component: () => import('@/views/permission/Page'),
17 | name: 'PagePermission',
18 | meta: {
19 | title: 'pagePermission',
20 | permissions: ['manage permission'],
21 | },
22 | },
23 | {
24 | path: 'directive',
25 | component: () => import('@/views/permission/Directive'),
26 | name: 'directivePermission',
27 | meta: {
28 | title: 'directivePermission',
29 | // if do not set roles neither permissions, means: this page does not require permission
30 | },
31 | },
32 | ],
33 | };
34 |
35 | export default permissionRoutes;
36 |
--------------------------------------------------------------------------------
/resources/js/router/modules/table.js:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout';
2 |
3 | const tableRoutes = {
4 | path: '/table',
5 | component: Layout,
6 | redirect: '/table/complex-table',
7 | name: 'Complex Table',
8 | meta: {
9 | title: 'table',
10 | icon: 'table',
11 | permissions: ['view menu table'],
12 | },
13 | children: [
14 | {
15 | path: 'drag-table',
16 | component: () => import('@/views/table/DragTable'),
17 | name: 'DragTable',
18 | meta: { title: 'dragTable' },
19 | },
20 | {
21 | path: 'inline-edit-table',
22 | component: () => import('@/views/table/InlineEditTable'),
23 | name: 'InlineEditTable',
24 | meta: { title: 'inlineEditTable' },
25 | },
26 | {
27 | path: 'complex-table',
28 | component: () => import('@/views/table/ComplexTable'),
29 | name: 'ComplexTable',
30 | meta: { title: 'complexTable' },
31 | },
32 | ],
33 | };
34 | export default tableRoutes;
35 |
--------------------------------------------------------------------------------
/resources/js/settings.js:
--------------------------------------------------------------------------------
1 | import variables from '@/styles/element-variables.scss';
2 |
3 | export default {
4 | /**
5 | * @type {String}
6 | */
7 | title: 'Laravue Admin',
8 | theme: variables.theme,
9 |
10 | /**
11 | * @type {boolean} true | false
12 | * @description Whether show the settings right-panel
13 | */
14 | showSettings: true,
15 |
16 | /**
17 | * @type {boolean} true | false
18 | * @description Whether need tagsView
19 | */
20 | tagsView: true,
21 |
22 | /**
23 | * @type {boolean} true | false
24 | * @description Whether fix the header
25 | */
26 | fixedHeader: false,
27 |
28 | /**
29 | * @type {boolean} true | false
30 | * @description Whether show the logo in sidebar
31 | */
32 | sidebarLogo: false,
33 |
34 | /**
35 | * @type {string | array} 'production' | ['production','development']
36 | * @description Need show err logs component.
37 | * The default is only used in the production env
38 | * If you want to also use it in dev, you can pass ['production','development']
39 | */
40 | errorLog: 'production',
41 | };
42 |
--------------------------------------------------------------------------------
/resources/js/store/getters.js:
--------------------------------------------------------------------------------
1 | const getters = {
2 | sidebar: state => state.app.sidebar,
3 | language: state => state.app.language,
4 | size: state => state.app.size,
5 | device: state => state.app.device,
6 | visitedViews: state => state.tagsView.visitedViews,
7 | cachedViews: state => state.tagsView.cachedViews,
8 | userId: state => state.user.id,
9 | token: state => state.user.token,
10 | avatar: state => state.user.avatar,
11 | name: state => state.user.name,
12 | user: state => state.user.user,
13 | introduction: state => state.user.introduction,
14 | roles: state => state.user.roles,
15 | permissions: state => state.user.permissions,
16 | permissionRoutes: state => state.permission.routes,
17 | addRoutes: state => state.permission.addRoutes,
18 | };
19 | export default getters;
20 |
--------------------------------------------------------------------------------
/resources/js/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 | import getters from './getters';
4 |
5 | Vue.use(Vuex);
6 |
7 | // https://webpack.js.org/guides/dependency-management/#requirecontext
8 | const modulesFiles = require.context('./modules', false, /\.js$/);
9 |
10 | // you do not need `import app from './modules/app'`
11 | // it will auto require all vuex module from modules file
12 | const modules = modulesFiles.keys().reduce((modules, modulePath) => {
13 | // set './app.js' => 'app'
14 | const moduleName = (modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')).replace(/-([a-z])/g, g => g[1].toUpperCase());
15 | // camelCase(modulePath.replace(/^\.\/(.*)\.\w+$/, '$1'));
16 | const value = modulesFiles(modulePath);
17 | modules[moduleName] = value.default;
18 | return modules;
19 | }, {});
20 |
21 | const store = new Vuex.Store({
22 | modules,
23 | getters,
24 | });
25 |
26 | export default store;
27 |
--------------------------------------------------------------------------------
/resources/js/store/modules/settings.js:
--------------------------------------------------------------------------------
1 | import defaultSettings from '@/settings';
2 | const { showSettings, tagsView, fixedHeader, sidebarLogo, theme } = defaultSettings;
3 |
4 | const state = {
5 | theme: theme,
6 | showSettings: showSettings,
7 | tagsView: tagsView,
8 | fixedHeader: fixedHeader,
9 | sidebarLogo: sidebarLogo,
10 | };
11 |
12 | const mutations = {
13 | CHANGE_SETTING: (state, { key, value }) => {
14 | if (Object.prototype.hasOwnProperty.call(state, key)) {
15 | state[key] = value;
16 | }
17 | },
18 | };
19 |
20 | const actions = {
21 | changeSetting({ commit }, data) {
22 | commit('CHANGE_SETTING', data);
23 | },
24 | };
25 |
26 | export default {
27 | namespaced: true,
28 | state,
29 | mutations,
30 | actions,
31 | };
32 |
33 |
--------------------------------------------------------------------------------
/resources/js/styles/element-ui.scss:
--------------------------------------------------------------------------------
1 | //to reset element-ui default css
2 | .el-breadcrumb__inner,
3 | .el-breadcrumb__inner a {
4 | font-weight: 400 !important;
5 | }
6 |
7 | .el-upload {
8 | input[type="file"] {
9 | display: none !important;
10 | }
11 | }
12 |
13 | .el-upload__input {
14 | display: none;
15 | }
16 |
17 | .cell {
18 | .el-tag {
19 | margin-right: 0px;
20 | }
21 | }
22 |
23 | .small-padding {
24 | .cell {
25 | padding-left: 5px;
26 | padding-right: 5px;
27 | }
28 | }
29 |
30 | .fixed-width {
31 | .el-button--mini {
32 | padding: 7px 10px;
33 | width: 60px;
34 | }
35 | }
36 |
37 | .status-col {
38 | .cell {
39 | padding: 0 10px;
40 | text-align: center;
41 |
42 | .el-tag {
43 | margin-right: 0px;
44 | }
45 | }
46 | }
47 |
48 | .el-dialog {
49 | transform: none;
50 | left: 0;
51 | position: relative;
52 | margin: 0 auto;
53 | }
54 |
55 | .article-textarea {
56 | textarea {
57 | padding-right: 40px;
58 | resize: none;
59 | border: none;
60 | border-radius: 0px;
61 | border-bottom: 1px solid #bfcbd9;
62 | }
63 | }
64 |
65 | //element ui upload
66 | .upload-container {
67 | .el-upload {
68 | width: 100%;
69 |
70 | .el-upload-dragger {
71 | width: 100%;
72 | height: 200px;
73 | }
74 | }
75 | }
76 |
77 | //dropdown
78 | .el-dropdown-menu {
79 | a {
80 | display: block
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/resources/js/styles/element-variables.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * I think element-ui's default theme color is too light for long-term use.
3 | * So I modified the default color and you can modify it to your liking.
4 | **/
5 |
6 | /* theme color */
7 | $--color-primary: #1890ff;
8 | $--color-success: #13ce66;
9 | $--color-warning: #FFBA00;
10 | $--color-danger: #ff4949;
11 | // $--color-info: #1E1E1E;
12 |
13 | $--button-font-weight: 400;
14 |
15 | // $--color-text-regular: #1f2d3d;
16 |
17 | $--border-color-light: #dfe4ed;
18 | $--border-color-lighter: #e6ebf5;
19 |
20 | $--table-border:1px solid#dfe6ec;
21 |
22 | /* icon font path, required */
23 | $--font-path: 'css/fonts';
24 |
25 | @import "~element-ui/packages/theme-chalk/src/index";
26 |
27 | // the :export directive is the magic sauce for webpack
28 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
29 | :export {
30 | theme: $--color-primary;
31 | }
32 |
--------------------------------------------------------------------------------
/resources/js/styles/laravue.scss:
--------------------------------------------------------------------------------
1 | .box-center {
2 | margin: 0 auto;
3 | display: table;
4 | }
5 | .text-muted {
6 | color: #777;
7 | }
8 | .pull-right {
9 | float: right !important;
10 | }
11 |
12 | .permissions-container {
13 | .block {
14 | .el-form-item__label {
15 | padding-left: 24px;
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/resources/js/styles/mixin.scss:
--------------------------------------------------------------------------------
1 | @mixin clearfix {
2 | &:after {
3 | content: "";
4 | display: table;
5 | clear: both;
6 | }
7 | }
8 |
9 | @mixin scrollBar {
10 | &::-webkit-scrollbar-track-piece {
11 | background: #d3dce6;
12 | }
13 |
14 | &::-webkit-scrollbar {
15 | width: 6px;
16 | }
17 |
18 | &::-webkit-scrollbar-thumb {
19 | background: #99a9bf;
20 | border-radius: 20px;
21 | }
22 | }
23 |
24 | @mixin relative {
25 | position: relative;
26 | width: 100%;
27 | height: 100%;
28 | }
29 |
--------------------------------------------------------------------------------
/resources/js/styles/transition.scss:
--------------------------------------------------------------------------------
1 | //globl transition css
2 |
3 | /*fade*/
4 | .fade-enter-active,
5 | .fade-leave-active {
6 | transition: opacity 0.28s;
7 | }
8 |
9 | .fade-enter,
10 | .fade-leave-active {
11 | opacity: 0;
12 | }
13 |
14 | /*fade-transform*/
15 | .fade-transform-leave-active,
16 | .fade-transform-enter-active {
17 | transition: all .5s;
18 | }
19 |
20 | .fade-transform-enter {
21 | opacity: 0;
22 | transform: translateX(-30px);
23 | }
24 |
25 | .fade-transform-leave-to {
26 | opacity: 0;
27 | transform: translateX(30px);
28 | }
29 |
30 | /*fade*/
31 | .breadcrumb-enter-active,
32 | .breadcrumb-leave-active {
33 | transition: all .5s;
34 | }
35 |
36 | .breadcrumb-enter,
37 | .breadcrumb-leave-active {
38 | opacity: 0;
39 | transform: translateX(20px);
40 | }
41 |
42 | .breadcrumb-move {
43 | transition: all .5s;
44 | }
45 |
46 | .breadcrumb-leave-active {
47 | position: absolute;
48 | }
49 |
--------------------------------------------------------------------------------
/resources/js/styles/variables.scss:
--------------------------------------------------------------------------------
1 | // base color
2 | $blue:#324157;
3 | $light-blue:#3A71A8;
4 | $red:#C03639;
5 | $pink: #E65D6E;
6 | $green: #30B08F;
7 | $tiffany: #4AB7BD;
8 | $yellow:#FEC171;
9 | $panGreen: #30B08F;
10 |
11 | //sidebar
12 | $menuText:#bfcbd9;
13 | $menuActiveText:#409EFF;
14 | $subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
15 |
16 | $menuBg:#304156;
17 | $menuHover:#263445;
18 |
19 | $subMenuBg:#1f2d3d;
20 | $subMenuHover:#001528;
21 |
22 | $sideBarWidth: 210px;
23 |
24 | // the :export directive is the magic sauce for webpack
25 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
26 | :export {
27 | menuText: $menuText;
28 | menuActiveText: $menuActiveText;
29 | subMenuActiveText: $subMenuActiveText;
30 | menuBg: $menuBg;
31 | menuHover: $menuHover;
32 | subMenuBg: $subMenuBg;
33 | subMenuHover: $subMenuHover;
34 | sideBarWidth: $sideBarWidth;
35 | }
36 |
--------------------------------------------------------------------------------
/resources/js/utils/auth.js:
--------------------------------------------------------------------------------
1 | import Cookies from 'js-cookie';
2 |
3 | const TokenKey = 'isLogged';
4 |
5 | export function isLogged() {
6 | return Cookies.get(TokenKey) === '1';
7 | }
8 |
9 | export function setLogged(isLogged) {
10 | return Cookies.set(TokenKey, isLogged);
11 | }
12 |
13 | export function removeToken() {
14 | return Cookies.remove(TokenKey);
15 | }
16 |
--------------------------------------------------------------------------------
/resources/js/utils/clipboard.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Clipboard from 'clipboard';
3 |
4 | function clipboardSuccess() {
5 | Vue.prototype.$message({
6 | message: 'Copy successfully',
7 | type: 'success',
8 | duration: 1500,
9 | });
10 | }
11 |
12 | function clipboardError() {
13 | Vue.prototype.$message({
14 | message: 'Copy failed',
15 | type: 'error',
16 | });
17 | }
18 |
19 | export default function handleClipboard(text, event) {
20 | const clipboard = new Clipboard(event.target, {
21 | text: () => text,
22 | });
23 |
24 | clipboard.on('success', () => {
25 | clipboardSuccess();
26 | clipboard.off('error');
27 | clipboard.off('success');
28 | clipboard.destroy();
29 | });
30 |
31 | clipboard.on('error', () => {
32 | clipboardError();
33 | clipboard.off('error');
34 | clipboard.off('success');
35 | clipboard.destroy();
36 | });
37 |
38 | clipboard.onClick(event);
39 | }
40 |
--------------------------------------------------------------------------------
/resources/js/utils/get-page-title.js:
--------------------------------------------------------------------------------
1 | import defaultSettings from '@/settings';
2 | import i18n from '@/lang';
3 |
4 | const title = defaultSettings.title || 'Laravue Admin';
5 |
6 | export default function getPageTitle(key) {
7 | const hasKey = i18n.te(`route.${key}`);
8 | if (hasKey) {
9 | const pageName = i18n.t(`route.${key}`);
10 | return `${pageName} - ${title}`;
11 | }
12 | return `${title}`;
13 | }
14 |
--------------------------------------------------------------------------------
/resources/js/utils/i18n.js:
--------------------------------------------------------------------------------
1 | // translate router.meta.title, be used in breadcrumb sidebar tagsview
2 | export function generateTitle(title) {
3 | const hasKey = this.$te('route.' + title);
4 |
5 | if (hasKey) {
6 | // $t :this method from vue-i18n, inject in @/lang/index.js
7 | const translatedTitle = this.$t('route.' + title);
8 |
9 | return translatedTitle;
10 | }
11 | return title;
12 | }
13 |
--------------------------------------------------------------------------------
/resources/js/utils/permission.js:
--------------------------------------------------------------------------------
1 | import store from '@/store';
2 |
3 | /**
4 | * @param {Array} value
5 | * @returns {Boolean}
6 | * @example see @/views/permission/Directive.vue
7 | */
8 | export default function checkPermission(value) {
9 | if (value && value instanceof Array && value.length > 0) {
10 | const permissions = store.getters && store.getters.permissions;
11 | const requiredPermissions = value;
12 |
13 | const hasPermission = permissions.some(permission => {
14 | return requiredPermissions.includes(permission);
15 | });
16 |
17 | return hasPermission;
18 | } else {
19 | console.error(`Need permissions! Like v-permission="['manage permission','edit article']"`);
20 | return false;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/resources/js/utils/request.js:
--------------------------------------------------------------------------------
1 | import '@/bootstrap';
2 | import { Message } from 'element-ui';
3 | // import { isLogged, setLogged } from '@/utils/auth';
4 |
5 | // Create axios instance
6 | const service = window.axios.create({
7 | baseURL: process.env.MIX_BASE_API,
8 | timeout: 10000, // Request timeout
9 | });
10 |
11 | // Request intercepter
12 | service.interceptors.request.use(
13 | config => {
14 | // const token = isLogged();
15 | // if (token) {
16 | // config.headers['Authorization'] = 'Bearer ' + isLogged(); // Set JWT token
17 | // }
18 | return config;
19 | },
20 | error => {
21 | // Do something with request error
22 | console.log(error); // for debug
23 | Promise.reject(error);
24 | }
25 | );
26 |
27 | // response pre-processing
28 | service.interceptors.response.use(
29 | response => {
30 | // if (response.headers.authorization) {
31 | // setLogged(response.headers.authorization);
32 | // response.data.token = response.headers.authorization;
33 | // }
34 |
35 | return response.data;
36 | },
37 | error => {
38 | let message = error.message;
39 | if (error.response.data && error.response.data.errors) {
40 | message = error.response.data.errors;
41 | } else if (error.response.data && error.response.data.error) {
42 | message = error.response.data.error;
43 | }
44 |
45 | Message({
46 | message: message,
47 | type: 'error',
48 | duration: 5 * 1000,
49 | });
50 | return Promise.reject(error);
51 | }
52 | );
53 |
54 | export default service;
55 |
--------------------------------------------------------------------------------
/resources/js/utils/role.js:
--------------------------------------------------------------------------------
1 | import store from '@/store';
2 |
3 | /**
4 | * @param {Array} value
5 | * @returns {Boolean}
6 | * @example see @/views/permission/Directive.vue
7 | */
8 | export default function checkRole(value) {
9 | if (value && value instanceof Array && value.length > 0) {
10 | const roles = store.getters && store.getters.roles;
11 | const requiredRoles = value;
12 |
13 | const hasRole = roles.some(role => {
14 | return requiredRoles.includes(role);
15 | });
16 |
17 | return hasRole;
18 | } else {
19 | console.error(`Need roles! Like v-role="['admin','editor']"`);
20 | return false;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/resources/js/vendor/Export2Zip.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | require('script-loader!file-saver');
3 | import JSZip from 'jszip'
4 |
5 | export function export_txt_to_zip(th, jsonData, txtName, zipName) {
6 | const zip = new JSZip()
7 | const txt_name = txtName || 'file'
8 | const zip_name = zipName || 'file'
9 | const data = jsonData
10 | let txtData = `${th}\r\n`
11 | data.forEach((row) => {
12 | let tempStr = ''
13 | tempStr = row.toString()
14 | txtData += `${tempStr}\r\n`
15 | })
16 | zip.file(`${txt_name}.txt`, txtData)
17 | zip.generateAsync({
18 | type: "blob"
19 | }).then((blob) => {
20 | saveAs(blob, `${zip_name}.zip`)
21 | }, (err) => {
22 | alert('导出失败')
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/resources/js/views/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/resources/js/views/articles/Create.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
--------------------------------------------------------------------------------
/resources/js/views/articles/Edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
--------------------------------------------------------------------------------
/resources/js/views/articles/components/Dropdown/Comment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ !comment_disabled ? 'Comment opened' : 'Comment closed' }}
5 |
6 |
7 |
8 |
9 |
10 |
11 | Close comment
12 |
13 |
14 | Open comment
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
42 |
--------------------------------------------------------------------------------
/resources/js/views/articles/components/Dropdown/Platform.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Platform ({{ platforms.length }})
5 |
6 |
7 |
8 |
9 |
10 | {{ item.name }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
47 |
--------------------------------------------------------------------------------
/resources/js/views/articles/components/Dropdown/SourceUrl.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | External URL
5 |
6 |
7 |
8 |
9 |
10 |
11 | Fill in the URL
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
39 |
--------------------------------------------------------------------------------
/resources/js/views/articles/components/Dropdown/index.js:
--------------------------------------------------------------------------------
1 | export { default as CommentDropdown } from './Comment';
2 | export { default as PlatformDropdown } from './Platform';
3 | export { default as SourceUrlDropdown } from './SourceUrl';
4 |
--------------------------------------------------------------------------------
/resources/js/views/charts/Keyboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/resources/js/views/charts/Line.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/resources/js/views/charts/MixChart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/resources/js/views/clipboard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | copy
8 |
9 |
10 |
11 |
12 |
13 | copy
14 |
15 |
16 |
17 |
18 |
19 |
20 |
49 |
50 |
--------------------------------------------------------------------------------
/resources/js/views/components-demo/BackToTop.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ $t('components.backToTopTips1') }}
4 |
{{ $t('components.backToTopTips2') }}
5 |
6 |
7 | -
8 | Placeholder
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
40 |
41 |
51 |
--------------------------------------------------------------------------------
/resources/js/views/components-demo/DndList.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
39 |
40 |
--------------------------------------------------------------------------------
/resources/js/views/components-demo/DragSelect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ item }}
10 |
11 |
12 |
13 |
14 |
15 |
44 |
--------------------------------------------------------------------------------
/resources/js/views/components-demo/Dropzone.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Based on dropzone .
5 | {{ $t('components.dropzoneTips') }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
29 |
30 |
--------------------------------------------------------------------------------
/resources/js/views/components-demo/JsonEditor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
JsonEditor is base on CodeMirrorr , lint base on json-lint
4 |
5 |
6 |
7 |
8 |
9 |
10 |
25 |
26 |
32 |
--------------------------------------------------------------------------------
/resources/js/views/components-demo/SplitPane.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
34 |
35 |
63 |
--------------------------------------------------------------------------------
/resources/js/views/components-demo/Tinymce.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
30 |
31 |
36 |
37 |
--------------------------------------------------------------------------------
/resources/js/views/dashboard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
32 |
--------------------------------------------------------------------------------
/resources/js/views/excel/UploadExcel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
43 |
--------------------------------------------------------------------------------
/resources/js/views/excel/components/AutoWidthOption.vue:
--------------------------------------------------------------------------------
1 | Tinymce/components/EditorImage.vue
2 |
--------------------------------------------------------------------------------
/resources/js/views/excel/components/BookTypeOption.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
40 |
--------------------------------------------------------------------------------
/resources/js/views/excel/components/FilenameOption.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
29 |
--------------------------------------------------------------------------------
/resources/js/views/guide/define-steps.js:
--------------------------------------------------------------------------------
1 | const steps = [
2 | {
3 | element: '#hamburger-container',
4 | popover: {
5 | title: 'Hamburger',
6 | description: 'Open && Close sidebar',
7 | position: 'bottom',
8 | },
9 | },
10 | {
11 | element: '#breadcrumb-container',
12 | popover: {
13 | title: 'Breadcrumb',
14 | description: 'Indicate the current page location',
15 | position: 'bottom',
16 | },
17 | },
18 | {
19 | element: '#header-search',
20 | popover: {
21 | title: 'Page Search',
22 | description: 'Page search, quick navigation',
23 | position: 'left',
24 | },
25 | },
26 | {
27 | element: '#screenfull',
28 | popover: {
29 | title: 'Screenfull',
30 | description: 'Set the page into fullscreen',
31 | position: 'left',
32 | },
33 | },
34 | {
35 | element: '#size-select',
36 | popover: {
37 | title: 'Switch Size',
38 | description: 'Switch the system size',
39 | position: 'left',
40 | },
41 | },
42 | {
43 | element: '#tags-view-container',
44 | popover: {
45 | title: 'Tags view',
46 | description: 'The history of the page you visited',
47 | position: 'bottom',
48 | },
49 | padding: 0,
50 | },
51 | ];
52 |
53 | export default steps;
54 |
--------------------------------------------------------------------------------
/resources/js/views/guide/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ $t('guide.description') }}
5 | driver.js.
6 |
7 |
8 |
9 | {{ $t('guide.button') }}
10 |
11 |
12 |
13 |
14 |
37 |
--------------------------------------------------------------------------------
/resources/js/views/icons/components/IconFont/require-icons.js:
--------------------------------------------------------------------------------
1 | const req = require.context('@/icons/svg', false, /\.svg$/);
2 | const requireAll = requireContext => requireContext.keys();
3 |
4 | const re = /\.\/(.*)\.svg/;
5 |
6 | const icons = requireAll(req).map(i => {
7 | return i.match(re)[1];
8 | });
9 |
10 | export default icons;
11 |
--------------------------------------------------------------------------------
/resources/js/views/icons/element-icons.js:
--------------------------------------------------------------------------------
1 | const elementIcons = ['info', 'error', 'success', 'warning', 'question', 'back', 'arrow-left', 'arrow-down', 'arrow-right', 'arrow-up', 'caret-left', 'caret-bottom', 'caret-top', 'caret-right', 'd-arrow-left', 'd-arrow-right', 'minus', 'plus', 'remove', 'circle-plus', 'remove-outline', 'circle-plus-outline', 'close', 'check', 'circle-close', 'circle-check', 'circle-close-outline', 'circle-check-outline', 'zoom-out', 'zoom-in', 'd-caret', 'sort', 'sort-down', 'sort-up', 'tickets', 'document', 'goods', 'sold-out', 'news', 'message', 'date', 'printer', 'time', 'bell', 'mobile-phone', 'service', 'view', 'menu', 'more', 'more-outline', 'star-on', 'star-off', 'location', 'location-outline', 'phone', 'phone-outline', 'picture', 'picture-outline', 'delete', 'search', 'edit', 'edit-outline', 'rank', 'refresh', 'share', 'setting', 'upload', 'upload2', 'download', 'loading'];
2 | export default elementIcons;
3 |
--------------------------------------------------------------------------------
/resources/js/views/icons/svg-icons.js:
--------------------------------------------------------------------------------
1 | const req = require.context('../../icons/svg', false, /\.svg$/);
2 | const requireAll = requireContext => requireContext.keys();
3 |
4 | const re = /\.\/(.*)\.svg/;
5 |
6 | const svgIcons = requireAll(req).map(i => {
7 | return i.match(re)[1];
8 | });
9 |
10 | export default svgIcons;
11 |
--------------------------------------------------------------------------------
/resources/js/views/login/AuthRedirect.vue:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/resources/js/views/nested/menu1/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/js/views/nested/menu1/menu1-1/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/js/views/nested/menu1/menu1-2/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/js/views/nested/menu1/menu1-2/menu1-2-1/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/js/views/nested/menu1/menu1-2/menu1-2-2/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/js/views/nested/menu1/menu1-3/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/js/views/nested/menu2/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/js/views/pdf/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ $t('pdf.tips') }}
4 |
5 |
6 | Click to download PDF
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/resources/js/views/permission/Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
--------------------------------------------------------------------------------
/resources/js/views/redirect/index.vue:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/resources/js/views/tab/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | mounted times :{{ createdTimes }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
40 |
41 |
46 |
--------------------------------------------------------------------------------
/resources/js/views/table/DynamicTable/UnfixedThead.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | apple
7 |
8 |
9 | banana
10 |
11 |
12 | orange
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ scope.row[fruit] }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
51 |
--------------------------------------------------------------------------------
/resources/js/views/table/DynamicTable/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ $t('table.dynamicTips1') }}
5 |
6 |
7 |
8 |
9 | {{ $t('table.dynamicTips2') }}
10 |
11 |
12 |
13 |
14 |
15 |
24 |
25 |
--------------------------------------------------------------------------------
/resources/js/views/users/SelfProfile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
44 |
--------------------------------------------------------------------------------
/resources/js/views/users/UserProfile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
52 |
--------------------------------------------------------------------------------
/resources/lang/en/auth.php:
--------------------------------------------------------------------------------
1 | 'These credentials do not match our records.',
17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
18 |
19 | ];
20 |
--------------------------------------------------------------------------------
/resources/lang/en/pagination.php:
--------------------------------------------------------------------------------
1 | '« Previous',
17 | 'next' => 'Next »',
18 |
19 | ];
20 |
--------------------------------------------------------------------------------
/resources/lang/en/passwords.php:
--------------------------------------------------------------------------------
1 | 'Your password has been reset!',
17 | 'sent' => 'We have emailed your password reset link!',
18 | 'throttled' => 'Please wait before retrying.',
19 | 'token' => 'This password reset token is invalid.',
20 | 'user' => "We can't find a user with that email address.",
21 |
22 | ];
23 |
--------------------------------------------------------------------------------
/resources/sass/_variables.scss:
--------------------------------------------------------------------------------
1 |
2 | // Body
3 | $body-bg: #f8fafc;
4 |
5 | // Typography
6 | $font-family-sans-serif: "Nunito", sans-serif;
7 | $font-size-base: 0.9rem;
8 | $line-height-base: 1.6;
9 |
10 | // Colors
11 | $blue: #3490dc;
12 | $indigo: #6574cd;
13 | $purple: #9561e2;
14 | $pink: #f66D9b;
15 | $red: #e3342f;
16 | $orange: #f6993f;
17 | $yellow: #ffed4a;
18 | $green: #38c172;
19 | $teal: #4dc0b5;
20 | $cyan: #6cb2eb;
21 |
--------------------------------------------------------------------------------
/resources/sass/app.scss:
--------------------------------------------------------------------------------
1 | // Fonts
2 | @import url('https://fonts.googleapis.com/css?family=Nunito');
3 |
4 | // Variables
5 | @import 'variables';
6 |
7 | .navbar-laravel {
8 | background-color: #fff;
9 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
10 | }
11 |
--------------------------------------------------------------------------------
/routes/channels.php:
--------------------------------------------------------------------------------
1 | id === (int) $id;
18 | });
19 |
--------------------------------------------------------------------------------
/routes/console.php:
--------------------------------------------------------------------------------
1 | comment(Inspiring::quote());
19 | })->describe('Display an inspiring quote');
20 |
--------------------------------------------------------------------------------
/routes/web.php:
--------------------------------------------------------------------------------
1 | 'web'], function () {
21 | Route::get(env('LARAVUE_PATH'), 'LaravueController@index')->where('any', '.*')->name('laravue');
22 | });
23 |
--------------------------------------------------------------------------------
/server.php:
--------------------------------------------------------------------------------
1 |
8 | */
9 |
10 | $uri = urldecode(
11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
12 | );
13 |
14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the
15 | // built-in PHP web server. This provides a convenient way to test a Laravel
16 | // application without having installed a "real" web server software here.
17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {
18 | return false;
19 | }
20 |
21 | require_once __DIR__.'/public/index.php';
22 |
--------------------------------------------------------------------------------
/storage/app/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !public/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/app/public/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/.gitignore:
--------------------------------------------------------------------------------
1 | config.php
2 | routes.php
3 | schedule-*
4 | compiled.php
5 | services.json
6 | events.scanned.php
7 | routes.scanned.php
8 | down
9 |
--------------------------------------------------------------------------------
/storage/framework/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !data/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/framework/cache/data/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/sessions/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/testing/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/views/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/logs/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/tests/Bootstrap.php:
--------------------------------------------------------------------------------
1 | createApplication()->make(Kernel::class);
27 |
28 | $commands = [
29 | 'config:cache',
30 | 'event:cache',
31 | ];
32 |
33 | foreach ($commands as $command) {
34 | $console->call($command);
35 | }
36 | }
37 |
38 | public function executeAfterLastTest(): void
39 | {
40 | array_map('unlink', glob('bootstrap/cache/*.phpunit.php'));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/tests/CreatesApplication.php:
--------------------------------------------------------------------------------
1 | make(Kernel::class)->bootstrap();
19 |
20 | return $app;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Feature/ExampleTest.php:
--------------------------------------------------------------------------------
1 | get('/');
18 |
19 | $response->assertStatus(200);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | assertTrue(true);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
3 |
4 | function resolve(dir) {
5 | return path.join(
6 | __dirname,
7 | '/resources/js',
8 | dir
9 | );
10 | }
11 |
12 | const rawArgv = process.argv.slice(2);
13 | const args = rawArgv.join(' ');
14 | const report = rawArgv.includes('--report');
15 | let plugins = [];
16 | if (report) {
17 | plugins.push(new BundleAnalyzerPlugin({
18 | openAnalyzer: true,
19 | }));
20 | }
21 | module.exports = {
22 | resolve: {
23 | extensions: ['.js', '.vue', '.json'],
24 | alias: {
25 | vue$: 'vue/dist/vue.esm.js',
26 | '@': path.join(__dirname, '/resources/js'),
27 | },
28 | },
29 | module: {
30 | rules: [
31 | {
32 | test: /\.svg$/,
33 | loader: 'svg-sprite-loader',
34 | include: [resolve('icons')],
35 | options: {
36 | symbolId: 'icon-[name]',
37 | },
38 | },
39 | ],
40 | },
41 | plugins: plugins,
42 | output: {
43 | filename: '[name].js',
44 | chunkFilename: 'js/app.[chunkhash:6].js',
45 | },
46 | };
47 |
--------------------------------------------------------------------------------