├── public
├── favicon.ico
├── robots.txt
├── images
│ └── logo.png
├── fonts
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ ├── fontawesome-webfont.woff2
│ └── vendor
│ │ ├── _social-share.js@1.0.16@social-share.js
│ │ └── dist
│ │ │ ├── iconfont.eot
│ │ │ ├── iconfont.ttf
│ │ │ └── iconfont.woff
│ │ ├── _@fortawesome_fontawesome-free-webfonts@1.0.4@@fortawesome
│ │ ├── fontawesome-free-webwebfa-solid-900.eot
│ │ ├── fontawesome-free-webwebfa-solid-900.ttf
│ │ ├── fontawesome-free-webwebfa-brands-400.eot
│ │ ├── fontawesome-free-webwebfa-brands-400.ttf
│ │ ├── fontawesome-free-webwebfa-brands-400.woff
│ │ ├── fontawesome-free-webwebfa-regular-400.eot
│ │ ├── fontawesome-free-webwebfa-regular-400.ttf
│ │ ├── fontawesome-free-webwebfa-solid-900.woff
│ │ ├── fontawesome-free-webwebfa-solid-900.woff2
│ │ ├── fontawesome-free-webwebfa-brands-400.woff2
│ │ ├── fontawesome-free-webwebfa-regular-400.woff
│ │ └── fontawesome-free-webwebfa-regular-400.woff2
│ │ └── _@fortawesome_fontawesome-free-webfonts@1.0.5@@fortawesome
│ │ ├── fontawesome-free-webwebfa-solid-900.eot
│ │ ├── fontawesome-free-webwebfa-solid-900.ttf
│ │ ├── fontawesome-free-webwebfa-brands-400.eot
│ │ ├── fontawesome-free-webwebfa-brands-400.ttf
│ │ ├── fontawesome-free-webwebfa-brands-400.woff
│ │ ├── fontawesome-free-webwebfa-regular-400.eot
│ │ ├── fontawesome-free-webwebfa-regular-400.ttf
│ │ ├── fontawesome-free-webwebfa-solid-900.woff
│ │ ├── fontawesome-free-webwebfa-solid-900.woff2
│ │ ├── fontawesome-free-webwebfa-brands-400.woff2
│ │ ├── fontawesome-free-webwebfa-regular-400.woff
│ │ └── fontawesome-free-webwebfa-regular-400.woff2
├── vendor
│ └── horizon
│ │ ├── css
│ │ └── app.css.map
│ │ ├── img
│ │ └── favicon.png
│ │ └── mix-manifest.json
├── mix-manifest.json
├── .htaccess
└── js
│ └── manifest.js
├── database
├── .gitignore
├── factories
│ ├── CategoryFactory.php
│ ├── TagFactory.php
│ ├── ReplyFactory.php
│ ├── DiscusstionFactory.php
│ ├── UserFactory.php
│ ├── ArticleFactory.php
│ └── CommentFactory.php
├── seeds
│ ├── CommentsTableSeeder.php
│ ├── DiscusstionTableSeeder.php
│ ├── TagsTableSeeder.php
│ ├── CategoriesTableSeeder.php
│ ├── DiscussionsTableSeeder.php
│ ├── ArticlesTableSeeder.php
│ ├── UsersTableSeeder.php
│ ├── DatabaseSeeder.php
│ └── MakeDiscussionSolvedSeeder.php
└── migrations
│ ├── 2017_05_28_025409_create_categories_table.php
│ ├── 2014_10_12_100000_create_password_resets_table.php
│ ├── 2017_05_28_031123_create_tags_table.php
│ ├── 2017_05_28_030133_create_replies_table.php
│ ├── 2017_05_28_031151_create_taggables_table.php
│ ├── 2017_06_22_100627_create_special_pages_table.php
│ ├── 2017_05_28_030521_create_activities_table.php
│ ├── 2018_01_14_204314_create_notifications_table.php
│ ├── 2018_02_27_171949_create_failed_jobs_table.php
│ ├── 2017_05_28_030506_create_favorites_table.php
│ ├── 2017_06_01_095839_create_comments_table.php
│ ├── 2017_12_13_225211_create_subscriptions_table.php
│ ├── 2017_12_10_223853_add_outh_field_to_users_table.php
│ ├── 2017_11_19_115928_seed_special_pages_data.php
│ ├── 2018_02_06_142849_create_drafts_table.php
│ ├── 2018_01_29_211051_create_discussions_table.php
│ ├── 2014_10_12_000000_create_users_table.php
│ └── 2017_05_28_025758_create_articles_table.php
├── bootstrap
├── cache
│ └── .gitignore
└── autoload.php
├── resources
├── assets
│ ├── js
│ │ ├── libs.js
│ │ ├── components
│ │ │ ├── Home
│ │ │ │ ├── DeleteUser.vue
│ │ │ │ └── Menus.vue
│ │ │ ├── Parse.vue
│ │ │ ├── Example.vue
│ │ │ ├── BestAnswer.vue
│ │ │ └── Paginator.vue
│ │ ├── router.js
│ │ ├── global.js
│ │ └── pages
│ │ │ └── Article.vue
│ └── sass
│ │ ├── vender
│ │ └── fontawesome
│ │ │ ├── webfonts
│ │ │ ├── fa-brands-400.eot
│ │ │ ├── fa-brands-400.ttf
│ │ │ ├── fa-brands-400.woff
│ │ │ ├── fa-regular-400.eot
│ │ │ ├── fa-regular-400.ttf
│ │ │ ├── fa-solid-900.eot
│ │ │ ├── fa-solid-900.ttf
│ │ │ ├── fa-solid-900.woff
│ │ │ ├── fa-solid-900.woff2
│ │ │ ├── fa-brands-400.woff2
│ │ │ ├── fa-regular-400.woff
│ │ │ └── fa-regular-400.woff2
│ │ │ ├── _fixed-width.scss
│ │ │ ├── _screen-reader.scss
│ │ │ ├── _core.scss
│ │ │ ├── _animated.scss
│ │ │ ├── _list.scss
│ │ │ ├── _larger.scss
│ │ │ ├── fontawesome.scss
│ │ │ ├── _bordered-pulled.scss
│ │ │ ├── _stacked.scss
│ │ │ ├── fa-brands.scss
│ │ │ ├── fa-solid.scss
│ │ │ ├── fa-regular.scss
│ │ │ ├── _rotated-flipped.scss
│ │ │ └── _mixins.scss
│ │ ├── _navbar.scss
│ │ ├── helpers.scss
│ │ ├── home.scss
│ │ ├── overrite.scss
│ │ ├── app.scss
│ │ └── _variables.scss
├── views
│ ├── vendor
│ │ ├── mail
│ │ │ ├── markdown
│ │ │ │ ├── panel.blade.php
│ │ │ │ ├── table.blade.php
│ │ │ │ ├── footer.blade.php
│ │ │ │ ├── promotion.blade.php
│ │ │ │ ├── subcopy.blade.php
│ │ │ │ ├── button.blade.php
│ │ │ │ ├── header.blade.php
│ │ │ │ ├── promotion
│ │ │ │ │ └── button.blade.php
│ │ │ │ ├── layout.blade.php
│ │ │ │ └── message.blade.php
│ │ │ └── html
│ │ │ │ ├── table.blade.php
│ │ │ │ ├── header.blade.php
│ │ │ │ ├── subcopy.blade.php
│ │ │ │ ├── promotion.blade.php
│ │ │ │ ├── footer.blade.php
│ │ │ │ ├── panel.blade.php
│ │ │ │ ├── promotion
│ │ │ │ └── button.blade.php
│ │ │ │ ├── message.blade.php
│ │ │ │ └── button.blade.php
│ │ ├── flash
│ │ │ ├── modal.blade.php
│ │ │ └── message.blade.php
│ │ ├── pagination
│ │ │ ├── simple-bootstrap-4.blade.php
│ │ │ ├── admin.blade.php
│ │ │ ├── bootstrap-4.blade.php
│ │ │ └── default.blade.php
│ │ └── notifications
│ │ │ └── email.blade.php
│ ├── articles
│ │ ├── partials
│ │ │ ├── archive.blade.php
│ │ │ └── user.blade.php
│ │ ├── create_new.blade.php
│ │ ├── create.blade.php
│ │ └── edit.blade.php
│ ├── users
│ │ ├── activities
│ │ │ ├── activity.blade.php
│ │ │ ├── created_article.blade.php
│ │ │ └── created_comment.blade.php
│ │ ├── partials
│ │ │ └── setting_nav.blade.php
│ │ ├── editAvatar.blade.php
│ │ └── show.blade.php
│ ├── admin
│ │ └── partials
│ │ │ ├── errors.blade.php
│ │ │ └── slide_menu.blade.php
│ ├── drafts
│ │ ├── edit.blade.php
│ │ └── show.blade.php
│ ├── notifications
│ │ ├── partials
│ │ │ ├── nav.blade.php
│ │ │ ├── article_was_subscribed.blade.php
│ │ │ ├── article_was_favorited.blade.php
│ │ │ ├── comment_was_favorited.blade.php
│ │ │ ├── discussion_was_favorited.blade.php
│ │ │ ├── discussion_was_subscribed.blade.php
│ │ │ ├── article_was_updated.blade.php
│ │ │ └── answer_was_update_best.blade.php
│ │ └── index.blade.php
│ ├── home.blade.php
│ ├── layouts
│ │ └── partials
│ │ │ ├── footer.blade.php
│ │ │ └── category.blade.php
│ ├── discussions
│ │ └── index.blade.php
│ └── special_pages
│ │ └── edit.blade.php
└── lang
│ ├── en
│ ├── pagination.php
│ ├── auth.php
│ └── passwords.php
│ └── zh-CN
│ ├── pagination.php
│ ├── auth.php
│ └── passwords.php
├── storage
├── debugbar
│ └── .gitignore
├── logs
│ └── .gitignore
├── app
│ ├── public
│ │ └── .gitignore
│ └── .gitignore
└── framework
│ ├── cache
│ └── .gitignore
│ ├── testing
│ └── .gitignore
│ ├── views
│ └── .gitignore
│ ├── sessions
│ └── .gitignore
│ └── .gitignore
├── .rnd
├── .gitattributes
├── app
├── Models
│ ├── Reply.php
│ ├── SpecialPage.php
│ ├── Favorite.php
│ ├── Activity.php
│ ├── Subscription.php
│ ├── Category.php
│ └── Tag.php
├── Notifications
│ ├── NotificationMappable.php
│ ├── ArticleWasFavorited.php
│ ├── AnswerWasUpdateBest.php
│ └── CommentWasFavorited.php
├── Http
│ ├── Controllers
│ │ ├── Web
│ │ │ ├── ReplyController.php
│ │ │ ├── ActivityController.php
│ │ │ ├── FavoriteController.php
│ │ │ ├── TagsController.php
│ │ │ ├── CommentsController.php
│ │ │ ├── HomeController.php
│ │ │ ├── CategoriesController.php
│ │ │ ├── DraftsController.php
│ │ │ ├── NotificationsController.php
│ │ │ ├── SpecialPagesController.php
│ │ │ └── SessionsController.php
│ │ ├── Api
│ │ │ ├── ApiController.php
│ │ │ ├── CategoriesController.php
│ │ │ ├── TagsController.php
│ │ │ ├── FilesController.php
│ │ │ ├── AuthenticateController.php
│ │ │ ├── SubscriptionsController.php
│ │ │ ├── UsersController.php
│ │ │ ├── DraftsController.php
│ │ │ └── FavoriteController.php
│ │ ├── Controller.php
│ │ ├── HomeController.php
│ │ ├── Admin
│ │ │ ├── HomeController.php
│ │ │ └── UsersController.php
│ │ └── Auth
│ │ │ ├── ForgotPasswordController.php
│ │ │ └── ResetPasswordController.php
│ ├── Middleware
│ │ ├── EncryptCookies.php
│ │ ├── VerifyCsrfToken.php
│ │ ├── TrimStrings.php
│ │ ├── MustBeAdmin.php
│ │ └── RedirectIfAuthenticated.php
│ ├── Resources
│ │ ├── TagResource.php
│ │ ├── UserResource.php
│ │ ├── ArchiveResource.php
│ │ ├── CategoryResource.php
│ │ ├── SpecialPageResource.php
│ │ ├── DraftResource.php
│ │ ├── FavoriteResource.php
│ │ ├── CommentResource.php
│ │ ├── DiscussionResource.php
│ │ └── ArticleResource.php
│ ├── Flash.php
│ └── Requests
│ │ ├── UpdateUserRequest.php
│ │ ├── SubscribeRequest.php
│ │ └── FavoriteRequest.php
├── Observers
│ ├── ArticleObserver.php
│ └── DiscussionObserver.php
├── Providers
│ ├── BroadcastServiceProvider.php
│ ├── EventServiceProvider.php
│ ├── OAuthServiceProvider.php
│ └── AuthServiceProvider.php
├── Base
│ ├── Exceptions
│ │ ├── SubscribeException.php
│ │ └── FavoriteException.php
│ ├── Handler
│ │ └── NotificationHandler.php
│ ├── Filters
│ │ ├── Filters.php
│ │ └── ArticleFilters.php
│ ├── Traits
│ │ ├── SlugTransable.php
│ │ ├── ContentSetable.php
│ │ ├── GetModelByMorpType.php
│ │ └── Subscribable.php
│ ├── Helpers.php
│ └── Service
│ │ └── Markdowner.php
├── Policies
│ ├── UserPolicy.php
│ ├── SpecialPagePolicy.php
│ ├── CommentPolicy.php
│ ├── DiscussionPolicy.php
│ ├── ArticlePolicy.php
│ └── DraftPolicy.php
├── Scopes
│ └── ArticleFitterScope.php
├── Console
│ └── Kernel.php
└── Jobs
│ └── TranslateSlug.php
├── tests
├── TestCase.php
├── Feature
│ ├── ArticlesTest.php
│ └── ExampleTest.php
├── Unit
│ └── ExampleTest.php
└── CreatesApplication.php
├── .gitignore
├── config
├── note.php
├── hashing.php
├── image.php
├── view.php
├── trustedproxy.php
└── hashids.php
├── routes
├── channels.php
└── console.php
├── server.php
├── .eslintrc.json
├── webpack.mix.js
├── .env.example
├── phpunit.xml
└── package.json
/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/database/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite
2 |
--------------------------------------------------------------------------------
/bootstrap/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/resources/assets/js/libs.js:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/storage/debugbar/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/storage/logs/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/storage/app/public/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/.rnd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wowiwj/Note/HEAD/.rnd
--------------------------------------------------------------------------------
/storage/app/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !public/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/framework/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/testing/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/views/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/sessions/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/panel.blade.php:
--------------------------------------------------------------------------------
1 | {{ $slot }}
2 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/table.blade.php:
--------------------------------------------------------------------------------
1 | {{ $slot }}
2 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/footer.blade.php:
--------------------------------------------------------------------------------
1 | {{ $slot }}
2 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/promotion.blade.php:
--------------------------------------------------------------------------------
1 | {{ $slot }}
2 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/subcopy.blade.php:
--------------------------------------------------------------------------------
1 | {{ $slot }}
2 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/button.blade.php:
--------------------------------------------------------------------------------
1 | {{ $slot }}: {{ $url }}
2 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/header.blade.php:
--------------------------------------------------------------------------------
1 | [{{ $slot }}]({{ $url }})
2 |
--------------------------------------------------------------------------------
/resources/assets/js/components/Home/DeleteUser.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/resources/views/articles/partials/archive.blade.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wowiwj/Note/HEAD/public/images/logo.png
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/promotion/button.blade.php:
--------------------------------------------------------------------------------
1 | [{{ $slot }}]({{ $url }})
2 |
--------------------------------------------------------------------------------
/public/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wowiwj/Note/HEAD/public/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/public/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wowiwj/Note/HEAD/public/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/public/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wowiwj/Note/HEAD/public/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wowiwj/Note/HEAD/public/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/public/vendor/horizon/css/app.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"/css/app.css","sources":[],"mappings":";;;;;A","sourceRoot":""}
--------------------------------------------------------------------------------
/public/vendor/horizon/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wowiwj/Note/HEAD/public/vendor/horizon/img/favicon.png
--------------------------------------------------------------------------------
/resources/views/vendor/mail/html/table.blade.php:
--------------------------------------------------------------------------------
1 |
config('app.url')])
5 | {{ config('app.name') }}
6 | @endcomponent
7 | @endslot
8 |
9 | {{-- Body --}}
10 | {{ $slot }}
11 |
12 | {{-- Subcopy --}}
13 | @isset($subcopy)
14 | @slot('subcopy')
15 | @component('mail::subcopy')
16 | {{ $subcopy }}
17 | @endcomponent
18 | @endslot
19 | @endisset
20 |
21 | {{-- Footer --}}
22 | @slot('footer')
23 | @component('mail::footer')
24 | © {{ date('Y') }} {{ config('app.name') }}. All rights reserved.
25 | @endcomponent
26 | @endslot
27 | @endcomponent
28 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/markdown/message.blade.php:
--------------------------------------------------------------------------------
1 | @component('mail::layout')
2 | {{-- Header --}}
3 | @slot('header')
4 | @component('mail::header', ['url' => config('app.url')])
5 | {{ config('app.name') }}
6 | @endcomponent
7 | @endslot
8 |
9 | {{-- Body --}}
10 | {{ $slot }}
11 |
12 | {{-- Subcopy --}}
13 | @isset($subcopy)
14 | @slot('subcopy')
15 | @component('mail::subcopy')
16 | {{ $subcopy }}
17 | @endcomponent
18 | @endslot
19 | @endisset
20 |
21 | {{-- Footer --}}
22 | @slot('footer')
23 | @component('mail::footer')
24 | © {{ date('Y') }} {{ config('app.name') }}. All rights reserved.
25 | @endcomponent
26 | @endslot
27 | @endcomponent
28 |
--------------------------------------------------------------------------------
/resources/assets/js/global.js:
--------------------------------------------------------------------------------
1 | // 全局消息
2 | window.events = new Vue();
3 |
4 | window.flash = function(text,level='success'){
5 |
6 | var message = {'text':text,'level':level};
7 | window.events.$emit('flash',message);
8 | };
9 |
10 | window.showLogin = function(){
11 |
12 | window.events.$emit('login');
13 | }
14 |
15 | window.showLoginConfirm = function () {
16 |
17 | this.$dialog.confirm({
18 | message: '请登录后再执行操作',
19 | onConfirm: () => window.showLogin()
20 | })
21 |
22 | }
23 |
24 | // axios 钩子
25 | axios.interceptors.response.use(function(response){
26 | return response;
27 | },function(error){
28 |
29 | if (error.response.status === 401){
30 |
31 | window.showLogin()
32 | }
33 | return Promise.reject(error);
34 | });
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/Base/Handler/NotificationHandler.php:
--------------------------------------------------------------------------------
1 | notification = $notification;
20 |
21 | return $this->mapObject();
22 |
23 | }
24 |
25 | private function mapObject(){
26 |
27 | $type = $this->notification->type;
28 | $class = new \ReflectionClass($type);
29 | if ($class->implementsInterface(NotificationMappable::class)){
30 | return $type::map($this->notification->data);
31 | }
32 |
33 | return null;
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/app/Http/Resources/CommentResource.php:
--------------------------------------------------------------------------------
1 | $this->id,
20 | 'body' => $this->body,
21 | 'created_at' => $this->created_at->toDateTimeString(),
22 | 'is_favorite' => $this->isFavorited,
23 | 'favorite_count' => $this->favoritesCount,
24 | 'user' => new UserCollection($this->user)
25 | ];
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/resources/views/notifications/partials/article_was_subscribed.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
17 |
--------------------------------------------------------------------------------
/resources/views/notifications/partials/article_was_favorited.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
17 |
--------------------------------------------------------------------------------
/resources/views/notifications/partials/comment_was_favorited.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 | {{ $message->user->name }}
11 | 喜欢了你的评论
12 | •
13 | {{ $notification->created_at->diffForHumans() }}
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/resources/views/notifications/partials/discussion_was_favorited.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
17 |
--------------------------------------------------------------------------------
/resources/views/vendor/mail/html/button.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | |
7 |
14 | |
15 |
16 |
17 | |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/resources/views/notifications/partials/discussion_was_subscribed.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
17 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/FilesController.php:
--------------------------------------------------------------------------------
1 | middleware('auth:api');
15 | }
16 |
17 | public function ImageUpload(Request $request)
18 | {
19 |
20 | if (!$request->hasFile('file')){
21 | return $this->failed('上传文件不能为空');
22 | }
23 |
24 |
25 | $file = $request->file('file');
26 |
27 | $imageHander = new ImageUploadHandler();
28 | $result = $imageHander->uploadImage($file);
29 |
30 | return $this->success([
31 | 'image' => '/'.$result['filename']
32 | ]);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/resources/views/users/activities/created_comment.blade.php:
--------------------------------------------------------------------------------
1 | @component('users.activities.activity')
2 | @slot('heading')
3 |
4 | @if($activity->subject->commentable instanceof \App\Models\SpecialPage)
5 | {{ $user->name }} 评论页面
6 |
7 | "{{ $activity->subject->commentable['title'] }}"
8 |
9 | @else
10 | {{ $user->name }} 评论文章
11 |
12 | "{{ $activity->subject->commentable['title'] }}"
13 |
14 | @endif
15 |
16 | @endslot
17 |
18 | @slot('body')
19 |
20 | @endslot
21 | @endcomponent
--------------------------------------------------------------------------------
/database/migrations/2017_05_28_025409_create_categories_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->string('name',50);
19 | $table->string('slug');
20 | $table->timestamps();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down()
30 | {
31 | Schema::dropIfExists('categories');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/resources/assets/sass/vender/fontawesome/fa-brands.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com
3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Brands';
9 | font-style: normal;
10 | font-weight: normal;
11 | src: url('#{$fa-font-path}/fa-brands-400.eot');
12 | src: url('#{$fa-font-path}/fa-brands-400.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-brands-400.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-brands-400.svg#fontawesome') format('svg');
17 | }
18 |
19 | .fab {
20 | font-family: 'Font Awesome 5 Brands';
21 | }
22 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/resources/assets/sass/vender/fontawesome/fa-solid.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com
3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Free';
9 | font-style: normal;
10 | font-weight: 900;
11 | src: url('#{$fa-font-path}/fa-solid-900.eot');
12 | src: url('#{$fa-font-path}/fa-solid-900.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-solid-900.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-solid-900.svg#fontawesome') format('svg');
17 | }
18 |
19 | .fa,
20 | .fas {
21 | font-family: 'Font Awesome 5 Free';
22 | font-weight: 900;
23 | }
24 |
--------------------------------------------------------------------------------
/resources/lang/en/passwords.php:
--------------------------------------------------------------------------------
1 | 'Passwords must be at least six characters and match the confirmation.',
17 | 'reset' => 'Your password has been reset!',
18 | 'sent' => 'We have e-mailed your password reset link!',
19 | 'token' => 'This password reset token is invalid.',
20 | 'user' => "We can't find a user with that e-mail address.",
21 |
22 | ];
23 |
--------------------------------------------------------------------------------
/resources/assets/sass/vender/fontawesome/fa-regular.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome Free 5.0.6 by @fontawesome - http://fontawesome.com
3 | * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4 | */
5 | @import 'variables';
6 |
7 | @font-face {
8 | font-family: 'Font Awesome 5 Free';
9 | font-style: normal;
10 | font-weight: 400;
11 | src: url('#{$fa-font-path}/fa-regular-400.eot');
12 | src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'),
13 | url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
14 | url('#{$fa-font-path}/fa-regular-400.woff') format('woff'),
15 | url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'),
16 | url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg');
17 | }
18 |
19 | .far {
20 | font-family: 'Font Awesome 5 Free';
21 | font-weight: 400;
22 | }
23 |
--------------------------------------------------------------------------------
/resources/views/vendor/pagination/simple-bootstrap-4.blade.php:
--------------------------------------------------------------------------------
1 | @if ($paginator->hasPages())
2 |
17 | @endif
18 |
--------------------------------------------------------------------------------
/app/Http/Flash.php:
--------------------------------------------------------------------------------
1 | flash($key,[
11 | 'text'=>$message,
12 | 'level'=>$level
13 | ]);
14 |
15 | }
16 |
17 | public function message($message,$level='info')
18 | {
19 |
20 | $this->create($message,$level);
21 |
22 | }
23 |
24 | public function info($message){
25 | $this->message($message);
26 | }
27 |
28 | public function success($message){
29 | $this->message($message,'success');
30 | }
31 |
32 | public function error($title,$message){
33 | $this->message($message,'error');
34 | }
35 |
36 | public function overlay($message,$level='info'){
37 | $this->create($message,$level,'flash_message_overlay');
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/resources/views/notifications/partials/article_was_updated.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
19 |
--------------------------------------------------------------------------------
/webpack.mix.js:
--------------------------------------------------------------------------------
1 | const { mix } = require('laravel-mix');
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | Mix Asset Management
6 | |--------------------------------------------------------------------------
7 | |
8 | | Mix provides a clean, fluent API for defining some Webpack build steps
9 | | for your Laravel application. By default, we are compiling the Sass
10 | | file for the application as well as bundling up all the JS files.
11 | |
12 | */
13 |
14 | mix.js('resources/assets/js/app.js', 'public/js')
15 | .sass('resources/assets/sass/app.scss', 'public/css')
16 | .js('resources/assets/js/home.js', 'public/js')
17 | .sass('resources/assets/sass/home.scss', 'public/css')
18 | .extract(['vue','buefy','vue-multiselect','moment']);
19 |
20 | if (mix.inProduction) {
21 | mix.version();
22 | }
23 |
24 | // mix.browserSync('note.com');
25 |
26 |
--------------------------------------------------------------------------------
/resources/assets/sass/vender/fontawesome/_rotated-flipped.scss:
--------------------------------------------------------------------------------
1 | // Rotated & Flipped Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); }
5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
7 |
8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); }
10 | .#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(-1, -1, 2); }
11 |
12 | // Hook for IE8-9
13 | // -------------------------
14 |
15 | :root {
16 | .#{$fa-css-prefix}-rotate-90,
17 | .#{$fa-css-prefix}-rotate-180,
18 | .#{$fa-css-prefix}-rotate-270,
19 | .#{$fa-css-prefix}-flip-horizontal,
20 | .#{$fa-css-prefix}-flip-vertical {
21 | filter: none;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/Http/Resources/DiscussionResource.php:
--------------------------------------------------------------------------------
1 | $this->id,
20 | 'title' => $this->title,
21 | 'page_image' => $this->page_image,
22 | 'body' => $this->body,
23 | 'created_at' => $this->created_at,
24 | 'user' => new UserResource($this->whenLoaded('user')),
25 | 'tags' => TagResource::collection($this->whenLoaded('tags')),
26 | 'best_answer' => new CommentResource($this->bestAnswer)
27 |
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/database/migrations/2017_05_28_031123_create_tags_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->string('name')->unique();
19 | $table->string('slug')->unique();
20 | $table->text('message')->nullable();
21 | $table->timestamps();
22 | });
23 | }
24 |
25 | /**
26 | * Reverse the migrations.
27 | *
28 | * @return void
29 | */
30 | public function down()
31 | {
32 | Schema::dropIfExists('tags');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/database/migrations/2017_05_28_030133_create_replies_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('article_id');
19 | $table->unsignedSmallInteger('user_id');
20 | $table->text('body');
21 | $table->timestamps();
22 | });
23 | }
24 |
25 | /**
26 | * Reverse the migrations.
27 | *
28 | * @return void
29 | */
30 | public function down()
31 | {
32 | Schema::dropIfExists('replies');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/resources/assets/js/components/Parse.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/resources/assets/sass/home.scss:
--------------------------------------------------------------------------------
1 | // 后台 管理 的css
2 |
3 | @import url("https://fonts.googleapis.com/icon?family=Material+Icons");
4 |
5 | @import "variables";
6 |
7 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fontawesome';
8 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fa-brands';
9 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fa-regular';
10 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fa-solid';
11 |
12 | @import "node_modules/bulma/bulma";
13 |
14 | @import "node_modules/buefy/src/scss/buefy";
15 |
16 | .body{
17 |
18 | background-color: #eee;
19 | }
20 |
21 |
22 | .slide-menu{
23 |
24 | padding-left: 2em;
25 | padding-top: 20px;
26 |
27 | }
28 |
29 | .main-content{
30 |
31 | padding-top: 20px;
32 | padding-right: 25px;
33 |
34 | background-color: #ddd;
35 |
36 | }
37 |
38 | li{
39 |
40 | list-style: none;
41 |
42 | }
--------------------------------------------------------------------------------
/database/migrations/2017_05_28_031151_create_taggables_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('tag_id');
19 | $table->unsignedInteger('taggable_id');
20 | $table->string('taggable_type','50');
21 |
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('taggables');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/resources/assets/js/components/Example.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Example Component
7 |
8 |
9 |
10 | I'm an example component!
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
44 |
--------------------------------------------------------------------------------
/app/Base/Filters/Filters.php:
--------------------------------------------------------------------------------
1 | request = $request;
18 | }
19 |
20 | public function apply(Builder $builder)
21 | {
22 | $this->builder = $builder;
23 |
24 | foreach ($this->getFitters() as $filter => $value){
25 | if (method_exists($this,$filter)){
26 | $this->$filter($value);
27 | }
28 | }
29 | }
30 |
31 | public function getFitters()
32 | {
33 | return $this->request->only($this->filters);
34 | }
35 |
36 | public function setFilters($fitter,$value){
37 | $this->filters[$fitter] = $value;
38 | }
39 |
40 |
41 | }
--------------------------------------------------------------------------------
/app/Providers/OAuthServiceProvider.php:
--------------------------------------------------------------------------------
1 | app->make('Laravel\Socialite\Contracts\Factory')->extend('qq', function ($app) {
18 | $config = $app['config']['services.qq'];
19 | return new QQProvider(
20 | $app['request'],
21 | $config['client_id'],
22 | $config['client_secret'],
23 | $config['redirect']
24 | );
25 | });
26 | }
27 |
28 | /**
29 | * Register the application services.
30 | *
31 | * @return void
32 | */
33 | public function register()
34 | {
35 | //
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/database/migrations/2017_06_22_100627_create_special_pages_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->boolean('show_nav')->default(true);
19 | $table->string('route');
20 | $table->string('title');
21 | $table->text('body');
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('special_pages');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/database/migrations/2017_05_28_030521_create_activities_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('user_id');
19 | $table->unsignedInteger('subject_id');
20 | $table->string('subject_type',50);
21 | $table->string('type',50);
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('activities');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/database/migrations/2018_01_14_204314_create_notifications_table.php:
--------------------------------------------------------------------------------
1 | uuid('id')->primary();
18 | $table->string('type');
19 | $table->morphs('notifiable');
20 | $table->text('data');
21 | $table->timestamp('read_at')->nullable();
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('notifications');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/resources/views/notifications/partials/answer_was_update_best.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
7 |
21 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/AuthenticateController.php:
--------------------------------------------------------------------------------
1 | validate($request, [
15 | 'email' => 'required|email|max:255',
16 | 'password' => 'required|string'
17 | ]);
18 |
19 | $credentials = $request->only(['email','password']);
20 |
21 | if (Auth::attempt($credentials,true)) {
22 |
23 | if (Auth::user()->activated) {
24 | return $this->message('登录成功');
25 | }else{
26 | Auth::logout();
27 |
28 | return $this->failed('账号未激活,请使用邮件链接激活邮箱');
29 | }
30 |
31 | } else {
32 |
33 | return $this->failed('用户名或密码错误');
34 | }
35 |
36 |
37 |
38 |
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/database/migrations/2018_02_27_171949_create_failed_jobs_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('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 |
--------------------------------------------------------------------------------
/resources/assets/sass/overrite.scss:
--------------------------------------------------------------------------------
1 |
2 | .card{
3 | box-shadow:none;
4 | box-shadow: 0 1px 2px 0 rgba(0,0,0,.05);
5 |
6 |
7 |
8 | .card-header{
9 | box-shadow: none;
10 | border-bottom: 1px solid hsla(0,0%,59%,.1);
11 |
12 |
13 | .card-header-title{
14 |
15 | font-weight:500;
16 |
17 | padding: 0.63em;
18 | padding-left: 1em;
19 | }
20 |
21 | .card-header-icon{
22 |
23 | padding: 0.63em;
24 | }
25 |
26 | .card-header-icon{
27 |
28 | font-size: 13px;
29 | }
30 |
31 |
32 |
33 | }
34 | }
35 |
36 | .nopadding{
37 | padding:0;
38 | }
39 |
40 | .icon .fa, .icon .mdi {
41 | font-size: inherit;
42 | }
43 |
44 | .social-share .social-share-icon {
45 | position: relative;
46 | display: inline-block;
47 | width: 20px;
48 | height: 20px;
49 | font-size: 10px;
50 | border-radius: 50%;
51 | line-height: 20px;
52 | text-align: center;
53 | vertical-align: middle;
54 | transition: background 0.6s ease-out 0s;
55 | }
--------------------------------------------------------------------------------
/app/Base/Traits/SlugTransable.php:
--------------------------------------------------------------------------------
1 | getAttributes();
33 | $translate = 'name';
34 |
35 | if (! array_key_exists('slug', $attributes)) {
36 | return;
37 | }
38 |
39 | if (array_key_exists('title', $attributes)) {
40 | $translate = 'title';
41 | }
42 |
43 | dispatch(new TranslateSlug($model,$translate));
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/app/Console/Kernel.php:
--------------------------------------------------------------------------------
1 | command('inspire')
28 | // ->hourly();
29 | }
30 |
31 | /**
32 | * Register the Closure based commands for the application.
33 | *
34 | * @return void
35 | */
36 | protected function commands()
37 | {
38 | require base_path('routes/console.php');
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/SubscriptionsController.php:
--------------------------------------------------------------------------------
1 | middleware('auth:api');
15 | }
16 |
17 |
18 | public function store(SubscribeRequest $request){
19 |
20 | try{
21 | $request->subscribe();
22 | }catch(SubscribeException $e){
23 | return $e->response();
24 | }
25 |
26 | $request->getModel()->notify();
27 |
28 | return $this->message('点赞成功');
29 | }
30 |
31 |
32 | public function destroy(SubscribeRequest $request){
33 |
34 | try{
35 | $request->unsubscribe();
36 | }catch(SubscribeException $e){
37 | return $e->response();
38 | }
39 | return $this->message('取消点赞成功');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/resources/views/layouts/partials/category.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 | @forelse($popular_categories as $item)
16 |
17 |
23 | @empty
24 |
没有分类数据
25 | @endforelse
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/database/migrations/2017_05_28_030506_create_favorites_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('user_id');
19 | $table->unsignedInteger('favorited_id');
20 | $table->string('favorited_type',50);
21 | $table->timestamps();
22 | $table->unique(['user_id','favorited_id','favorited_type']);
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('favorites');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/database/migrations/2017_06_01_095839_create_comments_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('user_id');
19 | $table->text('body');
20 | $table->unsignedInteger('commentable_id');
21 | $table->string('commentable_type',50);
22 | $table->softDeletes();
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('comments');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/CategoriesController.php:
--------------------------------------------------------------------------------
1 | orderBy('articles_count','desc')
16 | ->limit(10)
17 | ->get();
18 |
19 |
20 |
21 | return $categories;
22 | }
23 | public function create()
24 | {
25 | return view('categories.create');
26 | }
27 |
28 | public function store(Request $request)
29 | {
30 | $this->validate($request,[
31 | 'name' => 'required|unique:categories',
32 | 'slug' => 'required|unique:categories',
33 | ]);
34 |
35 | Category::create($request->only('name','slug'));
36 |
37 | alert('分类添加成功','success');
38 | return back();
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/Http/Requests/UpdateUserRequest.php:
--------------------------------------------------------------------------------
1 | only($this->allowed_field));
28 | $user->update($data);
29 | return $user;
30 | }
31 |
32 | /**
33 | * Get the validation rules that apply to the request.
34 | *
35 | * @return array
36 | */
37 | public function rules()
38 | {
39 | return [
40 | 'name' => 'string',
41 | 'signature' => 'max:26'
42 | ];
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/DraftsController.php:
--------------------------------------------------------------------------------
1 | middleware('auth');
16 | }
17 |
18 | public function index(){
19 |
20 | $user = Auth::user();
21 |
22 | $drafts = $user->drafts()->whereNull('parent_id')->latest()->paginate(10);
23 |
24 | return view('drafts.index',compact('user','drafts'));
25 | }
26 |
27 | public function show($draft){
28 |
29 | return view('drafts.show');
30 | }
31 |
32 | public function edit(Draft $draft){
33 | return view('drafts.edit',compact('draft'));
34 |
35 | }
36 |
37 | public function destroy(Draft $draft){
38 | $draft->delete();
39 | flash('删除成功');
40 | return back();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/resources/assets/js/components/Home/Menus.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/UsersController.php:
--------------------------------------------------------------------------------
1 | middleware('auth:api');
14 | }
15 |
16 | public function uploadAvatar(Request $request){
17 |
18 | $this->validate($request,[
19 | 'img' => 'required|image'
20 |
21 | ]);
22 |
23 | $user = Auth::user();
24 |
25 | $imageHander = new ImageUploadHandler();
26 |
27 |
28 | $avatar = $request->file('img');
29 | $result = $imageHander->uploadAvatar($avatar,$user);
30 |
31 | $avatarPath = '/'.$imageHander->avatarPath().'/'.$result['filename'];
32 |
33 | $user->avatar = $avatarPath;
34 | $user->save();
35 |
36 | return $this->success([
37 | 'avatar' => $avatarPath
38 | ]);
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/database/migrations/2017_12_13_225211_create_subscriptions_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('user_id');
19 | $table->unsignedInteger('subscribable_id');
20 | $table->string('subscribable_type');
21 | $table->unique(['user_id','subscribable_id','subscribable_type']);
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('subscriptions');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/Models/Tag.php:
--------------------------------------------------------------------------------
1 | morphedByMany(Article::class,'taggable');
17 | }
18 |
19 | public function discussions(){
20 | return $this->morphedByMany(Discussion::class,'taggable');
21 | }
22 |
23 | public function path($name = null){
24 |
25 | $path = '?tag='.$this->name;
26 |
27 |
28 | if ($name){
29 | return url()->route($name).$path;
30 | }
31 |
32 | return $path;
33 |
34 | }
35 |
36 | protected static function boot()
37 | {
38 | parent::boot();
39 |
40 | static::creating(function ($model){
41 | $model->slug = app(SlugTranslateHandler::class)->translate($model->name);
42 | });
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/NotificationsController.php:
--------------------------------------------------------------------------------
1 | middleware('auth');
16 | }
17 |
18 | public function index(){
19 |
20 | $limit = Input::get('limit') ?: 30;
21 |
22 | $type = Input::get('type');
23 | $notifications = [];
24 | $user = Auth::user();
25 | if ($type == 'unread'){
26 | $notifications = $user->unreadNotifications()->paginate($limit);
27 | $notifications->markAsRead();
28 | }else{
29 | $notifications = $user->notifications()->paginate($limit);
30 | }
31 |
32 | $notifications->appends(Input::except('page'));
33 |
34 | return view('notifications.index',compact('notifications'));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/ForgotPasswordController.php:
--------------------------------------------------------------------------------
1 | middleware('guest');
32 | }
33 |
34 |
35 |
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/database/migrations/2017_12_10_223853_add_outh_field_to_users_table.php:
--------------------------------------------------------------------------------
1 | integer('github_id')->nullable()->after('is_admin');
19 | $table->string('github_name')->nullable()->after('is_admin');
20 | $table->string('github_url')->nullable()->after('is_admin');
21 |
22 | $table->string('qq_openid')->nullable()->after('is_admin');
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::table('users', function (Blueprint $table) {
34 | //
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/resources/views/discussions/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('title','评论首页')
4 |
5 |
6 | @section('content')
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | @forelse($discussions as $discussion)
15 | @include('discussions.partials.discussion')
16 | @empty
17 |
没有提问数据
18 | @endforelse
19 |
20 |
21 | {{ $discussions->links('vendor.pagination.default') }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | @include('discussions.partials.filter')
32 |
33 |
34 |
35 |
36 |
37 |
38 | @endsection
--------------------------------------------------------------------------------
/resources/views/articles/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 |
4 | @section('content')
5 |
6 |
7 |
8 |
9 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
34 |
35 | 这是奥克兰发还发爱古法卡法咖啡馆花费
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | @endsection
--------------------------------------------------------------------------------
/app/Base/Traits/ContentSetable.php:
--------------------------------------------------------------------------------
1 | convertMarkdownToHtml($value);
15 | $data = [
16 | 'raw' => $value,
17 | 'html' => $html
18 | ];
19 |
20 | if (array_key_exists('page_image', $this->getAttributes())) {
21 | $this->makeContentImage($html);
22 | }
23 |
24 | $this->body = json_encode($data);
25 | }
26 |
27 |
28 | public function makeContentImage($html){
29 |
30 | $pattern = "/[img|IMG].*?src=['|\"](.*?(?:[.gif|.jpg]))['|\"].*?[\/]?>/";
31 | preg_match($pattern,$html,$match);
32 | if (empty($match) || is_null($match[1])){
33 | return;
34 | }
35 | $content_image = (new ImageUploadHandler())
36 | ->makeArticleImage($match[1],'');
37 | $this->page_image = $content_image;
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/resources/views/special_pages/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 | 编辑页面
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 | 这是奥克兰发还发爱古法卡法咖啡馆花费
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | @endsection
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | APP_NAME=Laravel
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_LOG_LEVEL=debug
6 | APP_URL=http://localhost
7 |
8 | LOG_CHANNEL=stack
9 |
10 | DB_CONNECTION=mysql
11 | DB_HOST=127.0.0.1
12 | DB_PORT=3306
13 | DB_DATABASE=homestead
14 | DB_USERNAME=homestead
15 | DB_PASSWORD=secret
16 |
17 | BROADCAST_DRIVER=log
18 | CACHE_DRIVER=file
19 | SESSION_DRIVER=file
20 | QUEUE_DRIVER=sync
21 |
22 | REDIS_HOST=127.0.0.1
23 | REDIS_PASSWORD=null
24 | REDIS_PORT=6379
25 |
26 | MAIL_DRIVER=smtp
27 | MAIL_HOST=smtp.mailtrap.io
28 | MAIL_PORT=2525
29 | MAIL_USERNAME=null
30 | MAIL_PASSWORD=null
31 | MAIL_ENCRYPTION=null
32 |
33 |
34 | # send cloud 配置
35 | # send cloud 配置,打开当前driver,关闭上面的 MAIL_DRIVER,并设置user和key
36 | # MAIL_DRIVER=sendcloud
37 | SEND_CLOUD_USER=
38 | SEND_CLOUD_KEY=
39 |
40 |
41 | PUSHER_APP_ID=
42 | PUSHER_APP_KEY=
43 | PUSHER_APP_SECRET=
44 |
45 | # 谷歌分析配置
46 | GOOGLE_ANALYTICS_ID=
47 |
48 | # github第三方登录配置
49 | GITHUB_CLIENT_ID=
50 | GITHUB_CLIENT_SECRET=
51 |
52 | # qq第三方登录配置
53 | QQ_CLIENT_ID=
54 | QQ_CLIENT_SECRET=
55 |
56 | # 百度翻译配置
57 | BAIDU_TRANSLATE_APPID=
58 | BAIDU_TRANSLATE_KEY=
59 |
--------------------------------------------------------------------------------
/resources/views/notifications/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 |
6 |
7 |
8 | @include('notifications.partials.nav')
9 |
10 |
11 |
12 |
13 |
14 |
15 | 我的提醒
16 |
17 |
18 | @forelse ($notifications as $notification)
19 |
20 | @if (view()->exists("notifications.partials.".snake_case(class_basename($notification->type))))
21 | @include ("notifications.partials.".snake_case(class_basename($notification->type)), [
22 | 'message' => notification_parser($notification),
23 | 'notification' => $notification
24 | ])
25 | @endif
26 | @empty
27 |
暂时没有任何消息哦
28 | @endforelse
29 |
30 | {{ $notifications->links() }}
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | @endsection
--------------------------------------------------------------------------------
/database/migrations/2017_11_19_115928_seed_special_pages_data.php:
--------------------------------------------------------------------------------
1 | 1,
19 | 'route' => 'about',
20 | 'title' => '关于',
21 | 'body' => '关于界面'
22 | ],
23 | [
24 | 'show_nav' => 1,
25 | 'route' => 'message',
26 | 'title' => '留言板',
27 | 'body' => '留言板界面'
28 | ]
29 |
30 |
31 | ];
32 |
33 | DB::table('special_pages')->insert($pages);
34 |
35 |
36 | }
37 |
38 | /**
39 | * Reverse the migrations.
40 | *
41 | * @return void
42 | */
43 | public function down()
44 | {
45 | DB::table('special_pages')->truncate();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/Http/Requests/SubscribeRequest.php:
--------------------------------------------------------------------------------
1 | Article::class,
19 | 'discussion' => Discussion::class
20 | ];
21 | }
22 |
23 | /**
24 | * Determine if the user is authorized to make this request.
25 | *
26 | * @return bool
27 | */
28 | public function authorize()
29 | {
30 | return true;
31 | }
32 |
33 |
34 | // 用户订阅
35 | public function subscribe()
36 | {
37 | $model = $this->getModel();
38 | return $model->subscribe();
39 |
40 | }
41 |
42 | // 用户取消订阅
43 | public function unsubscribe()
44 | {
45 | $model = $this->getModel();
46 | if($model->isSubscribed){
47 | $model->unsubscribe();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/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' => realpath(storage_path('framework/views')),
32 |
33 | ];
34 |
--------------------------------------------------------------------------------
/database/migrations/2018_02_06_142849_create_drafts_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('user_id');
19 | $table->unsignedInteger('parent_id')->nullable();
20 | $table->unsignedInteger('relation_id')->nullable();
21 | $table->string('relation_type')->nullable();
22 | $table->string('title');
23 | $table->string('slug')->nullable();
24 | $table->text('body');
25 | $table->timestamps();
26 | });
27 | }
28 |
29 | /**
30 | * Reverse the migrations.
31 | *
32 | * @return void
33 | */
34 | public function down()
35 | {
36 | Schema::dropIfExists('drafts');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Auth/ResetPasswordController.php:
--------------------------------------------------------------------------------
1 | middleware('guest');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/Http/Resources/ArticleResource.php:
--------------------------------------------------------------------------------
1 | $this->id,
24 | 'title' => $this->title,
25 | 'page_image' => $this->page_image,
26 | 'body' => $this->body,
27 | 'is_original' => $this->is_original,
28 | 'published_at' => $this->published_at,
29 | 'user' => new UserCollection($this->whenLoaded('user')),
30 | 'category' => new CategoryCollection($this->whenLoaded('category')),
31 | 'tags' => TagCollection::collection($this->whenLoaded('tags'))
32 | ];
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Admin/UsersController.php:
--------------------------------------------------------------------------------
1 | validate($request,[
29 | 'name' => 'string',
30 | 'signature' => 'max:26',
31 | 'email' => 'email'
32 | ]);
33 |
34 | $user->update($request->only(['name','signature','email']));
35 |
36 | flash('修改成功')->success();
37 |
38 | return back();
39 | }
40 |
41 | public function destroy(User $user){
42 |
43 | $user->delete();
44 |
45 | flash('删除成功')->success();
46 |
47 | return back();
48 |
49 | }
50 |
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/Http/Requests/FavoriteRequest.php:
--------------------------------------------------------------------------------
1 | Comment::class,
20 | 'article' => Article::class,
21 | 'discussions' => Discussion::class
22 | ];
23 | }
24 |
25 | /**
26 | * Determine if the user is authorized to make this request.
27 | *
28 | * @return bool
29 | */
30 | public function authorize()
31 | {
32 | return true;
33 | }
34 |
35 | // 用户点赞
36 | public function store()
37 | {
38 | $model = $this->getModel();
39 | return $model->favorite();
40 | }
41 |
42 | // 用户取消点赞
43 | public function destroy()
44 | {
45 | $model = $this->getModel();
46 | if($model->isFavorited){
47 | $model->unfavorite();
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/resources/views/articles/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 |
4 | @section('content')
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
37 |
38 |
39 | 这是奥克兰发还发爱古法卡法咖啡馆花费
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | @endsection
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/SpecialPagesController.php:
--------------------------------------------------------------------------------
1 | middleware(['auth','admin'])->except(['show']);
15 | }
16 |
17 |
18 | public function index(){
19 |
20 |
21 |
22 | }
23 |
24 | public function edit(SpecialPage $page){
25 |
26 | return view('special_pages.edit',compact('page'));
27 | }
28 |
29 | public function show($name){
30 |
31 | $page = SpecialPage::where('route',$name)->firstOrFail();
32 |
33 | return view('special_pages.show',compact('page'));
34 | }
35 |
36 | public function create(){
37 |
38 | return view('special_pages.create');
39 | }
40 |
41 |
42 | public function store(){
43 |
44 |
45 |
46 | }
47 |
48 | public function destroy(SpecialPage $page){
49 |
50 |
51 | $page->delete();
52 |
53 | $page->comments->each->delete();
54 |
55 | alert('页面删除成功','success');
56 |
57 | return redirect('/');
58 | }
59 |
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/resources/assets/js/components/BestAnswer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/Base/Filters/ArticleFilters.php:
--------------------------------------------------------------------------------
1 | firstOrFail();
21 |
22 | return $this->builder->where('user_id',$user->id);
23 | }
24 |
25 | protected function popular()
26 | {
27 | $this->builder->getQuery()->orders = [];
28 |
29 | return $this->builder
30 | ->withCount('comments')
31 | ->orderBy('comments_count','desc');
32 | }
33 |
34 | protected function uncommented(){
35 | $this->builder->getQuery()->orders = [];
36 | return $this->builder
37 | ->has('comments','=',0);
38 | }
39 |
40 | public function tag($name){
41 |
42 | return $this->builder->whereHas('tags',function ($query) use ($name){
43 | $query->where('slug',$name)->orWhere('name',$name);
44 | });
45 | }
46 |
47 | public function archive($date){
48 |
49 | dd($date);
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/database/migrations/2018_01_29_211051_create_discussions_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('user_id');
19 | $table->string('page_image')->nullable();
20 | $table->string('title');
21 | $table->string('slug')->nullable();
22 | $table->text('body');
23 | $table->unsignedInteger('views_count')->default(0);
24 | $table->unsignedInteger('solved_id')->nullable();
25 | $table->unsignedInteger('draft_id')->nullable();
26 | $table->timestamps();
27 | $table->softDeletes();
28 | });
29 | }
30 |
31 | /**
32 | * Reverse the migrations.
33 | *
34 | * @return void
35 | */
36 | public function down()
37 | {
38 | Schema::dropIfExists('discussions');
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/resources/views/vendor/flash/message.blade.php:
--------------------------------------------------------------------------------
1 | @foreach (session('flash_notification', collect())->toArray() as $message)
2 | @if ($message['overlay'])
3 | @include('flash::modal', [
4 | 'modalClass' => 'flash-modal',
5 | 'title' => $message['title'],
6 | 'body' => $message['message']
7 | ])
8 | @else
9 |
10 |
11 | {!! $message['message'] !!}
12 |
13 |
14 | {{----}}
19 | {{--@if ($message['important'])--}}
20 | {{----}}
25 | {{--@endif--}}
26 |
27 | {{--{!! $message['message'] !!}--}}
28 | {{--
--}}
29 | @endif
30 | @endforeach
31 |
32 | {{ session()->forget('flash_notification') }}
33 |
--------------------------------------------------------------------------------
/app/Jobs/TranslateSlug.php:
--------------------------------------------------------------------------------
1 | translate = $translate;
30 | $this->field = $field;
31 | }
32 |
33 | /**
34 | * Execute the job.
35 | *
36 | * @return void
37 | */
38 | public function handle()
39 | {
40 |
41 | $field = $this->field;
42 | $slug = app(SlugTranslateHandler::class)->translate($this->translate->$field);
43 |
44 | $this->translate->slug = $slug;
45 | DB::table($this->translate->getTable())->where('id', $this->translate->id)->update(['slug' => $slug]);
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | ./tests/Feature
14 |
15 |
16 |
17 | ./tests/Unit
18 |
19 |
20 |
21 |
22 | ./app
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/resources/assets/sass/app.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | //@import url("https://fonts.googleapis.com/icon?family=Material+Icons");
4 |
5 | @import "variables";
6 |
7 | $modal-content-width:400px;
8 |
9 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fontawesome';
10 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fa-brands';
11 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fa-regular';
12 | @import 'node_modules/@fortawesome/fontawesome-free-webfonts/scss/fa-solid';
13 |
14 |
15 | @import "node_modules/bulma/bulma";
16 |
17 | @import "node_modules/buefy/src/scss/buefy";
18 |
19 | @import "node_modules/social-share.js/dist/css/share.min";
20 |
21 | @import "node_modules/vue-multiselect/dist/vue-multiselect.min";
22 |
23 |
24 |
25 |
26 | // Fonts
27 | //@import url(https://fonts.googleapis.com/css?family=Raleway:300,400,600);
28 | //
29 | // @import url("https://fonts.googleapis.com/icon?family=Material+Icons");
30 | //
31 |
32 | @import "navbar";
33 |
34 | @import "helpers";
35 | //
36 | @import "styles";
37 | //
38 | @import "vender/prism.css";
39 | //
40 | @import "markdown";
41 | //
42 | @import "article";
43 |
44 | @import "discussion";
45 |
46 | //
47 | @import "vender/simplemde.min.css";
48 |
49 | @import "overrite";
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/resources/views/vendor/notifications/email.blade.php:
--------------------------------------------------------------------------------
1 | @component('mail::message')
2 | {{-- Greeting --}}
3 | @if (! empty($greeting))
4 | # {{ $greeting }}
5 | @else
6 | @if ($level == 'error')
7 | # Whoops!
8 | @else
9 | # Hello!
10 | @endif
11 | @endif
12 |
13 | {{-- Intro Lines --}}
14 | @foreach ($introLines as $line)
15 | {{ $line }}
16 |
17 | @endforeach
18 |
19 | {{-- Action Button --}}
20 | @isset($actionText)
21 |
33 | @component('mail::button', ['url' => $actionUrl, 'color' => $color])
34 | {{ $actionText }}
35 | @endcomponent
36 | @endisset
37 |
38 | {{-- Outro Lines --}}
39 | @foreach ($outroLines as $line)
40 | {{ $line }}
41 |
42 | @endforeach
43 |
44 |
45 | @if (! empty($salutation))
46 | {{ $salutation }}
47 | @else
48 | 荣幸之至,
{{ config('app.name') }}
49 | @endif
50 |
51 |
52 | @isset($actionText)
53 | @component('mail::subcopy')
54 | 如果点击 "{{ $actionText }}" 按钮无效, 请拷贝改链接到您的浏览器进行访问: [{{ $actionUrl }}]({{ $actionUrl }})
55 | @endcomponent
56 | @endisset
57 | @endcomponent
58 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->string('name')->unique();
19 | $table->string('signature')->nullable();
20 | $table->string('email')->nullable()->unique();
21 | $table->string('activation_token')->nullable();
22 | $table->boolean('activated')->default(false);
23 | $table->string('password');
24 | $table->string('avatar')->nullable();
25 | $table->json('settings')->nullable();
26 | $table->boolean('is_admin')->default(false);
27 | $table->rememberToken();
28 | $table->timestamps();
29 | });
30 | }
31 |
32 | /**
33 | * Reverse the migrations.
34 | *
35 | * @return void
36 | */
37 | public function down()
38 | {
39 | Schema::dropIfExists('users');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/resources/assets/js/components/Paginator.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
44 |
45 |
--------------------------------------------------------------------------------
/resources/assets/sass/_variables.scss:
--------------------------------------------------------------------------------
1 |
2 | // Body
3 | //$body-bg: #f5f8fa;
4 | $body-bg: #f5f8f9;
5 |
6 | $family-serif: "lato-regular", "Helvetica Neue", Helvetica, Arial, "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
7 |
8 | // Borders
9 | $laravel-border-color: darken($body-bg, 10%);
10 | $list-group-border: #e7eaf1;
11 | $navbar-default-border: #e7eaf1;
12 | //$panel-default-border: $laravel-border-color;
13 | $panel-default-border: #e7eaf1;
14 |
15 | $panel-inner-border: $laravel-border-color;
16 |
17 | // Brands
18 | //$brand-primary: #3097D1;
19 | $brand-primary: #00b5ad;
20 |
21 |
22 | $brand-info: #8eb4cb;
23 | $brand-success: #2ab27b;
24 | $brand-warning: #cbb956;
25 | $brand-danger: #bf5329;
26 |
27 | // Typography
28 | $icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
29 | $font-family-sans-serif: "Raleway", sans-serif;
30 | $font-size-base: 14px;
31 | $line-height-base: 1.6;
32 | $text-color: #636b6f;
33 |
34 | // Navbar
35 | //$navbar-default-bg: #fff;
36 | $navbar-default-bg: rgba(255,255,255,0.9);
37 |
38 | // Buttons
39 | $btn-default-color: $text-color;
40 |
41 | // Inputs
42 | $input-border: lighten($text-color, 40%);
43 | $input-border-focus: lighten($brand-primary, 25%);
44 | $input-color-placeholder: lighten($text-color, 30%);
45 |
46 | // Panels
47 | $panel-default-heading-bg: #fff;
48 |
--------------------------------------------------------------------------------
/app/Base/Helpers.php:
--------------------------------------------------------------------------------
1 | message($message, $level);
15 | }
16 | }
17 |
18 |
19 | if (! function_exists('nav_is_active')) {
20 |
21 | function nav_is_active($name, $route = null)
22 | {
23 | if ($route == null) {
24 | return Route::currentRouteName() == $name ? 'is-active' : '';
25 | }
26 | return request()->url() == route($name, $route) ? 'is-active' : '';
27 |
28 | }
29 | }
30 |
31 | if (! function_exists('menu_is_active')) {
32 |
33 | function menu_is_active($name, $route = null)
34 | {
35 | if ($route == null) {
36 | return Route::currentRouteName() == $name ? 'is-active' : '';
37 | }
38 | return request()->url() == route($name, $route) ? 'is-active' : '';
39 |
40 | }
41 | }
42 |
43 |
44 | if (! function_exists('notification_parser')) {
45 |
46 | function notification_parser($data)
47 | {
48 | $handler = app(NotificationHandler::class);
49 | return $handler->make($data);
50 | }
51 | }
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/SessionsController.php:
--------------------------------------------------------------------------------
1 | validate($request, [
16 | 'email' => 'required|email|max:255',
17 | 'password' => 'required|string'
18 | ]);
19 |
20 | $credentials = [
21 | 'email' => $request->email,
22 | 'password' => $request->password,
23 | ];
24 |
25 | if (Auth::attempt($credentials,true)) {
26 |
27 |
28 |
29 | if (Auth::user()->activated) {
30 |
31 | // return back();
32 |
33 | // flash('尊敬的'.Auth::user()->name.',欢迎回来')->success();
34 | return redirect()->intended(route("users.show", [Auth::user()]));
35 | }else{
36 | Auth::logout();
37 | flash('你的账号未激活,请检查邮箱中的注册邮件进行激活。')->important();
38 |
39 | return back();
40 | }
41 |
42 | } else {
43 |
44 | flash('很抱歉,您的邮箱和密码不匹配')->error()->important();
45 | return redirect()->back();
46 | }
47 |
48 |
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/resources/views/users/show.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 | @component('users.components.user',['user'=>$user])
6 | @forelse ($activities as $date => $activity)
7 |
8 |
9 | @foreach ($activity as $record)
10 | @if (view()->exists("users.activities.{$record->type}"))
11 | @include ("users.activities.{$record->type}", ['activity' => $record])
12 | @endif
13 | @endforeach
14 |
15 |
16 | @empty
17 | 暂时没有任何动态哦
18 | @endforelse
19 | @endcomponent
20 |
21 |
22 | @endsection
23 |
24 | @section('scripts')
25 |
26 |
47 |
48 | @endsection
--------------------------------------------------------------------------------
/app/Base/Service/Markdowner.php:
--------------------------------------------------------------------------------
1 | htmlConverter = new HtmlConverter();
25 |
26 | $this->markdownConverter = new Parsedown();
27 | }
28 |
29 | /**
30 | * Convert Markdown To Html.
31 | *
32 | * @param $markdown
33 | * @return string
34 | */
35 | public function convertMarkdownToHtml($markdown)
36 | {
37 | $convertedHmtl = $this->markdownConverter
38 | ->setBreaksEnabled(true)
39 | ->text($markdown);
40 | //$convertedHmtl = str_replace("", '', $convertedHmtl);
41 | return $convertedHmtl;
42 |
43 | }
44 |
45 | /**
46 | * Convert Html To Markdown.
47 | *
48 | * @param $html
49 | * @return string
50 | */
51 | public function convertHtmlToMarkdown($html)
52 | {
53 | return $this->htmlConverter->convert($html);
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/app/Base/Traits/GetModelByMorpType.php:
--------------------------------------------------------------------------------
1 | method()){
15 | case 'GET':
16 | return [];
17 | default:
18 | return [
19 | 'type' => 'required',
20 | 'type_id' => 'required'
21 | ];
22 | }
23 | }
24 |
25 | protected function map(){
26 |
27 | return [];
28 | }
29 |
30 | protected function getModelClass($type = null)
31 | {
32 | if ($type == null){
33 | $type = $this->get('type');
34 | }
35 | return $this->map()[$type];
36 | }
37 |
38 | public function getModel($type = null,$type_id = null)
39 | {
40 |
41 |
42 | $modelClass = $this->getModelClass($type);
43 | if(! $modelClass){
44 | throw new FavoriteException('type参数有误',400);
45 | }
46 | $model = $modelClass::find($type_id ?? $this->type_id);
47 |
48 | if(! $model){
49 | throw new FavoriteException('模型未找到',404);
50 | }
51 | return $model;
52 |
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/DraftsController.php:
--------------------------------------------------------------------------------
1 | middleware('auth:api');
17 | }
18 |
19 | public function show(Draft $draft){
20 | $lastUpdate = $draft;
21 | if ($draft->children()->count() > 0){
22 | $lastUpdate = $draft->children()->latest()->first();
23 | }
24 | return new DraftResource($lastUpdate->load(['user','relation']));
25 | }
26 |
27 | public function update(Request $request,Draft $draft){
28 |
29 | $this->validate($request,[
30 | 'title' => 'required',
31 | 'body' => ''
32 | ]);
33 | $fields = $request->except('_method');
34 |
35 | if (!$request->get('body')){
36 | $fields['body'] = '';
37 | }
38 |
39 | $newDraft = $draft->children()->create($fields + [
40 | 'user_id' => Auth::id()
41 | ]);
42 | $newDraft->relation_id = $draft->relation_id;
43 | $newDraft->relation_type = $draft->relation_type;
44 | $newDraft->save();
45 | return $this->message('保存成功');
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/config/trustedproxy.php:
--------------------------------------------------------------------------------
1 | null, // [,], '*'
19 |
20 | /*
21 | * To trust one or more specific proxies that connect
22 | * directly to your server, use an array of IP addresses:
23 | */
24 | # 'proxies' => ['192.168.1.1'],
25 |
26 | /*
27 | * Or, to trust all proxies that connect
28 | * directly to your server, use a "*"
29 | */
30 | # 'proxies' => '*',
31 |
32 | /*
33 | * Which headers to use to detect proxy related data (For, Host, Proto, Port)
34 | *
35 | * Options include:
36 | *
37 | * - Illuminate\Http\Request::HEADER_X_FORWARDED_ALL (use all x-forwarded-* headers to establish trust)
38 | * - Illuminate\Http\Request::HEADER_FORWARDED (use the FORWARDED header to establish trust)
39 | *
40 | * @link https://symfony.com/doc/current/deployment/proxies.html
41 | */
42 | 'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL,
43 |
44 |
45 | ];
46 |
--------------------------------------------------------------------------------
/resources/assets/js/pages/Article.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/Base/Traits/Subscribable.php:
--------------------------------------------------------------------------------
1 | subscriptions()->firstOrCreate([
11 | 'user_id' => $userId ?: auth()->id()
12 | ]);
13 | }
14 |
15 | public function unsubscribe($userId = null){
16 |
17 | $this->subscriptions()
18 | ->where('user_id',$userId ?: auth()->id())
19 | ->delete();
20 |
21 | }
22 |
23 | /**
24 | * Determine if the current type has been subscribed.
25 | *
26 | * @return boolean
27 | */
28 | public function isSubscribed()
29 | {
30 | return !! $this->subscriptions()->where('user_id', auth()->id())->count();
31 | }
32 |
33 | /**
34 | * Fetch the subscribe status as a property.
35 | *
36 | * @return bool
37 | */
38 | public function getIsSubscribedAttribute()
39 | {
40 | return $this->subscriptions()->where('user_id', auth()->id())->exists();
41 | }
42 |
43 | /**
44 | * Get the number of subscriptions for the reply.
45 | *
46 | * @return integer
47 | */
48 | public function getSubscriptionsCountAttribute()
49 | {
50 | return $this->subscriptions()->count();
51 | }
52 |
53 |
54 | public function subscriptions(){
55 |
56 | return $this->morphMany(Subscription::class,'subscribable');
57 | }
58 |
59 | }
--------------------------------------------------------------------------------
/database/migrations/2017_05_28_025758_create_articles_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->unsignedInteger('user_id');
19 | $table->unsignedInteger('category_id');
20 | $table->unsignedInteger('replies_count')->default(0);
21 | $table->unsignedInteger('views_count')->default(0);
22 | $table->string('title');
23 | $table->string('page_image')->nullable();
24 | $table->string('slug')->nullable();
25 | $table->text('body');
26 | $table->boolean('is_original')->default(false)->comment('是否为原创');
27 | $table->boolean('is_secret')->default(false)->comment('是否为私密文章');
28 |
29 | $table->unsignedInteger('draft_id')->nullable();
30 | $table->softDeletes();
31 | $table->timestamps();
32 | });
33 | }
34 |
35 | /**
36 | * Reverse the migrations.
37 | *
38 | * @return void
39 | */
40 | public function down()
41 | {
42 | Schema::dropIfExists('articles');
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/Providers/AuthServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'App\Policies\ModelPolicy',
30 | Article::class => ArticlePolicy::class,
31 | User::class => UserPolicy::class,
32 | Comment::class => CommentPolicy::class,
33 | SpecialPage::class => SpecialPagePolicy::class,
34 | Draft::class => DraftPolicy::class,
35 | Discussion::class => DiscussionPolicy::class
36 | ];
37 |
38 | /**
39 | * Register any authentication / authorization services.
40 | *
41 | * @return void
42 | */
43 | public function boot()
44 | {
45 | Passport::routes();
46 |
47 | $this->registerPolicies();
48 |
49 | //
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/FavoriteController.php:
--------------------------------------------------------------------------------
1 | middleware('auth:api')->except('index');
16 |
17 | }
18 |
19 | public function index($type,$type_id,FavoriteRequest $request){
20 |
21 | $limit = Input::get('limit') ?: 20;
22 | $model = $request->getModel($type,$type_id);
23 |
24 | $favorites = $model->favorites()->with('user')->paginate($limit);
25 | return FavoriteResource::collection($favorites);
26 | }
27 |
28 | // 用户点赞
29 | public function store(FavoriteRequest $request)
30 | {
31 |
32 | try{
33 | $favorite = $request->store();
34 | }catch(FavoriteException $e){
35 | return $e->response();
36 | }
37 |
38 | $request->getModel()->notifyFavorited();
39 |
40 | return new FavoriteResource($favorite->load('user'));
41 |
42 | }
43 |
44 | // 用户取消点赞
45 | public function destroy(FavoriteRequest $request){
46 |
47 | try{
48 | $request->destroy();
49 | }catch(FavoriteException $e){
50 | return $e->response();
51 | }
52 |
53 | return $this->message('取消点赞成功');
54 |
55 | }
56 |
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/resources/assets/sass/vender/fontawesome/_mixins.scss:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------
3 |
4 | @mixin fa-icon {
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | display: inline-block;
8 | font-style: normal;
9 | font-variant: normal;
10 | font-weight: normal;
11 | line-height: 1;
12 | vertical-align: -.125em;
13 | }
14 |
15 | @mixin fa-icon-rotate($degrees, $rotation) {
16 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})";
17 | transform: rotate($degrees);
18 | }
19 |
20 | @mixin fa-icon-flip($horiz, $vert, $rotation) {
21 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)";
22 | transform: scale($horiz, $vert);
23 | }
24 |
25 |
26 | // Only display content to screen readers. A la Bootstrap 4.
27 | //
28 | // See: http://a11yproject.com/posts/how-to-hide-content/
29 |
30 | @mixin sr-only {
31 | border: 0;
32 | clip: rect(0, 0, 0, 0);
33 | height: 1px;
34 | margin: -1px;
35 | overflow: hidden;
36 | padding: 0;
37 | position: absolute;
38 | width: 1px;
39 | }
40 |
41 | // Use in conjunction with .sr-only to only display content when it's focused.
42 | //
43 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
44 | //
45 | // Credit: HTML5 Boilerplate
46 |
47 | @mixin sr-only-focusable {
48 | &:active,
49 | &:focus {
50 | clip: auto;
51 | height: auto;
52 | margin: 0;
53 | overflow: visible;
54 | position: static;
55 | width: auto;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/config/hashids.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | declare(strict_types=1);
13 |
14 | return [
15 |
16 | /*
17 | |--------------------------------------------------------------------------
18 | | Default Connection Name
19 | |--------------------------------------------------------------------------
20 | |
21 | | Here you may specify which of the connections below you wish to use as
22 | | your default connection for all work. Of course, you may use many
23 | | connections at once using the manager class.
24 | |
25 | */
26 |
27 | 'default' => 'main',
28 |
29 | /*
30 | |--------------------------------------------------------------------------
31 | | Hashids Connections
32 | |--------------------------------------------------------------------------
33 | |
34 | | Here are each of the connections setup for your application. Example
35 | | configuration has been included, but you may add as many connections as
36 | | you would like.
37 | |
38 | */
39 |
40 | 'connections' => [
41 |
42 | 'main' => [
43 | 'salt' => '',
44 | 'length' => 30,
45 | ],
46 |
47 | 'alternative' => [
48 | 'salt' => 'your-salt-string',
49 | 'length' => 'your-length-integer',
50 | ],
51 |
52 | ],
53 |
54 | ];
55 |
--------------------------------------------------------------------------------
/resources/views/admin/partials/slide_menu.blade.php:
--------------------------------------------------------------------------------
1 |
47 |
48 |
--------------------------------------------------------------------------------
/resources/views/vendor/pagination/admin.blade.php:
--------------------------------------------------------------------------------
1 | @if ($paginator->hasPages())
2 |
3 |
4 |
41 |
42 | @endif
--------------------------------------------------------------------------------
/resources/views/vendor/pagination/bootstrap-4.blade.php:
--------------------------------------------------------------------------------
1 | @if ($paginator->hasPages())
2 |
36 | @endif
37 |
--------------------------------------------------------------------------------
/resources/views/vendor/pagination/default.blade.php:
--------------------------------------------------------------------------------
1 | @if ($paginator->hasPages())
2 |
3 |
4 |
41 |
42 | @endif
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "npm run development",
5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
7 | "watch-poll": "npm run watch -- --watch-poll",
8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
9 | "prod": "npm run production",
10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
11 | },
12 | "devDependencies": {
13 | "axios": "^0.17",
14 | "popper.js": "^1.12",
15 | "babel-polyfill": "^6.23.0",
16 | "bootstrap-sass": "^3.3.7",
17 | "buefy": "^0.6.2",
18 | "bulma": "^0.6.2",
19 | "cross-env": "^5.1",
20 | "fine-uploader": "^5.14.4",
21 | "ionicons": "^2.0.1",
22 | "jquery": "^3.2",
23 | "laravel-mix": "^2.0",
24 | "lodash": "^4.17.4",
25 | "vue": "^2.5.7",
26 | "vue-image-crop-upload": "^1.3.11",
27 | "vue-router": "^2.5.3"
28 | },
29 | "dependencies": {
30 | "@fortawesome/fontawesome-free-webfonts": "^1.0.3",
31 | "marked": "^0.3.6",
32 | "moment": "^2.18.1",
33 | "particles.js": "^2.0.0",
34 | "simplemde": "^1.11.2",
35 | "social-share.js": "^1.0.16",
36 | "vue-multiselect": "^2.0.0-beta.15"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/resources/views/articles/partials/user.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {{ $article->user->name }}
23 |
24 | @if($article->user->signature)
25 | {{ $article->user->signature }}
26 | @else
27 | 该用户很懒,什么都没有留下
28 | @endif
29 |
30 |
31 |
32 |
33 |
34 |
35 | @can('update',$article->user)
36 |
编辑个人资料
37 | @endcan
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/Notifications/ArticleWasFavorited.php:
--------------------------------------------------------------------------------
1 | article = $article;
26 | }
27 |
28 | /**
29 | * Get the notification's delivery channels.
30 | *
31 | * @param mixed $notifiable
32 | * @return array
33 | */
34 | public function via($notifiable)
35 | {
36 | return ['database'];
37 | }
38 |
39 |
40 |
41 | /**
42 | * Get the array representation of the notification.
43 | *
44 | * @param mixed $notifiable
45 | * @return array
46 | */
47 | public function toArray($notifiable)
48 | {
49 | $user = Auth::user();
50 | return [
51 | 'article_id' => $this->article->id,
52 | 'user_id' => $user->id
53 | ];
54 | }
55 |
56 | public static function map($data)
57 | {
58 | $article = Article::query()->find($data['article_id']);
59 | $user = User::query()->find($data['user_id']);
60 |
61 | return (object)[
62 | 'article' => $article,
63 | 'user' => $user
64 | ];
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/Notifications/AnswerWasUpdateBest.php:
--------------------------------------------------------------------------------
1 | comment = $comment;
28 | $this->user = $user;
29 | }
30 |
31 | /**
32 | * Get the notification's delivery channels.
33 | *
34 | * @param mixed $notifiable
35 | * @return array
36 | */
37 | public function via($notifiable)
38 | {
39 | return ['database'];
40 | }
41 |
42 |
43 | /**
44 | * Get the array representation of the notification.
45 | *
46 | * @param mixed $notifiable
47 | * @return array
48 | */
49 | public function toArray($notifiable)
50 | {
51 | return [
52 | 'comment_id' => $this->comment->id,
53 | 'user_id' => $this->user->id
54 | ];
55 | }
56 |
57 | public static function map($data)
58 | {
59 | $discussion = Comment::query()->find($data['comment_id']);
60 | $user = User::query()->find($data['user_id']);
61 |
62 | return (object)[
63 | 'comment' => $discussion,
64 | 'user' => $user
65 | ];
66 |
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/Notifications/CommentWasFavorited.php:
--------------------------------------------------------------------------------
1 | comment = $comment;
27 | }
28 |
29 | /**
30 | * Get the notification's delivery channels.
31 | *
32 | * @param mixed $notifiable
33 | * @return array
34 | */
35 | public function via($notifiable)
36 | {
37 | return ['database'];
38 | }
39 |
40 |
41 | /**
42 | * Get the array representation of the notification.
43 | *
44 | * @param mixed $notifiable
45 | * @return array
46 | */
47 | public function toArray($notifiable)
48 | {
49 | $user = Auth::user();
50 | return [
51 | 'comment_id' => $this->comment->id,
52 | 'user_id' => $user->id
53 | ];
54 | }
55 |
56 | public static function map($data)
57 | {
58 |
59 | $comment = Comment::query()->find($data['comment_id']);
60 | $user = User::query()->find($data['user_id']);
61 |
62 | return (object)[
63 | 'comment' => $comment,
64 | 'user' => $user
65 | ];
66 |
67 | }
68 | }
69 |
--------------------------------------------------------------------------------