├── .env.example ├── .gitattributes ├── .gitignore ├── app ├── Console │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ ├── Admin │ │ │ ├── AdminController.php │ │ │ └── ArticleController.php │ │ ├── ArticleController.php │ │ ├── Auth │ │ │ ├── ForgotPasswordController.php │ │ │ ├── LoginController.php │ │ │ ├── RegisterController.php │ │ │ └── ResetPasswordController.php │ │ ├── CommentsController.php │ │ ├── Controller.php │ │ ├── HomeController.php │ │ ├── MessagesController.php │ │ ├── RemessagesController.php │ │ ├── ReplysController.php │ │ └── TodosController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── EncryptCookies.php │ │ ├── RedirectIfAuthenticated.php │ │ └── VerifyCsrfToken.php │ └── ViewComposers │ │ └── App2Composer.php ├── Mail │ ├── NewComment.php │ └── NewMessage.php ├── Models │ ├── Article.php │ ├── Comment.php │ ├── Message.php │ ├── Remessage.php │ ├── Reply.php │ ├── Todo.php │ └── User.php ├── Policies │ └── UserPolicy.php └── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── ComposerServiceProvider.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php ├── artisan ├── bootstrap ├── app.php ├── autoload.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── captcha.php ├── compile.php ├── database.php ├── debugbar.php ├── filesystems.php ├── image.php ├── mail.php ├── markdown.php ├── queue.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ └── ModelFactory.php ├── migrations │ ├── .gitkeep │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2017_01_06_031257_create_articles_table.php │ ├── 2017_01_09_050613_change_content_column_type_of_articles_table.php │ ├── 2017_01_22_113528_add_cover_column_to_articles_table.php │ ├── 2017_02_17_171909_create_messages_table.php │ ├── 2017_03_10_142540_create_comments_talbe.php │ ├── 2017_03_10_142633_create_replys_talbe.php │ ├── 2017_03_10_160608_change_name_column_of_messages_table.php │ ├── 2017_03_31_160014_add_hidden_column_to_articles_table.php │ ├── 2017_08_03_235245_create_remessages_table.php │ └── 2017_09_16_153816_create_todos_table.php └── seeds │ ├── .gitkeep │ └── DatabaseSeeder.php ├── gulpfile.js ├── package.json ├── phpunit.xml ├── public ├── .htaccess ├── css │ ├── app.css │ └── app.css.map ├── favicon.ico ├── fonts │ └── bootstrap │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 ├── img │ ├── .gitignore │ ├── article │ │ └── 2.jpg │ ├── author │ │ ├── avatar.jpg │ │ ├── github.png │ │ ├── qq.png │ │ ├── qqQR.jpg │ │ ├── wechat.png │ │ └── wechatQR.png │ ├── default_cover.jpg │ ├── favicon.ico │ ├── header-phone.jpg │ ├── header.jpg │ ├── message │ │ └── message.jpg │ └── slide │ │ ├── 1.jpg │ │ └── 2.jpg ├── index.php ├── js │ ├── app.js │ └── sortable │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── .jshintrc │ │ ├── CONTRIBUTING.md │ │ ├── Gruntfile.js │ │ ├── ISSUE_TEMPLATE.md │ │ ├── README.md │ │ ├── Sortable.js │ │ ├── Sortable.min.js │ │ ├── bower.json │ │ ├── component.json │ │ ├── index.html │ │ ├── jquery.binding.js │ │ ├── package.json │ │ └── st │ │ ├── app.css │ │ ├── app.js │ │ ├── face-01.jpg │ │ ├── face-02.jpg │ │ ├── face-03.jpg │ │ ├── face-04.jpg │ │ ├── face-05.jpg │ │ ├── face-06.jpg │ │ ├── face-07.jpg │ │ ├── face-08.jpg │ │ ├── face-09.jpg │ │ ├── iframe │ │ ├── frame.html │ │ └── index.html │ │ ├── logo.png │ │ └── og-image.png ├── robots.txt └── web.config ├── readme.md ├── resources ├── assets │ ├── js │ │ ├── app.js │ │ ├── bootstrap.js │ │ └── components │ │ │ ├── Example.vue │ │ │ └── Reply.vue │ └── sass │ │ ├── _variables.scss │ │ └── app.scss ├── lang │ ├── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php │ └── zh-CN │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php └── views │ ├── admin │ ├── admin.blade.php │ ├── article │ │ ├── create.blade.php │ │ ├── edit.blade.php │ │ └── index.blade.php │ └── index.blade.php │ ├── article │ ├── list.blade.php │ └── show.blade.php │ ├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ └── register.blade.php │ ├── emails │ ├── email.blade.php │ ├── new_comment.blade.php │ └── new_message.blade.php │ ├── errors │ └── 503.blade.php │ ├── home.blade.php │ ├── layouts │ ├── _footer.blade.php │ ├── _header.blade.php │ ├── app_2columns.blade.php │ └── app_imax.blade.php │ ├── messages │ └── index.blade.php │ ├── shared │ ├── ads.blade.php │ ├── article.blade.php │ ├── article_hot.blade.php │ ├── article_little.blade.php │ ├── author_info.blade.php │ ├── errors.blade.php │ ├── links.blade.php │ ├── message_new.blade.php │ ├── messages.blade.php │ ├── slides.blade.php │ └── user_info.blade.php │ ├── todos │ └── index.blade.php │ └── vendor │ ├── .gitkeep │ ├── notifications │ ├── email-plain.blade.php │ └── email.blade.php │ └── pagination │ ├── bootstrap-4.blade.php │ ├── default.blade.php │ ├── simple-bootstrap-4.blade.php │ └── simple-default.blade.php ├── routes ├── api.php ├── console.php └── web.php ├── server.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── debugbar │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore └── tests ├── ExampleTest.php └── TestCase.php /.env.example: -------------------------------------------------------------------------------- 1 | APP_ENV=local 2 | APP_KEY= 3 | APP_DEBUG=true 4 | APP_LOG_LEVEL=debug 5 | APP_URL=http://localhost 6 | 7 | DB_CONNECTION=mysql 8 | DB_HOST=127.0.0.1 9 | DB_PORT=3306 10 | DB_DATABASE=homestead 11 | DB_USERNAME=homestead 12 | DB_PASSWORD=secret 13 | 14 | BROADCAST_DRIVER=log 15 | CACHE_DRIVER=file 16 | SESSION_DRIVER=file 17 | QUEUE_DRIVER=sync 18 | 19 | REDIS_HOST=127.0.0.1 20 | REDIS_PASSWORD=null 21 | REDIS_PORT=6379 22 | 23 | MAIL_DRIVER=smtp 24 | MAIL_HOST=mailtrap.io 25 | MAIL_PORT=2525 26 | MAIL_USERNAME=null 27 | MAIL_PASSWORD=null 28 | MAIL_ENCRYPTION=null 29 | 30 | PUSHER_APP_ID= 31 | PUSHER_KEY= 32 | PUSHER_SECRET= 33 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/storage 3 | /vendor 4 | /.idea 5 | Homestead.json 6 | Homestead.yaml 7 | .env 8 | -------------------------------------------------------------------------------- /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/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 60 | return response()->json(['error' => 'Unauthenticated.'], 401); 61 | } 62 | 63 | return redirect()->guest('login'); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/AdminController.php: -------------------------------------------------------------------------------- 1 | id == 1) { 15 | return view('admin.index'); 16 | } 17 | else { 18 | session()->flash('warning', '没有权限'); 19 | return view('home'); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/ArticleController.php: -------------------------------------------------------------------------------- 1 | paginate(20); 18 | return view('admin.article.index', compact('articles')); 19 | } 20 | 21 | //新建文章页 22 | public function create() 23 | { 24 | return view('admin.article.create'); 25 | } 26 | 27 | //文章->保存 28 | public function store(Request $request) 29 | { 30 | $this->validate($request, [ 31 | 'title' => 'required|max:50', 32 | 'intro' => 'max:200', 33 | ]); 34 | 35 | // BUG 封面图片存储并生成路径--> 读取不到? 36 | //$cover_path = Storage::url($request->cover->store('public/covers')); 37 | //Image::make($cover_path)->resize(350, 200)->save($cover_path); 38 | 39 | if ($request->hasFile('cover')) { 40 | //封面图片压缩存储并生成路径 41 | $cover_path = "img/article/cover/" . time() . ".jpg"; 42 | Image::make($request->cover)->resize(355, 200)->save(public_path($cover_path)); 43 | }else{ 44 | $cover_path = "img/default_cover.jpg"; 45 | } 46 | 47 | $article = Article::create([ 48 | 'title' => $request->title, 49 | 'intro' => $request->intro, 50 | 'content' => $request->content, 51 | 'cover' => $cover_path, 52 | ]); 53 | 54 | session()->flash('success', '添加成功'); 55 | return redirect()->route('article.index'); 56 | } 57 | 58 | //编辑文章页 59 | public function edit($id) 60 | { 61 | $article = Article::findOrFail($id); 62 | return view('admin.article.edit', compact('article')); 63 | } 64 | 65 | //文章->更新 66 | public function update($id, Request $request) 67 | { 68 | $this->validate($request, [ 69 | 'title' => 'required|max:50', 70 | 'intro' => 'max:200', 71 | ]); 72 | 73 | $article = Article::findOrFail($id); 74 | $article->update([ 75 | 'title' => $request->title, 76 | 'intro' => $request->intro, 77 | 'content' => $request->content, 78 | ]); 79 | 80 | //如果上传了封面图片则更新 81 | if ($request->hasFile('cover')) { 82 | //封面图片压缩存储并生成路径 83 | $cover_path = "img/article/cover/" . time() . ".jpg"; 84 | Image::make($request->cover)->resize(355, 200)->save(public_path($cover_path)); 85 | $article->update([ 86 | 'cover' => $cover_path, 87 | ]); 88 | } 89 | 90 | session()->flash('success', '编辑成功'); 91 | return back(); 92 | } 93 | 94 | //文章->删除 95 | public function destroy($id) 96 | { 97 | $article = Article::findOrFail($id); 98 | $article->delete(); 99 | session()->flash('success', '删除成功'); 100 | return back(); 101 | } 102 | 103 | //文章->隐藏/显示 104 | public function hidden($id) 105 | { 106 | $article = Article::findOrFail($id); 107 | 108 | $article->update([ 109 | 'hidden' => !$article->hidden, 110 | ]); 111 | 112 | if ($article->hidden == 1) { 113 | session()->flash('success', '文章已隐藏'); 114 | }else{ 115 | session()->flash('success', '文章已解除隐藏'); 116 | } 117 | 118 | return back(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/Http/Controllers/ArticleController.php: -------------------------------------------------------------------------------- 1 | content = Markdown::convertToHtml($article->content); 20 | 21 | //更新浏览量 22 | Article::update_view($id); 23 | 24 | //获取评论 25 | $comments = $article->comments()->orderBy('created_at','desc')->paginate(10); 26 | 27 | 28 | return view('article.show', compact(['article','comments'])); 29 | } 30 | 31 | //文章列表页 32 | public function list() 33 | { 34 | //获取全部文章 35 | $articles = Article::where('hidden', false)->orderBy('created_at','desc')->paginate(20); 36 | 37 | return view('article.list', compact('articles')); 38 | } 39 | 40 | //文章搜索页 41 | public function search(Request $request) 42 | { 43 | //搜索文章 44 | $articles = Article::search($request->key); 45 | 46 | $articles = $articles->appends(['key'=>$request->key]); 47 | 48 | session()->flash('success', '搜索完成'); 49 | return view('article.list',compact('articles')); 50 | } 51 | 52 | //markdown AJAX 解析 53 | public function markdown(Request $request) 54 | { 55 | return Markdown::convertToHtml($request->content); 56 | } 57 | 58 | //markdown AJAX 获取文章内容 59 | public function markdown_article($article_id) 60 | { 61 | $article = Article::findOrFail($article_id); 62 | return Markdown::convertToHtml($article->content); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/LoginController.php: -------------------------------------------------------------------------------- 1 | middleware('guest', ['except' => 'logout']); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/RegisterController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 40 | } 41 | 42 | /** 43 | * Get a validator for an incoming registration request. 44 | * 45 | * @param array $data 46 | * @return \Illuminate\Contracts\Validation\Validator 47 | */ 48 | protected function validator(array $data) 49 | { 50 | return Validator::make($data, [ 51 | 'name' => 'required|max:255', 52 | 'email' => 'required|email|max:255|unique:users', 53 | 'password' => 'required|min:6|confirmed', 54 | //'captcha' => 'required|captcha',//图片验证码 55 | ]); 56 | } 57 | 58 | /** 59 | * Create a new user instance after a valid registration. 60 | * 61 | * @param array $data 62 | * @return User 63 | */ 64 | protected function create(array $data) 65 | { 66 | return User::create([ 67 | 'name' => $data['name'], 68 | 'email' => $data['email'], 69 | 'password' => bcrypt($data['password']), 70 | ]); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/CommentsController.php: -------------------------------------------------------------------------------- 1 | validate($request, [ 22 | 'content' => 'required', 23 | ]); 24 | 25 | $comment = Comment::create([ 26 | 'user_id' => Auth::id(), 27 | 'article_id' => $request->article_id, 28 | 'content' => $request->content, 29 | ]); 30 | 31 | //更新评论量 32 | Article::update_comment($request->article_id); 33 | 34 | //发送邮件通知 35 | $data['article_id'] = $request->article_id; 36 | Mail::to(User::findOrFail(1))->send(new NewComment($data)); 37 | 38 | session()->flash('success', '评论成功'); 39 | return back(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | paginate(20); 21 | 22 | return view('messages.index', compact('messages')); 23 | } 24 | 25 | public function store(Request $request) 26 | { 27 | $this->validate($request, [ 28 | 'content' => 'required|max:120', 29 | ]); 30 | 31 | //获取 user_id 未登录用户为 0 32 | if (Auth::check()) { 33 | $user_id = Auth::id(); 34 | }else{ 35 | $user_id = 0; 36 | } 37 | 38 | $message = Message::create([ 39 | 'user_id' => $user_id, 40 | 'content' => $request->content, 41 | ]); 42 | 43 | //发送邮件通知 44 | Mail::to(User::findOrFail(1))->send(new NewMessage()); 45 | 46 | session()->flash('success', '留言成功'); 47 | return redirect()->route('messages.index'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Http/Controllers/RemessagesController.php: -------------------------------------------------------------------------------- 1 | validate($request, [ 19 | 'content' => 'required', 20 | ]); 21 | 22 | $remessage = Remessage::create([ 23 | 'user_id' => Auth::id(), 24 | 'message_id' => $request->message_id, 25 | 'content' => $request->content, 26 | ]); 27 | 28 | //session()->flash('success', '回复成功'); 29 | //return back(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Http/Controllers/ReplysController.php: -------------------------------------------------------------------------------- 1 | validate($request, [ 23 | 'content' => 'required', 24 | ]); 25 | 26 | $reply = Reply::create([ 27 | 'user_id' => Auth::id(), 28 | 'comment_id' => $request->comment_id, 29 | 'content' => $request->content, 30 | ]); 31 | 32 | //更新评论量 33 | $article_id = Comment::findOrFail($request->comment_id)->article->id; 34 | Article::update_comment($article_id); 35 | 36 | //发送邮件通知 37 | $data['article_id'] = $article_id; 38 | Mail::to(User::findOrFail(1))->send(new NewComment($data)); 39 | 40 | //session()->flash('success', '回复成功'); 41 | //return back(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Http/Controllers/TodosController.php: -------------------------------------------------------------------------------- 1 | $request->content, 20 | ]); 21 | 22 | return back(); 23 | } 24 | 25 | public function destroy($id) 26 | { 27 | $todo = Todo::findOrFail($id); 28 | $todo->delete(); 29 | 30 | return back(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Kernel.php: -------------------------------------------------------------------------------- 1 | [ 27 | \App\Http\Middleware\EncryptCookies::class, 28 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 29 | \Illuminate\Session\Middleware\StartSession::class, 30 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 31 | \App\Http\Middleware\VerifyCsrfToken::class, 32 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 33 | ], 34 | 35 | 'api' => [ 36 | 'throttle:60,1', 37 | 'bindings', 38 | ], 39 | ]; 40 | 41 | /** 42 | * The application's route middleware. 43 | * 44 | * These middleware may be assigned to groups or used individually. 45 | * 46 | * @var array 47 | */ 48 | protected $routeMiddleware = [ 49 | 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 50 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 51 | 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 52 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 53 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 54 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 55 | ]; 56 | } 57 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | check()) { 21 | return redirect('/home'); 22 | } 23 | 24 | return $next($request); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | with('articles_hot', $articles_hot); 28 | $view->with( 29 | [ 30 | 'articles_hot' => $articles_hot, 31 | 'messages_new' => $messages_new, 32 | ]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Mail/NewComment.php: -------------------------------------------------------------------------------- 1 | data = $data; 24 | } 25 | 26 | /** 27 | * Build the message. 28 | * 29 | * @return $this 30 | */ 31 | public function build() 32 | { 33 | return $this->subject('收到了新的评论:)')->view('emails.new_comment'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Mail/NewMessage.php: -------------------------------------------------------------------------------- 1 | subject('收到了新的留言:)')->view('emails.new_message'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Models/Article.php: -------------------------------------------------------------------------------- 1 | view = $article->view + 1; 23 | $article->update([ 24 | 'view' => $article->view, 25 | ]); 26 | } 27 | 28 | //更新评论量 29 | static public function update_comment($id) 30 | { 31 | $article = Article::findOrFail($id); 32 | $article->comment = $article->comment + 1; 33 | $article->update([ 34 | 'comment' => $article->comment, 35 | ]); 36 | } 37 | 38 | //搜索文章 39 | static public function search($key) 40 | { 41 | $article = Article::where('title', 'like', '%'.$key.'%')->where('hidden', false)->paginate(20); 42 | return $article; 43 | } 44 | 45 | //动态流-最新文章 46 | static public function new() 47 | { 48 | $articles = Article::where('hidden', false)->orderBy('created_at','desc')->take(5)->get(); 49 | 50 | return $articles; 51 | } 52 | 53 | //动态流-热门文章 54 | static public function hot() 55 | { 56 | $articles = Article::where('hidden', false)->orderBy('view','desc')->take(5)->get(); 57 | 58 | return $articles; 59 | } 60 | 61 | //模型关联: 获取文章下的所有评论 62 | public function comments() 63 | { 64 | return $this->hasMany('App\Models\Comment'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Models/Comment.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Models\User'); 22 | } 23 | 24 | //模型关联:获取该评论所属的文章模型 25 | public function article() 26 | { 27 | return $this->belongsTo('App\Models\Article'); 28 | } 29 | 30 | //模型关联:获取该评论的所有回复 31 | public function replys() 32 | { 33 | return $this->hasMany('App\Models\Reply'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Models/Message.php: -------------------------------------------------------------------------------- 1 | take(5)->get(); 22 | 23 | return $messages; 24 | } 25 | 26 | //模型关联:获取该留言所属的用户模型 27 | public function user() 28 | { 29 | return $this->belongsTo('App\Models\User'); 30 | } 31 | 32 | //模型关联:获取该留言的所有回复 33 | public function remessages() 34 | { 35 | return $this->hasMany('App\Models\Remessage'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Models/Remessage.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Models\User'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Models/Reply.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Models\User'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Models/Todo.php: -------------------------------------------------------------------------------- 1 | attributes['email']))); 39 | return "http://www.gravatar.com/avatar/$hash?s=$size"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Policies/UserPolicy.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 19 | User::class => UserPolicy::class, 20 | ]; 21 | 22 | /** 23 | * Register any authentication / authorization services. 24 | * 25 | * @return void 26 | */ 27 | public function boot() 28 | { 29 | $this->registerPolicies(); 30 | 31 | // 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | id === (int) $userId; 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Providers/ComposerServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'App\Listeners\EventListener', 18 | ], 19 | ]; 20 | 21 | /** 22 | * Register any events for your application. 23 | * 24 | * @return void 25 | */ 26 | public function boot() 27 | { 28 | parent::boot(); 29 | 30 | // 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | mapApiRoutes(); 39 | 40 | $this->mapWebRoutes(); 41 | 42 | // 43 | } 44 | 45 | /** 46 | * Define the "web" routes for the application. 47 | * 48 | * These routes all receive session state, CSRF protection, etc. 49 | * 50 | * @return void 51 | */ 52 | protected function mapWebRoutes() 53 | { 54 | Route::group([ 55 | 'middleware' => 'web', 56 | 'namespace' => $this->namespace, 57 | ], function ($router) { 58 | require base_path('routes/web.php'); 59 | }); 60 | } 61 | 62 | /** 63 | * Define the "api" routes for the application. 64 | * 65 | * These routes are typically stateless. 66 | * 67 | * @return void 68 | */ 69 | protected function mapApiRoutes() 70 | { 71 | Route::group([ 72 | 'middleware' => 'api', 73 | 'namespace' => $this->namespace, 74 | 'prefix' => 'api', 75 | ], function ($router) { 76 | require base_path('routes/api.php'); 77 | }); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 32 | 33 | $status = $kernel->handle( 34 | $input = new Symfony\Component\Console\Input\ArgvInput, 35 | new Symfony\Component\Console\Output\ConsoleOutput 36 | ); 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Shutdown The Application 41 | |-------------------------------------------------------------------------- 42 | | 43 | | Once Artisan has finished running. We will fire off the shutdown events 44 | | so that any final work may be done by the application before we shut 45 | | down the process. This is the last thing to happen to the request. 46 | | 47 | */ 48 | 49 | $kernel->terminate($input, $status); 50 | 51 | exit($status); 52 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /bootstrap/autoload.php: -------------------------------------------------------------------------------- 1 | =5.6.4", 9 | "laravel/framework": "5.3.*", 10 | "caouecs/laravel-lang": "~3.0", 11 | "doctrine/dbal": "^2.5", 12 | "graham-campbell/markdown": "^7.1", 13 | "intervention/image": "^2.3", 14 | "mews/captcha": "^2.1" 15 | }, 16 | "require-dev": { 17 | "fzaninotto/faker": "~1.4", 18 | "mockery/mockery": "0.9.*", 19 | "phpunit/phpunit": "~5.0", 20 | "symfony/css-selector": "3.1.*", 21 | "symfony/dom-crawler": "3.1.*", 22 | "barryvdh/laravel-debugbar": "^2.3" 23 | }, 24 | "autoload": { 25 | "classmap": [ 26 | "database" 27 | ], 28 | "psr-4": { 29 | "App\\": "app/" 30 | } 31 | }, 32 | "autoload-dev": { 33 | "classmap": [ 34 | "tests/TestCase.php" 35 | ] 36 | }, 37 | "scripts": { 38 | "post-root-package-install": [ 39 | "php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 40 | ], 41 | "post-create-project-cmd": [ 42 | "php artisan key:generate" 43 | ], 44 | "post-install-cmd": [ 45 | "Illuminate\\Foundation\\ComposerScripts::postInstall", 46 | "php artisan optimize" 47 | ], 48 | "post-update-cmd": [ 49 | "Illuminate\\Foundation\\ComposerScripts::postUpdate", 50 | "php artisan optimize" 51 | ] 52 | }, 53 | "config": { 54 | "preferred-install": "dist" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /config/auth.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'guard' => 'web', 18 | 'passwords' => 'users', 19 | ], 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Authentication Guards 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Next, you may define every authentication guard for your application. 27 | | Of course, a great default configuration has been defined for you 28 | | here which uses session storage and the Eloquent user provider. 29 | | 30 | | All authentication drivers have a user provider. This defines how the 31 | | users are actually retrieved out of your database or other storage 32 | | mechanisms used by this application to persist your user's data. 33 | | 34 | | Supported: "session", "token" 35 | | 36 | */ 37 | 38 | 'guards' => [ 39 | 'web' => [ 40 | 'driver' => 'session', 41 | 'provider' => 'users', 42 | ], 43 | 44 | 'api' => [ 45 | 'driver' => 'token', 46 | 'provider' => 'users', 47 | ], 48 | ], 49 | 50 | /* 51 | |-------------------------------------------------------------------------- 52 | | User Providers 53 | |-------------------------------------------------------------------------- 54 | | 55 | | All authentication drivers have a user provider. This defines how the 56 | | users are actually retrieved out of your database or other storage 57 | | mechanisms used by this application to persist your user's data. 58 | | 59 | | If you have multiple user tables or models you may configure multiple 60 | | sources which represent each model / table. These sources may then 61 | | be assigned to any extra authentication guards you have defined. 62 | | 63 | | Supported: "database", "eloquent" 64 | | 65 | */ 66 | 67 | 'providers' => [ 68 | 'users' => [ 69 | 'driver' => 'eloquent', 70 | 'model' => App\Models\User::class, 71 | ], 72 | 73 | // 'users' => [ 74 | // 'driver' => 'database', 75 | // 'table' => 'users', 76 | // ], 77 | ], 78 | 79 | /* 80 | |-------------------------------------------------------------------------- 81 | | Resetting Passwords 82 | |-------------------------------------------------------------------------- 83 | | 84 | | You may specify multiple password reset configurations if you have more 85 | | than one user table or model in the application and you want to have 86 | | separate password reset settings based on the specific user types. 87 | | 88 | | The expire time is the number of minutes that the reset token should be 89 | | considered valid. This security feature keeps tokens short-lived so 90 | | they have less time to be guessed. You may change this as needed. 91 | | 92 | */ 93 | 94 | 'passwords' => [ 95 | 'users' => [ 96 | 'provider' => 'users', 97 | 'table' => 'password_resets', 98 | 'expire' => 60, 99 | ], 100 | ], 101 | 102 | ]; 103 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_KEY'), 36 | 'secret' => env('PUSHER_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | // 40 | ], 41 | ], 42 | 43 | 'redis' => [ 44 | 'driver' => 'redis', 45 | 'connection' => 'default', 46 | ], 47 | 48 | 'log' => [ 49 | 'driver' => 'log', 50 | ], 51 | 52 | 'null' => [ 53 | 'driver' => 'null', 54 | ], 55 | 56 | ], 57 | 58 | ]; 59 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | */ 30 | 31 | 'stores' => [ 32 | 33 | 'apc' => [ 34 | 'driver' => 'apc', 35 | ], 36 | 37 | 'array' => [ 38 | 'driver' => 'array', 39 | ], 40 | 41 | 'database' => [ 42 | 'driver' => 'database', 43 | 'table' => 'cache', 44 | 'connection' => null, 45 | ], 46 | 47 | 'file' => [ 48 | 'driver' => 'file', 49 | 'path' => storage_path('framework/cache'), 50 | ], 51 | 52 | 'memcached' => [ 53 | 'driver' => 'memcached', 54 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 55 | 'sasl' => [ 56 | env('MEMCACHED_USERNAME'), 57 | env('MEMCACHED_PASSWORD'), 58 | ], 59 | 'options' => [ 60 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 61 | ], 62 | 'servers' => [ 63 | [ 64 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 65 | 'port' => env('MEMCACHED_PORT', 11211), 66 | 'weight' => 100, 67 | ], 68 | ], 69 | ], 70 | 71 | 'redis' => [ 72 | 'driver' => 'redis', 73 | 'connection' => 'default', 74 | ], 75 | 76 | ], 77 | 78 | /* 79 | |-------------------------------------------------------------------------- 80 | | Cache Key Prefix 81 | |-------------------------------------------------------------------------- 82 | | 83 | | When utilizing a RAM based store such as APC or Memcached, there might 84 | | be other applications utilizing the same cache. So, we'll specify a 85 | | value to get prefixed to all our keys so we can avoid collisions. 86 | | 87 | */ 88 | 89 | 'prefix' => 'laravel', 90 | 91 | ]; 92 | -------------------------------------------------------------------------------- /config/captcha.php: -------------------------------------------------------------------------------- 1 | '2346789abcdefghjmnpqrtuxyzABCDEFGHJMNPQRTUXYZ', 7 | 8 | 'default' => [ 9 | 'length' => 5, 10 | 'width' => 120, 11 | 'height' => 36, 12 | 'quality' => 90, 13 | ], 14 | 15 | 'flat' => [ 16 | 'length' => 6, 17 | 'width' => 160, 18 | 'height' => 46, 19 | 'quality' => 90, 20 | 'lines' => 6, 21 | 'bgImage' => false, 22 | 'bgColor' => '#ecf2f4', 23 | 'fontColors'=> ['#2c3e50', '#c0392b', '#16a085', '#c0392b', '#8e44ad', '#303f9f', '#f57c00', '#795548'], 24 | 'contrast' => -5, 25 | ], 26 | 27 | 'mini' => [ 28 | 'length' => 3, 29 | 'width' => 60, 30 | 'height' => 32, 31 | ], 32 | 33 | 'inverse' => [ 34 | 'length' => 5, 35 | 'width' => 120, 36 | 'height' => 36, 37 | 'quality' => 90, 38 | 'sensitive' => true, 39 | 'angle' => 12, 40 | 'sharpen' => 10, 41 | 'blur' => 2, 42 | 'invert' => true, 43 | 'contrast' => -5, 44 | ] 45 | 46 | ]; 47 | -------------------------------------------------------------------------------- /config/compile.php: -------------------------------------------------------------------------------- 1 | [ 17 | // 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled File Providers 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may list service providers which define a "compiles" function 26 | | that returns additional files that should be compiled, providing an 27 | | easy way to get common files from any packages you are utilizing. 28 | | 29 | */ 30 | 31 | 'providers' => [ 32 | // 33 | ], 34 | 35 | ]; 36 | -------------------------------------------------------------------------------- /config/database.php: -------------------------------------------------------------------------------- 1 | PDO::FETCH_OBJ, 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Database Connection Name 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may specify which of the database connections below you wish 24 | | to use as your default connection for all database work. Of course 25 | | you may use many connections at once using the Database library. 26 | | 27 | */ 28 | 29 | 'default' => env('DB_CONNECTION', 'mysql'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Database Connections 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here are each of the database connections setup for your application. 37 | | Of course, examples of configuring each database platform that is 38 | | supported by Laravel is shown below to make development simple. 39 | | 40 | | 41 | | All database work in Laravel is done through the PHP PDO facilities 42 | | so make sure you have the driver for your particular database of 43 | | choice installed on your machine before you begin development. 44 | | 45 | */ 46 | 47 | 'connections' => [ 48 | 49 | 'sqlite' => [ 50 | 'driver' => 'sqlite', 51 | 'database' => env('DB_DATABASE', database_path('database.sqlite')), 52 | 'prefix' => '', 53 | ], 54 | 55 | 'mysql' => [ 56 | 'driver' => 'mysql', 57 | 'host' => env('DB_HOST', 'localhost'), 58 | 'port' => env('DB_PORT', '3306'), 59 | 'database' => env('DB_DATABASE', 'forge'), 60 | 'username' => env('DB_USERNAME', 'forge'), 61 | 'password' => env('DB_PASSWORD', ''), 62 | 'charset' => 'utf8', 63 | 'collation' => 'utf8_unicode_ci', 64 | 'prefix' => '', 65 | 'strict' => true, 66 | 'engine' => null, 67 | ], 68 | 69 | 'pgsql' => [ 70 | 'driver' => 'pgsql', 71 | 'host' => env('DB_HOST', 'localhost'), 72 | 'port' => env('DB_PORT', '5432'), 73 | 'database' => env('DB_DATABASE', 'forge'), 74 | 'username' => env('DB_USERNAME', 'forge'), 75 | 'password' => env('DB_PASSWORD', ''), 76 | 'charset' => 'utf8', 77 | 'prefix' => '', 78 | 'schema' => 'public', 79 | 'sslmode' => 'prefer', 80 | ], 81 | 82 | ], 83 | 84 | /* 85 | |-------------------------------------------------------------------------- 86 | | Migration Repository Table 87 | |-------------------------------------------------------------------------- 88 | | 89 | | This table keeps track of all the migrations that have already run for 90 | | your application. Using this information, we can determine which of 91 | | the migrations on disk haven't actually been run in the database. 92 | | 93 | */ 94 | 95 | 'migrations' => 'migrations', 96 | 97 | /* 98 | |-------------------------------------------------------------------------- 99 | | Redis Databases 100 | |-------------------------------------------------------------------------- 101 | | 102 | | Redis is an open source, fast, and advanced key-value store that also 103 | | provides a richer set of commands than a typical key-value systems 104 | | such as APC or Memcached. Laravel makes it easy to dig right in. 105 | | 106 | */ 107 | 108 | 'redis' => [ 109 | 110 | 'cluster' => false, 111 | 112 | 'default' => [ 113 | 'host' => env('REDIS_HOST', 'localhost'), 114 | 'password' => env('REDIS_PASSWORD', null), 115 | 'port' => env('REDIS_PORT', 6379), 116 | 'database' => 0, 117 | ], 118 | 119 | ], 120 | 121 | ]; 122 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | 'local', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Default Cloud Filesystem Disk 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Many applications store files both locally and in the cloud. For this 26 | | reason, you may specify a default "cloud" driver here. This driver 27 | | will be bound as the Cloud disk implementation in the container. 28 | | 29 | */ 30 | 31 | 'cloud' => 's3', 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Filesystem Disks 36 | |-------------------------------------------------------------------------- 37 | | 38 | | Here you may configure as many filesystem "disks" as you wish, and you 39 | | may even configure multiple disks of the same driver. Defaults have 40 | | been setup for each driver as an example of the required options. 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'public' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/public'), 54 | 'visibility' => 'public', 55 | ], 56 | 57 | 's3' => [ 58 | 'driver' => 's3', 59 | 'key' => 'your-key', 60 | 'secret' => 'your-secret', 61 | 'region' => 'your-region', 62 | 'bucket' => 'your-bucket', 63 | ], 64 | 65 | ], 66 | 67 | ]; 68 | -------------------------------------------------------------------------------- /config/image.php: -------------------------------------------------------------------------------- 1 | 'imagick' 20 | 21 | ); 22 | -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_DRIVER', 'smtp'), 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | SMTP Host Address 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Here you may provide the host address of the SMTP server used by your 27 | | applications. A default option is provided that is compatible with 28 | | the Mailgun mail service which will provide reliable deliveries. 29 | | 30 | */ 31 | 32 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 33 | 34 | /* 35 | |-------------------------------------------------------------------------- 36 | | SMTP Host Port 37 | |-------------------------------------------------------------------------- 38 | | 39 | | This is the SMTP port used by your application to deliver e-mails to 40 | | users of the application. Like the host we have set this value to 41 | | stay compatible with the Mailgun e-mail application by default. 42 | | 43 | */ 44 | 45 | 'port' => env('MAIL_PORT', 587), 46 | 47 | /* 48 | |-------------------------------------------------------------------------- 49 | | Global "From" Address 50 | |-------------------------------------------------------------------------- 51 | | 52 | | You may wish for all e-mails sent by your application to be sent from 53 | | the same address. Here, you may specify a name and address that is 54 | | used globally for all e-mails that are sent by your application. 55 | | 56 | */ 57 | 58 | 'from' => [ 59 | 'address' => '87826632@qq.com', 60 | 'name' => 'SadCreeper', 61 | ], 62 | 63 | /* 64 | |-------------------------------------------------------------------------- 65 | | E-Mail Encryption Protocol 66 | |-------------------------------------------------------------------------- 67 | | 68 | | Here you may specify the encryption protocol that should be used when 69 | | the application send e-mail messages. A sensible default using the 70 | | transport layer security protocol should provide great security. 71 | | 72 | */ 73 | 74 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | SMTP Server Username 79 | |-------------------------------------------------------------------------- 80 | | 81 | | If your SMTP server requires a username for authentication, you should 82 | | set it here. This will get used to authenticate with your server on 83 | | connection. You may also set the "password" value below this one. 84 | | 85 | */ 86 | 87 | 'username' => env('MAIL_USERNAME'), 88 | 89 | /* 90 | |-------------------------------------------------------------------------- 91 | | SMTP Server Password 92 | |-------------------------------------------------------------------------- 93 | | 94 | | Here you may set the password required by your SMTP server to send out 95 | | messages from your application. This will be given to the server on 96 | | connection so that the application will be able to send messages. 97 | | 98 | */ 99 | 100 | 'password' => env('MAIL_PASSWORD'), 101 | 102 | /* 103 | |-------------------------------------------------------------------------- 104 | | Sendmail System Path 105 | |-------------------------------------------------------------------------- 106 | | 107 | | When using the "sendmail" driver to send e-mails, we will need to know 108 | | the path to where Sendmail lives on this server. A default path has 109 | | been provided here, which will work well on most of your systems. 110 | | 111 | */ 112 | 113 | 'sendmail' => '/usr/sbin/sendmail -bs', 114 | 115 | ]; 116 | -------------------------------------------------------------------------------- /config/markdown.php: -------------------------------------------------------------------------------- 1 | 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | return [ 14 | 15 | /* 16 | |-------------------------------------------------------------------------- 17 | | Enable View Integration 18 | |-------------------------------------------------------------------------- 19 | | 20 | | This option specifies if the view integration is enabled so you can write 21 | | markdown views and have them rendered as html. The following extensions 22 | | are currently supported: ".md", ".md.php", and ".md.blade.php". You may 23 | | disable this integration if it is conflicting with another package. 24 | | 25 | | Default: true 26 | | 27 | */ 28 | 29 | 'views' => true, 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | CommonMark Extensions 34 | |-------------------------------------------------------------------------- 35 | | 36 | | This option specifies what extensions will be automatically enabled. 37 | | Simply provide your extension class names here. 38 | | 39 | | Default: [] 40 | | 41 | */ 42 | 43 | 'extensions' => [], 44 | 45 | /* 46 | |-------------------------------------------------------------------------- 47 | | Renderer Configuration 48 | |-------------------------------------------------------------------------- 49 | | 50 | | This option specifies an array of options for rendering HTML. 51 | | 52 | | Default: [ 53 | | 'block_separator' => "\n", 54 | | 'inner_separator' => "\n", 55 | | 'soft_break' => "\n", 56 | | ] 57 | | 58 | */ 59 | 60 | 'renderer' => [ 61 | 'block_separator' => "\n", 62 | 'inner_separator' => "\n", 63 | 'soft_break' => "\n", 64 | ], 65 | 66 | /* 67 | |-------------------------------------------------------------------------- 68 | | Enable Em Tag Parsing 69 | |-------------------------------------------------------------------------- 70 | | 71 | | This option specifies if `` parsing is enabled. 72 | | 73 | | Default: true 74 | | 75 | */ 76 | 77 | 'enable_em' => true, 78 | 79 | /* 80 | |-------------------------------------------------------------------------- 81 | | Enable Strong Tag Parsing 82 | |-------------------------------------------------------------------------- 83 | | 84 | | This option specifies if `` parsing is enabled. 85 | | 86 | | Default: true 87 | | 88 | */ 89 | 90 | 'enable_strong' => true, 91 | 92 | /* 93 | |-------------------------------------------------------------------------- 94 | | Enable Asterisk Parsing 95 | |-------------------------------------------------------------------------- 96 | | 97 | | This option specifies if `*` should be parsed for emphasis. 98 | | 99 | | Default: true 100 | | 101 | */ 102 | 103 | 'use_asterisk' => true, 104 | 105 | /* 106 | |-------------------------------------------------------------------------- 107 | | Enable Underscore Parsing 108 | |-------------------------------------------------------------------------- 109 | | 110 | | This option specifies if `_` should be parsed for emphasis. 111 | | 112 | | Default: true 113 | | 114 | */ 115 | 116 | 'use_underscore' => true, 117 | 118 | /* 119 | |-------------------------------------------------------------------------- 120 | | HTML Input 121 | |-------------------------------------------------------------------------- 122 | | 123 | | This option specifies how to handle untrusted HTML input. 124 | | 125 | | Default: 'strip' 126 | | 127 | */ 128 | 129 | 'html_input' => 'allow', 130 | 131 | /* 132 | |-------------------------------------------------------------------------- 133 | | Allow Unsafe Links 134 | |-------------------------------------------------------------------------- 135 | | 136 | | This option specifies whether to allow risky image URLs and links. 137 | | 138 | | Default: true 139 | | 140 | */ 141 | 142 | 'allow_unsafe_links' => true, 143 | 144 | ]; 145 | -------------------------------------------------------------------------------- /config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_DRIVER', 'sync'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Queue Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may configure the connection information for each server that 26 | | is used by your application. A default configuration has been added 27 | | for each back-end shipped with Laravel. You are free to add more. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'table' => 'jobs', 40 | 'queue' => 'default', 41 | 'retry_after' => 90, 42 | ], 43 | 44 | 'beanstalkd' => [ 45 | 'driver' => 'beanstalkd', 46 | 'host' => 'localhost', 47 | 'queue' => 'default', 48 | 'retry_after' => 90, 49 | ], 50 | 51 | 'sqs' => [ 52 | 'driver' => 'sqs', 53 | 'key' => 'your-public-key', 54 | 'secret' => 'your-secret-key', 55 | 'prefix' => 'https://sqs.us-east-1.amazonaws.com/your-account-id', 56 | 'queue' => 'your-queue-name', 57 | 'region' => 'us-east-1', 58 | ], 59 | 60 | 'redis' => [ 61 | 'driver' => 'redis', 62 | 'connection' => 'default', 63 | 'queue' => 'default', 64 | 'retry_after' => 90, 65 | ], 66 | 67 | ], 68 | 69 | /* 70 | |-------------------------------------------------------------------------- 71 | | Failed Queue Jobs 72 | |-------------------------------------------------------------------------- 73 | | 74 | | These options configure the behavior of failed queue job logging so you 75 | | can control which database and table are used to store the jobs that 76 | | have failed. You may change them to any database / table you wish. 77 | | 78 | */ 79 | 80 | 'failed' => [ 81 | 'database' => env('DB_CONNECTION', 'mysql'), 82 | 'table' => 'failed_jobs', 83 | ], 84 | 85 | ]; 86 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | ], 21 | 22 | 'ses' => [ 23 | 'key' => env('SES_KEY'), 24 | 'secret' => env('SES_SECRET'), 25 | 'region' => 'us-east-1', 26 | ], 27 | 28 | 'sparkpost' => [ 29 | 'secret' => env('SPARKPOST_SECRET'), 30 | ], 31 | 32 | 'stripe' => [ 33 | 'model' => App\Models\User::class, 34 | 'key' => env('STRIPE_KEY'), 35 | 'secret' => env('STRIPE_SECRET'), 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | realpath(base_path('resources/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/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /database/factories/ModelFactory.php: -------------------------------------------------------------------------------- 1 | define(App\Models\User::class, function (Faker\Generator $faker) { 15 | static $password; 16 | 17 | return [ 18 | 'name' => $faker->name, 19 | 'email' => $faker->unique()->safeEmail, 20 | 'password' => $password ?: $password = bcrypt('secret'), 21 | 'remember_token' => str_random(10), 22 | ]; 23 | }); 24 | -------------------------------------------------------------------------------- /database/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->string('password'); 21 | $table->rememberToken(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('users'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token')->index(); 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::drop('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_01_06_031257_create_articles_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('title'); 19 | $table->string('intro')->nullable(); 20 | $table->string('content')->nullable(); 21 | $table->integer('view')->default(0); 22 | $table->integer('comment')->default(0); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('articles'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2017_01_09_050613_change_content_column_type_of_articles_table.php: -------------------------------------------------------------------------------- 1 | longText('content')->nullable()->change(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('articles', function (Blueprint $table) { 29 | //$table->string('content')->nullable()->change(); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_01_22_113528_add_cover_column_to_articles_table.php: -------------------------------------------------------------------------------- 1 | string('cover')->nullable(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('articles', function (Blueprint $table) { 29 | $table->dropColumn('cover'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_02_17_171909_create_messages_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->text('content'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('messages'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2017_03_10_142540_create_comments_talbe.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('article_id'); 19 | $table->integer('user_id'); 20 | $table->text('content'); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('comments'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_03_10_142633_create_replys_talbe.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('comment_id'); 19 | $table->string('user_id'); 20 | $table->text('content'); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('replys'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_03_10_160608_change_name_column_of_messages_table.php: -------------------------------------------------------------------------------- 1 | integer('name')->change(); 18 | $table->renameColumn('name', 'user_id'); 19 | 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::table('messages', function (Blueprint $table) { 31 | $table->string('user_id')->change(); 32 | $table->renameColumn('user_id', 'name'); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2017_03_31_160014_add_hidden_column_to_articles_table.php: -------------------------------------------------------------------------------- 1 | boolean('hidden')->default(false); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::table('articles', function (Blueprint $table) { 29 | $table->dropColumn('hidden'); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2017_08_03_235245_create_remessages_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('message_id'); 19 | $table->string('user_id'); 20 | $table->text('content'); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('remessages'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_09_16_153816_create_todos_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('content'); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('todos'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/seeds/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(UsersTableSeeder::class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const elixir = require('laravel-elixir'); 2 | 3 | require('laravel-elixir-vue-2'); 4 | 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Elixir Asset Management 8 | |-------------------------------------------------------------------------- 9 | | 10 | | Elixir provides a clean, fluent API for defining some basic Gulp tasks 11 | | for your Laravel application. By default, we are compiling the Sass 12 | | file for our application, as well as publishing vendor resources. 13 | | 14 | */ 15 | 16 | elixir(mix => { 17 | mix.sass('app.scss') 18 | .webpack('app.js'); 19 | }); 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "prod": "gulp --production", 5 | "dev": "gulp watch" 6 | }, 7 | "devDependencies": { 8 | "bootstrap-sass": "^3.3.7", 9 | "gulp": "^3.9.1", 10 | "jquery": "^3.1.0", 11 | "laravel-elixir": "^6.0.0-9", 12 | "laravel-elixir-vue-2": "^0.2.0", 13 | "laravel-elixir-webpack-official": "^1.0.2", 14 | "lodash": "^4.16.2", 15 | "vue": "^2.0.1", 16 | "vue-resource": "^1.0.3" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests 14 | 15 | 16 | 17 | 18 | ./app 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes If Not A Folder... 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | RewriteRule ^(.*)/$ /$1 [L,R=301] 11 | 12 | # Handle Front Controller... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_FILENAME} !-f 15 | RewriteRule ^ index.php [L] 16 | 17 | # Handle Authorization Header 18 | RewriteCond %{HTTP:Authorization} . 19 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 20 | 21 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/favicon.ico -------------------------------------------------------------------------------- /public/fonts/bootstrap/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/fonts/bootstrap/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/bootstrap/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/fonts/bootstrap/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/bootstrap/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/fonts/bootstrap/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/fonts/bootstrap/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/fonts/bootstrap/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /public/img/.gitignore: -------------------------------------------------------------------------------- 1 | /article 2 | -------------------------------------------------------------------------------- /public/img/article/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/article/2.jpg -------------------------------------------------------------------------------- /public/img/author/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/author/avatar.jpg -------------------------------------------------------------------------------- /public/img/author/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/author/github.png -------------------------------------------------------------------------------- /public/img/author/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/author/qq.png -------------------------------------------------------------------------------- /public/img/author/qqQR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/author/qqQR.jpg -------------------------------------------------------------------------------- /public/img/author/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/author/wechat.png -------------------------------------------------------------------------------- /public/img/author/wechatQR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/author/wechatQR.png -------------------------------------------------------------------------------- /public/img/default_cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/default_cover.jpg -------------------------------------------------------------------------------- /public/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/favicon.ico -------------------------------------------------------------------------------- /public/img/header-phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/header-phone.jpg -------------------------------------------------------------------------------- /public/img/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/header.jpg -------------------------------------------------------------------------------- /public/img/message/message.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/message/message.jpg -------------------------------------------------------------------------------- /public/img/slide/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/slide/1.jpg -------------------------------------------------------------------------------- /public/img/slide/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/img/slide/2.jpg -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /* 11 | |-------------------------------------------------------------------------- 12 | | Register The Auto Loader 13 | |-------------------------------------------------------------------------- 14 | | 15 | | Composer provides a convenient, automatically generated class loader for 16 | | our application. We just need to utilize it! We'll simply require it 17 | | into the script here so that we don't have to worry about manual 18 | | loading any of our classes later on. It feels nice to relax. 19 | | 20 | */ 21 | 22 | require __DIR__.'/../bootstrap/autoload.php'; 23 | 24 | /* 25 | |-------------------------------------------------------------------------- 26 | | Turn On The Lights 27 | |-------------------------------------------------------------------------- 28 | | 29 | | We need to illuminate PHP development, so let us turn on the lights. 30 | | This bootstraps the framework and gets it ready for use, then it 31 | | will load up this application so that we can run it and send 32 | | the responses back to the browser and delight our users. 33 | | 34 | */ 35 | 36 | $app = require_once __DIR__.'/../bootstrap/app.php'; 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Run The Application 41 | |-------------------------------------------------------------------------- 42 | | 43 | | Once we have the application, we can handle the incoming request 44 | | through the kernel, and send the associated response back to 45 | | the client's browser allowing them to enjoy the creative 46 | | and wonderful application we have prepared for them. 47 | | 48 | */ 49 | 50 | $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); 51 | 52 | $response = $kernel->handle( 53 | $request = Illuminate\Http\Request::capture() 54 | ); 55 | 56 | $response->send(); 57 | 58 | $kernel->terminate($request, $response); 59 | -------------------------------------------------------------------------------- /public/js/sortable/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /public/js/sortable/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | mock.png 3 | .*.sw* 4 | .build* 5 | jquery.fn.* 6 | -------------------------------------------------------------------------------- /public/js/sortable/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "strict": true, 3 | "newcap": false, 4 | "node": true, 5 | "expr": true, 6 | "supernew": true, 7 | "laxbreak": true, 8 | "white": true, 9 | "globals": { 10 | "define": true, 11 | "test": true, 12 | "expect": true, 13 | "module": true, 14 | "asyncTest": true, 15 | "start": true, 16 | "ok": true, 17 | "equal": true, 18 | "notEqual": true, 19 | "deepEqual": true, 20 | "window": true, 21 | "document": true, 22 | "performance": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /public/js/sortable/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | ### Issue 4 | 5 | 1. Try [dev](https://github.com/RubaXa/Sortable/tree/dev/)-branch, perhaps the problem has been solved; 6 | 2. [Use the search](https://github.com/RubaXa/Sortable/search?type=Issues&q=problem), maybe already have an answer; 7 | 3. If not found, create example on [jsbin.com (draft)](http://jsbin.com/zunibaxada/1/edit?html,js,output) and describe the problem. 8 | 9 | --- 10 | 11 | ### Pull Request 12 | 13 | 1. Before PR run `grunt`; 14 | 2. Only into [dev](https://github.com/RubaXa/Sortable/tree/dev/)-branch. 15 | 16 | ### Setup 17 | 18 | Pieced together from [gruntjs](http://gruntjs.com/getting-started) 19 | 20 | 1. Fork repo on [github](https://github.com) 21 | 2. Clone locally 22 | 3. from local repro ```npm install``` 23 | 4. Install grunt-cli globally ```sudo -H npm install -g grunt-cli``` 24 | -------------------------------------------------------------------------------- /public/js/sortable/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 'use strict'; 3 | 4 | grunt.initConfig({ 5 | pkg: grunt.file.readJSON('package.json'), 6 | 7 | version: { 8 | js: { 9 | src: ['<%= pkg.exportName %>.js', '*.json'] 10 | }, 11 | cdn: { 12 | options: { 13 | prefix: '(cdnjs\\.cloudflare\\.com\\/ajax\\/libs\\/Sortable|cdn\\.jsdelivr\\.net\\/sortable)\\/', 14 | replace: '[0-9\\.]+' 15 | }, 16 | src: ['README.md'] 17 | } 18 | }, 19 | 20 | jshint: { 21 | all: ['*.js', '!*.min.js'], 22 | 23 | options: { 24 | jshintrc: true 25 | } 26 | }, 27 | 28 | uglify: { 29 | options: { 30 | banner: '/*! <%= pkg.exportName %> <%= pkg.version %> - <%= pkg.license %> | <%= pkg.repository.url %> */\n' 31 | }, 32 | dist: { 33 | files: { 34 | '<%= pkg.exportName %>.min.js': ['<%= pkg.exportName %>.js'] 35 | } 36 | }, 37 | jquery: { 38 | files: {} 39 | } 40 | }, 41 | 42 | jquery: {} 43 | }); 44 | 45 | 46 | grunt.registerTask('jquery', function (exportName, uglify) { 47 | if (exportName == 'min') { 48 | exportName = null; 49 | uglify = 'min'; 50 | } 51 | 52 | if (!exportName) { 53 | exportName = 'sortable'; 54 | } 55 | 56 | var fs = require('fs'), 57 | filename = 'jquery.fn.' + exportName + '.js'; 58 | 59 | grunt.log.oklns(filename); 60 | 61 | fs.writeFileSync( 62 | filename, 63 | (fs.readFileSync('jquery.binding.js') + '') 64 | .replace('$.fn.sortable', '$.fn.' + exportName) 65 | .replace('/* CODE */', 66 | (fs.readFileSync('Sortable.js') + '') 67 | .replace(/^[\s\S]*?function[\s\S]*?(var[\s\S]+)\/\/\s+Export[\s\S]+/, '$1') 68 | ) 69 | ); 70 | 71 | if (uglify) { 72 | var opts = {}; 73 | 74 | opts['jquery.fn.' + exportName + '.min.js'] = filename; 75 | grunt.config.set('uglify.jquery.files', opts); 76 | 77 | grunt.task.run('uglify:jquery'); 78 | } 79 | }); 80 | 81 | 82 | grunt.loadNpmTasks('grunt-version'); 83 | grunt.loadNpmTasks('grunt-contrib-jshint'); 84 | grunt.loadNpmTasks('grunt-contrib-uglify'); 85 | 86 | grunt.registerTask('tests', ['jshint']); 87 | grunt.registerTask('default', ['tests', 'version', 'uglify:dist']); 88 | }; 89 | -------------------------------------------------------------------------------- /public/js/sortable/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Before you create a issue, check it: 2 | 3 | 1. Try [dev](https://github.com/RubaXa/Sortable/tree/dev/)-branch, perhaps the problem has been solved; 4 | 2. [Use the search](https://github.com/RubaXa/Sortable/search?q=problem), maybe already have an answer; 5 | 3. If not found, create example on [jsbin.com (draft)](http://jsbin.com/zunibaxada/1/edit?html,js,output) and describe the problem. 6 | 7 | Bindings: 8 | - Angular 9 | - 2.0+: https://github.com/SortableJS/angular-sortablejs/issues 10 | - legacy: https://github.com/SortableJS/angular-legacy-sortablejs/issues 11 | - React 12 | - ES2015+: https://github.com/SortableJS/react-sortablejs/issues 13 | - mixin: https://github.com/SortableJS/react-mixin-sortablejs/issues 14 | - Polymer: https://github.com/SortableJS/polymer-sortablejs/issues 15 | - Knockout: https://github.com/SortableJS/knockout-sortablejs/issues 16 | - Meteor: https://github.com/SortableJS/meteor-sortablejs/issues 17 | 18 | -------------------------------------------------------------------------------- /public/js/sortable/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sortable", 3 | "main": [ 4 | "Sortable.js" 5 | ], 6 | "homepage": "http://rubaxa.github.io/Sortable/", 7 | "authors": [ 8 | "RubaXa " 9 | ], 10 | "description": "Minimalist library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery.", 11 | "keywords": [ 12 | "sortable", 13 | "reorder", 14 | "list", 15 | "html5", 16 | "drag", 17 | "and", 18 | "drop", 19 | "dnd", 20 | "web-components" 21 | ], 22 | "license": "MIT", 23 | "ignore": [ 24 | "node_modules", 25 | "bower_components", 26 | "test", 27 | "tests" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /public/js/sortable/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sortable", 3 | "main": "Sortable.js", 4 | "version": "1.4.2", 5 | "homepage": "http://rubaxa.github.io/Sortable/", 6 | "repo": "RubaXa/Sortable", 7 | "authors": [ 8 | "RubaXa " 9 | ], 10 | "description": "Minimalist library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery.", 11 | "keywords": [ 12 | "sortable", 13 | "reorder", 14 | "list", 15 | "html5", 16 | "drag", 17 | "and", 18 | "drop", 19 | "dnd" 20 | ], 21 | "license": "MIT", 22 | "ignore": [ 23 | "node_modules", 24 | "bower_components", 25 | "test", 26 | "tests" 27 | ], 28 | 29 | "scripts": [ 30 | "Sortable.js" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /public/js/sortable/jquery.binding.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery plugin for Sortable 3 | * @author RubaXa 4 | * @license MIT 5 | */ 6 | (function (factory) { 7 | "use strict"; 8 | 9 | if (typeof define === "function" && define.amd) { 10 | define(["jquery"], factory); 11 | } 12 | else { 13 | /* jshint sub:true */ 14 | factory(jQuery); 15 | } 16 | })(function ($) { 17 | "use strict"; 18 | 19 | 20 | /* CODE */ 21 | 22 | 23 | /** 24 | * jQuery plugin for Sortable 25 | * @param {Object|String} options 26 | * @param {..*} [args] 27 | * @returns {jQuery|*} 28 | */ 29 | $.fn.sortable = function (options) { 30 | var retVal, 31 | args = arguments; 32 | 33 | this.each(function () { 34 | var $el = $(this), 35 | sortable = $el.data('sortable'); 36 | 37 | if (!sortable && (options instanceof Object || !options)) { 38 | sortable = new Sortable(this, options); 39 | $el.data('sortable', sortable); 40 | } 41 | 42 | if (sortable) { 43 | if (options === 'widget') { 44 | retVal = sortable; 45 | } 46 | else if (options === 'destroy') { 47 | sortable.destroy(); 48 | $el.removeData('sortable'); 49 | } 50 | else if (typeof sortable[options] === 'function') { 51 | retVal = sortable[options].apply(sortable, [].slice.call(args, 1)); 52 | } 53 | else if (options in sortable.options) { 54 | retVal = sortable.option.apply(sortable, args); 55 | } 56 | } 57 | }); 58 | 59 | return (retVal === void 0) ? this : retVal; 60 | }; 61 | }); 62 | -------------------------------------------------------------------------------- /public/js/sortable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sortablejs", 3 | "exportName": "Sortable", 4 | "version": "1.4.2", 5 | "devDependencies": { 6 | "grunt": "*", 7 | "grunt-version": "*", 8 | "grunt-contrib-jshint": "*", 9 | "grunt-contrib-uglify": "*" 10 | }, 11 | "description": "Minimalist JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery. Supports AngularJS and any CSS library, e.g. Bootstrap.", 12 | "main": "Sortable.js", 13 | "scripts": { 14 | "test": "grunt" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/rubaxa/Sortable.git" 19 | }, 20 | "keywords": [ 21 | "sortable", 22 | "reorder", 23 | "drag", 24 | "meteor", 25 | "angular", 26 | "ng-sortable", 27 | "react", 28 | "mixin" 29 | ], 30 | "author": "Konstantin Lebedev ", 31 | "license": "MIT", 32 | "spm": { 33 | "main": "Sortable.js", 34 | "ignore": [ 35 | "meteor", 36 | "st" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /public/js/sortable/st/app.css: -------------------------------------------------------------------------------- 1 | html { 2 | background-image: -webkit-linear-gradient(bottom, #F4E2C9 20%, #F4D7C9 100%); 3 | background-image: -ms-linear-gradient(bottom, #F4E2C9 20%, #F4D7C9 100%); 4 | background-image: linear-gradient(to bottom, #F4E2C9 20%, #F4D7C9 100%); 5 | } 6 | 7 | html, body { 8 | margin: 0; 9 | padding: 0; 10 | position: relative; 11 | color: #464637; 12 | min-height: 100%; 13 | font-size: 20px; 14 | font-family: 'Roboto', sans-serif; 15 | font-weight: 300; 16 | } 17 | 18 | 19 | h1 { 20 | color: #FF3F00; 21 | font-size: 20px; 22 | font-family: 'Roboto', sans-serif; 23 | font-weight: 300; 24 | text-align: center; 25 | } 26 | 27 | 28 | ul { 29 | margin: 0; 30 | padding: 0; 31 | list-style: none; 32 | } 33 | 34 | .container { 35 | width: 80%; 36 | margin: auto; 37 | min-width: 1100px; 38 | max-width: 1300px; 39 | position: relative; 40 | } 41 | 42 | @media (min-width: 750px) and (max-width: 970px){ 43 | .container { 44 | width: 100%; 45 | min-width: 750px; 46 | } 47 | } 48 | 49 | 50 | .sortable-ghost { 51 | opacity: .2; 52 | } 53 | 54 | #foo .sortable-drag { 55 | background: #daf4ff; 56 | } 57 | 58 | 59 | img { 60 | border: 0; 61 | vertical-align: middle; 62 | } 63 | 64 | 65 | .logo { 66 | top: 55px; 67 | left: 30px; 68 | position: absolute; 69 | } 70 | 71 | 72 | .title { 73 | color: #fff; 74 | padding: 3px 10px; 75 | display: inline-block; 76 | position: relative; 77 | background-color: #FF7373; 78 | z-index: 1000; 79 | } 80 | .title_xl { 81 | padding: 3px 15px; 82 | font-size: 40px; 83 | } 84 | 85 | 86 | 87 | .tile { 88 | width: 22%; 89 | min-width: 245px; 90 | color: #FF7270; 91 | padding: 10px 30px; 92 | text-align: center; 93 | margin-top: 15px; 94 | margin-left: 5px; 95 | margin-right: 30px; 96 | background-color: #fff; 97 | display: inline-block; 98 | vertical-align: top; 99 | } 100 | .tile__name { 101 | cursor: move; 102 | padding-bottom: 10px; 103 | border-bottom: 1px solid #FF7373; 104 | } 105 | 106 | .tile__list { 107 | margin-top: 10px; 108 | } 109 | .tile__list:last-child { 110 | margin-right: 0; 111 | min-height: 80px; 112 | } 113 | 114 | .tile__list img { 115 | cursor: move; 116 | margin: 10px; 117 | border-radius: 100%; 118 | } 119 | 120 | 121 | 122 | .block { 123 | opacity: 1; 124 | position: absolute; 125 | } 126 | .block__list { 127 | padding: 20px 0; 128 | max-width: 360px; 129 | margin-top: -8px; 130 | margin-left: 5px; 131 | background-color: #fff; 132 | } 133 | .block__list-title { 134 | margin: -20px 0 0; 135 | padding: 10px; 136 | text-align: center; 137 | background: #5F9EDF; 138 | } 139 | .block__list li { cursor: move; } 140 | 141 | .block__list_words li { 142 | background-color: #fff; 143 | padding: 10px 40px; 144 | } 145 | .block__list_words .sortable-ghost { 146 | opacity: 0.4; 147 | background-color: #F4E2C9; 148 | } 149 | 150 | .block__list_words li:first-letter { 151 | text-transform: uppercase; 152 | } 153 | 154 | .block__list_tags { 155 | padding-left: 30px; 156 | } 157 | 158 | .block__list_tags:after { 159 | clear: both; 160 | content: ''; 161 | display: block; 162 | } 163 | .block__list_tags li { 164 | color: #fff; 165 | float: left; 166 | margin: 8px 20px 10px 0; 167 | padding: 5px 10px; 168 | min-width: 10px; 169 | background-color: #5F9EDF; 170 | text-align: center; 171 | } 172 | .block__list_tags li:first-child:first-letter { 173 | text-transform: uppercase; 174 | } 175 | 176 | 177 | 178 | #editable {} 179 | #editable li { 180 | position: relative; 181 | } 182 | 183 | #editable i { 184 | -webkit-transition: opacity .2s; 185 | transition: opacity .2s; 186 | opacity: 0; 187 | display: block; 188 | cursor: pointer; 189 | color: #c00; 190 | top: 10px; 191 | right: 40px; 192 | position: absolute; 193 | font-style: normal; 194 | } 195 | 196 | #editable li:hover i { 197 | opacity: 1; 198 | } 199 | 200 | 201 | #filter {} 202 | #filter button { 203 | color: #fff; 204 | width: 100%; 205 | border: none; 206 | outline: 0; 207 | opacity: .5; 208 | margin: 10px 0 0; 209 | transition: opacity .1s ease; 210 | cursor: pointer; 211 | background: #5F9EDF; 212 | padding: 10px 0; 213 | font-size: 20px; 214 | } 215 | #filter button:hover { 216 | opacity: 1; 217 | } 218 | 219 | #filter .block__list { 220 | padding-bottom: 0; 221 | } 222 | 223 | .drag-handle { 224 | margin-right: 10px; 225 | font: bold 20px Sans-Serif; 226 | color: #5F9EDF; 227 | display: inline-block; 228 | cursor: move; 229 | cursor: -webkit-grabbing; /* overrides 'move' */ 230 | } 231 | 232 | #todos input { 233 | padding: 5px; 234 | font-size: 14px; 235 | font-family: 'Roboto', sans-serif; 236 | font-weight: 300; 237 | } 238 | 239 | 240 | 241 | #nested ul li { 242 | background-color: rgba(0,0,0,.05); 243 | } 244 | -------------------------------------------------------------------------------- /public/js/sortable/st/app.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var byId = function (id) { return document.getElementById(id); }, 5 | 6 | loadScripts = function (desc, callback) { 7 | var deps = [], key, idx = 0; 8 | 9 | for (key in desc) { 10 | deps.push(key); 11 | } 12 | 13 | (function _next() { 14 | var pid, 15 | name = deps[idx], 16 | script = document.createElement('script'); 17 | 18 | script.type = 'text/javascript'; 19 | script.src = desc[deps[idx]]; 20 | 21 | pid = setInterval(function () { 22 | if (window[name]) { 23 | clearTimeout(pid); 24 | 25 | deps[idx++] = window[name]; 26 | 27 | if (deps[idx]) { 28 | _next(); 29 | } else { 30 | callback.apply(null, deps); 31 | } 32 | } 33 | }, 30); 34 | 35 | document.getElementsByTagName('head')[0].appendChild(script); 36 | })() 37 | }, 38 | 39 | console = window.console; 40 | 41 | 42 | if (!console.log) { 43 | console.log = function () { 44 | alert([].join.apply(arguments, ' ')); 45 | }; 46 | } 47 | 48 | 49 | Sortable.create(byId('foo'), { 50 | group: "words", 51 | animation: 150, 52 | store: { 53 | get: function (sortable) { 54 | var order = localStorage.getItem(sortable.options.group); 55 | return order ? order.split('|') : []; 56 | }, 57 | set: function (sortable) { 58 | var order = sortable.toArray(); 59 | localStorage.setItem(sortable.options.group, order.join('|')); 60 | } 61 | }, 62 | onAdd: function (evt){ console.log('onAdd.foo:', [evt.item, evt.from]); }, 63 | onUpdate: function (evt){ console.log('onUpdate.foo:', [evt.item, evt.from]); }, 64 | onRemove: function (evt){ console.log('onRemove.foo:', [evt.item, evt.from]); }, 65 | onStart:function(evt){ console.log('onStart.foo:', [evt.item, evt.from]);}, 66 | onSort:function(evt){ console.log('onStart.foo:', [evt.item, evt.from]);}, 67 | onEnd: function(evt){ console.log('onEnd.foo:', [evt.item, evt.from]);} 68 | }); 69 | 70 | 71 | Sortable.create(byId('bar'), { 72 | group: "words", 73 | animation: 150, 74 | onAdd: function (evt){ console.log('onAdd.bar:', evt.item); }, 75 | onUpdate: function (evt){ console.log('onUpdate.bar:', evt.item); }, 76 | onRemove: function (evt){ console.log('onRemove.bar:', evt.item); }, 77 | onStart:function(evt){ console.log('onStart.foo:', evt.item);}, 78 | onEnd: function(evt){ console.log('onEnd.foo:', evt.item);} 79 | }); 80 | 81 | 82 | // Multi groups 83 | Sortable.create(byId('multi'), { 84 | animation: 150, 85 | draggable: '.tile', 86 | handle: '.tile__name' 87 | }); 88 | 89 | [].forEach.call(byId('multi').getElementsByClassName('tile__list'), function (el){ 90 | Sortable.create(el, { 91 | group: 'photo', 92 | animation: 150 93 | }); 94 | }); 95 | 96 | 97 | // Editable list 98 | var editableList = Sortable.create(byId('editable'), { 99 | animation: 150, 100 | filter: '.js-remove', 101 | onFilter: function (evt) { 102 | evt.item.parentNode.removeChild(evt.item); 103 | } 104 | }); 105 | 106 | 107 | byId('addUser').onclick = function () { 108 | Ply.dialog('prompt', { 109 | title: 'Add', 110 | form: { name: 'name' } 111 | }).done(function (ui) { 112 | var el = document.createElement('li'); 113 | el.innerHTML = ui.data.name + ''; 114 | editableList.el.appendChild(el); 115 | }); 116 | }; 117 | 118 | 119 | // Advanced groups 120 | [{ 121 | name: 'advanced', 122 | pull: true, 123 | put: true 124 | }, 125 | { 126 | name: 'advanced', 127 | pull: 'clone', 128 | put: false 129 | }, { 130 | name: 'advanced', 131 | pull: false, 132 | put: true 133 | }].forEach(function (groupOpts, i) { 134 | Sortable.create(byId('advanced-' + (i + 1)), { 135 | sort: (i != 1), 136 | group: groupOpts, 137 | animation: 150 138 | }); 139 | }); 140 | 141 | 142 | // 'handle' option 143 | Sortable.create(byId('handle-1'), { 144 | handle: '.drag-handle', 145 | animation: 150 146 | }); 147 | 148 | 149 | // Angular example 150 | angular.module('todoApp', ['ng-sortable']) 151 | .constant('ngSortableConfig', {onEnd: function() { 152 | console.log('default onEnd()'); 153 | }}) 154 | .controller('TodoController', ['$scope', function ($scope) { 155 | $scope.todos = [ 156 | {text: 'learn angular', done: true}, 157 | {text: 'build an angular app', done: false} 158 | ]; 159 | 160 | $scope.addTodo = function () { 161 | $scope.todos.push({text: $scope.todoText, done: false}); 162 | $scope.todoText = ''; 163 | }; 164 | 165 | $scope.remaining = function () { 166 | var count = 0; 167 | angular.forEach($scope.todos, function (todo) { 168 | count += todo.done ? 0 : 1; 169 | }); 170 | return count; 171 | }; 172 | 173 | $scope.archive = function () { 174 | var oldTodos = $scope.todos; 175 | $scope.todos = []; 176 | angular.forEach(oldTodos, function (todo) { 177 | if (!todo.done) $scope.todos.push(todo); 178 | }); 179 | }; 180 | }]) 181 | .controller('TodoControllerNext', ['$scope', function ($scope) { 182 | $scope.todos = [ 183 | {text: 'learn Sortable', done: true}, 184 | {text: 'use ng-sortable', done: false}, 185 | {text: 'Enjoy', done: false} 186 | ]; 187 | 188 | $scope.remaining = function () { 189 | var count = 0; 190 | angular.forEach($scope.todos, function (todo) { 191 | count += todo.done ? 0 : 1; 192 | }); 193 | return count; 194 | }; 195 | 196 | $scope.sortableConfig = { group: 'todo', animation: 150 }; 197 | 'Start End Add Update Remove Sort'.split(' ').forEach(function (name) { 198 | $scope.sortableConfig['on' + name] = console.log.bind(console, name); 199 | }); 200 | }]); 201 | })(); 202 | 203 | 204 | 205 | // Background 206 | document.addEventListener("DOMContentLoaded", function () { 207 | function setNoiseBackground(el, width, height, opacity) { 208 | var canvas = document.createElement("canvas"); 209 | var context = canvas.getContext("2d"); 210 | 211 | canvas.width = width; 212 | canvas.height = height; 213 | 214 | for (var i = 0; i < width; i++) { 215 | for (var j = 0; j < height; j++) { 216 | var val = Math.floor(Math.random() * 255); 217 | context.fillStyle = "rgba(" + val + "," + val + "," + val + "," + opacity + ")"; 218 | context.fillRect(i, j, 1, 1); 219 | } 220 | } 221 | 222 | el.style.background = "url(" + canvas.toDataURL("image/png") + ")"; 223 | } 224 | 225 | setNoiseBackground(document.getElementsByTagName('body')[0], 50, 50, 0.02); 226 | }, false); 227 | -------------------------------------------------------------------------------- /public/js/sortable/st/face-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-01.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-02.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-03.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-04.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-05.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-06.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-07.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-07.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-08.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-08.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/face-09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/face-09.jpg -------------------------------------------------------------------------------- /public/js/sortable/st/iframe/frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 14 16 | 17 | Drag me by the handle 18 |
19 |
20 | 2 21 | 22 | You can also select text 23 |
24 |
25 | 1 26 | 27 | Best of both worlds! 28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /public/js/sortable/st/iframe/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IFrame playground 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
This is Sortable
21 |
It works with Bootstrap...
22 |
...out of the box.
23 |
It has support for touch devices.
24 |
Just drag some elements around.
25 |
26 | 27 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /public/js/sortable/st/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/logo.png -------------------------------------------------------------------------------- /public/js/sortable/st/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/public/js/sortable/st/og-image.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Laravel-blog 2 | 基于 Laravel 5.3 的个人博客系统 3 | 4 | 演示地址:http://dmmylove.cn:8080 5 | 6 | 如果你喜欢这个开源项目,记得在右上角点个 star 哦,谢谢:) 7 | 8 | 2018-02-07 更新:这个项目停更了,最近重构了一个新版本的博客:[laravel-blog-v2](https://github.com/SadCreeper/laravel-blog-v2) 9 | 10 | # 安装方法(开发环境) 11 | 12 | ## 安装 homestead 虚拟机 13 | 14 | [Homestead 安装与配置文档](http://d.laravel-china.org/docs/5.3/homestead) 15 | 16 | ## 进入 homestead 虚拟机 17 | 18 | ``` 19 | cd ~/Homestead 20 | 21 | vagrant up 22 | 23 | vagrant ssh 24 | 25 | cd Code 26 | ``` 27 | 28 | 29 | ## 获取代码 30 | 31 | ``` 32 | git clone https://github.com/SadCreeper/laravel-blog.git 33 | ``` 34 | 35 | ## 安装依赖 36 | 37 | ``` 38 | //在项目代码根目录执行 39 | composer install 40 | ``` 41 | 42 | 除此之外,因为使用了 intervention/image 图片处理扩展包,还需要单独为该扩展包安装所需依赖,[安装方法参考文档](http://sadcreeper.xyz/article/10) 43 | 44 | ## 数据库迁移 45 | 46 | ``` 47 | //在项目代码根目录执行 48 | php artisan migrate 49 | ``` 50 | 51 | ## 安装 npm 包 52 | 53 | ``` 54 | //在项目代码根目录执行 55 | npm install 56 | ``` 57 | 58 | `npm install` 通常比较慢,甚至卡死,解决办法: 59 | 60 | 1. 翻墙 61 | 2. 使用 cnpm 62 | ``` 63 | //先安装 cnpm 64 | npm install -g cnpm --registry=https://registry.npm.taobao.org 65 | //之后就可以使用 cnpm install 替代 npm install 66 | cnpm install 67 | ``` 68 | 69 | ## 编译静态资源 70 | 71 | ``` 72 | //在项目代码根目录执行 73 | gulp 74 | ``` 75 | 76 | # 安装方法(生产环境) 77 | 78 | 生产环境的安装方法可参考这篇文章 79 | 80 | [在阿里云上部署 Laravel 5.3 (LNMP 环境)](http://dmmylove.space/article/9) 81 | 82 | # 扩展包介绍 83 | - caouecs/laravel-lang (中文语言包) 84 | - doctrine/dbal (数据库迁移支持包) 85 | - graham-campbell/markdown (Markdown 解析器) 86 | - intervention/image (图片处理扩展) 87 | - mews/captcha (图片验证码) 88 | - barryvdh/laravel-debugbar (DebugBar 调试工具) 89 | 90 | # 更新日志 91 | 92 | ## 08-04 93 | 94 | - 【其他】admin可以回复留言 95 | - 【其他】admin增加了博主标签 96 | 97 | ## 08-02 98 | 99 | - 【优化】留言、评论、回复增加了频率限制,每分钟限制5次 100 | - 【优化】匿名留言增加了提示 101 | 102 | ## 07-15 103 | 104 | - 【BUG】修复了搜索文章结果分页的 BUG 105 | 106 | ## 04-18 107 | 108 | - 【功能】+ 邮件提醒(收到评论、回复、留言后发送邮件提醒) 109 | 110 | ## 03-31 111 | 112 | - 【功能】+ 文章隐藏(只能通过 url 访问) 113 | - 【扩展】+ DebugBar 114 | - 【其他】Markdown ajax 解析请求方式由 get 改为 post(解决了文章过长无法解析的问题) 115 | - 【其他】封面图片如果未上传保存一个默认图片 116 | - 【BUG】修复了连续长数字/字符超出不换行的 BUG 117 | 118 | ## 03-22 119 | 120 | - 【其他】 修改了 markdown 样式 121 | - 【BUG】修复了手机版后台JS不生效的BUG 122 | 123 | ## 03-21 124 | 125 | - 【后台】文章编辑增加预览功能(markdown解析) 126 | 127 | ## 03-14 128 | 129 | - 【功能】文章评论增加回复功能 130 | - 【其他】文章评论去掉了匿名回复 131 | - 【其他】回复后更新评论数 132 | 133 | ## 03-10 134 | 135 | - 【模块】+ 广告位 + 最新留言 136 | - 【功能】+ 文章评论 + 评论数量动态显示 137 | - 【优化】优化了留言表结构(将留言名称由静态改为动态关联) 138 | - 【其他】修改了友情链接 139 | - 【其他】将文章的浏览、评论、时间更改为小图标 140 | 141 | ## 03-08 142 | 143 | - 【后台】文章删除增加了弹出框提醒 144 | 145 | ## 02-25 146 | 147 | - 【其他】添加了 markdown 自定义 148 | - 【BUG】修复了作者信息二维码图片小屏幕超出的BUG 149 | - 【BUG】修复了文章详情页中图片超出的BUG 150 | 151 | ## 02-24 152 | 153 | - 【后台】实现手机自适应 154 | 155 | ## 02-22 156 | 157 | - 【功能】+ 忘记密码找回功能(通过邮箱找回) 158 | - 【扩展】+ 图片验证码 159 | - 【其他】修改 header 巨幕 在手机上换成小图 160 | - 【其他】修改 网站标题后缀 161 | 162 | ## 02-21 163 | 164 | - 【模块】+ 友情链接 165 | 166 | ## 02-17 167 | 168 | - 【页面】+ 留言板 169 | - 【功能】+ 留言 170 | - 【后台】点击文章管理直接跳到文章列表页,简化操作 171 | - 【优化】使用视图合成器绑定侧栏动态数据流,替代重复代码 172 | 173 | ## 02-16 174 | 175 | - 【其他】友好格式时间更改为中文 Carbon 本地化 176 | 177 | ## 02-15 178 | 179 | - 【其他】增加 favicon 180 | 181 | ## 01-22 182 | 183 | - 【功能】+ 图片上传功能 184 | - 【扩展】+ 增加图片处理扩展,支持图片压缩,水印等 185 | 186 | ## 01-19 187 | 188 | - 【BUG】修复注册完成后的跳转错误 189 | - 【其他】首页和后台增加项目跳转按钮(管理员可见) 190 | - 【其他】热门文章模块增加更多文章按钮 191 | 192 | ## 01-17 193 | 194 | - 【BUG】修复文章详情页标题不能动态显示 195 | 196 | ## 01-10 197 | 198 | - 【页面】+ 文章列表页 199 | - 【模块】+ 搜索框 200 | - 【功能】+ 搜索(支持搜索文章标题) 201 | - 【扩展】+ Markdown 解析器(支持 Markdown 语法) 202 | 203 | ## 2017-01-09 204 | 205 | - 【网站上线】 206 | - 【页面】+ 首页、文章详情页 207 | - 【模块】+ 轮播图、最新文章、作者信息、最热文章 208 | - 【后台】+ 文章管理 209 | - 【功能】+ 用户注册/登录 210 | - 【扩展】+ 中文语言包(实现中文语言支持) 211 | - 【优化】无 212 | - 【其他】无 213 | - 【BUG】无 214 | -------------------------------------------------------------------------------- /resources/assets/js/app.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * First we will load all of this project's JavaScript dependencies which 4 | * include Vue and Vue Resource. This gives a great starting point for 5 | * building robust, powerful web applications using Vue and Laravel. 6 | */ 7 | 8 | require('./bootstrap'); 9 | 10 | //给 AJAX 全局加入 csrf-token 11 | $.ajaxSetup({ 12 | headers: { 13 | 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 14 | } 15 | }); 16 | 17 | /** 18 | * Next, we will create a fresh Vue application instance and attach it to 19 | * the body of the page. From here, you may begin adding components to 20 | * the application, or feel free to tweak this setup for your needs. 21 | */ 22 | 23 | //Vue.component('reply', require('./components/Reply.vue')); 24 | 25 | const app = new Vue({ 26 | el: '#app' 27 | }); 28 | -------------------------------------------------------------------------------- /resources/assets/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | 2 | window._ = require('lodash'); 3 | 4 | /** 5 | * We'll load jQuery and the Bootstrap jQuery plugin which provides support 6 | * for JavaScript based Bootstrap features such as modals and tabs. This 7 | * code may be modified to fit the specific needs of your application. 8 | */ 9 | 10 | window.$ = window.jQuery = require('jquery'); 11 | require('bootstrap-sass'); 12 | 13 | /** 14 | * Vue is a modern JavaScript library for building interactive web interfaces 15 | * using reactive data binding and reusable components. Vue's API is clean 16 | * and simple, leaving you to focus on building your next great project. 17 | */ 18 | 19 | window.Vue = require('vue'); 20 | require('vue-resource'); 21 | 22 | /** 23 | * We'll register a HTTP interceptor to attach the "CSRF" header to each of 24 | * the outgoing requests issued by this application. The CSRF middleware 25 | * included with Laravel will automatically verify the header's value. 26 | */ 27 | 28 | Vue.http.interceptors.push((request, next) => { 29 | request.headers.set('X-CSRF-TOKEN', Laravel.csrfToken); 30 | 31 | next(); 32 | }); 33 | 34 | /** 35 | * Echo exposes an expressive API for subscribing to channels and listening 36 | * for events that are broadcast by Laravel. Echo and event broadcasting 37 | * allows your team to easily build robust real-time web applications. 38 | */ 39 | 40 | // import Echo from "laravel-echo" 41 | 42 | // window.Echo = new Echo({ 43 | // broadcaster: 'pusher', 44 | // key: 'your-pusher-key' 45 | // }); 46 | -------------------------------------------------------------------------------- /resources/assets/js/components/Example.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /resources/assets/js/components/Reply.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/N1ghtJs/laravel-blog/5d154add32c1ae4bf724555044f307aeb3ccc8b6/resources/assets/js/components/Reply.vue -------------------------------------------------------------------------------- /resources/assets/sass/_variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // Body 3 | $body-bg: #f5f8fa; 4 | 5 | // Borders 6 | $laravel-border-color: darken($body-bg, 10%); 7 | $list-group-border: $laravel-border-color; 8 | $navbar-default-border: $laravel-border-color; 9 | $panel-default-border: $laravel-border-color; 10 | $panel-inner-border: $laravel-border-color; 11 | 12 | // Brands 13 | $brand-primary: #3097D1; 14 | $brand-info: #8eb4cb; 15 | $brand-success: #2ab27b; 16 | $brand-warning: #cbb956; 17 | $brand-danger: #bf5329; 18 | 19 | // Typography 20 | $font-family-sans-serif: "Times new roman", "Arial", "Microsoft YaHei", "黑体", "宋体", sans-serif; 21 | $font-size-base: 14px; 22 | $line-height-base: 1.6; 23 | $text-color: #636b6f; 24 | 25 | // Navbar 26 | $navbar-default-bg: #fff; 27 | 28 | // Buttons 29 | $btn-default-color: $text-color; 30 | 31 | // Inputs 32 | $input-border: lighten($text-color, 40%); 33 | $input-border-focus: lighten($brand-primary, 25%); 34 | $input-color-placeholder: lighten($text-color, 30%); 35 | 36 | // Panels 37 | $panel-default-heading-bg: #fff; 38 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | '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/lang/en/validation.php: -------------------------------------------------------------------------------- 1 | 'The :attribute must be accepted.', 17 | 'active_url' => 'The :attribute is not a valid URL.', 18 | 'after' => 'The :attribute must be a date after :date.', 19 | 'alpha' => 'The :attribute may only contain letters.', 20 | 'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.', 21 | 'alpha_num' => 'The :attribute may only contain letters and numbers.', 22 | 'array' => 'The :attribute must be an array.', 23 | 'before' => 'The :attribute must be a date before :date.', 24 | 'between' => [ 25 | 'numeric' => 'The :attribute must be between :min and :max.', 26 | 'file' => 'The :attribute must be between :min and :max kilobytes.', 27 | 'string' => 'The :attribute must be between :min and :max characters.', 28 | 'array' => 'The :attribute must have between :min and :max items.', 29 | ], 30 | 'boolean' => 'The :attribute field must be true or false.', 31 | 'confirmed' => 'The :attribute confirmation does not match.', 32 | 'date' => 'The :attribute is not a valid date.', 33 | 'date_format' => 'The :attribute does not match the format :format.', 34 | 'different' => 'The :attribute and :other must be different.', 35 | 'digits' => 'The :attribute must be :digits digits.', 36 | 'digits_between' => 'The :attribute must be between :min and :max digits.', 37 | 'dimensions' => 'The :attribute has invalid image dimensions.', 38 | 'distinct' => 'The :attribute field has a duplicate value.', 39 | 'email' => 'The :attribute must be a valid email address.', 40 | 'exists' => 'The selected :attribute is invalid.', 41 | 'file' => 'The :attribute must be a file.', 42 | 'filled' => 'The :attribute field is required.', 43 | 'image' => 'The :attribute must be an image.', 44 | 'in' => 'The selected :attribute is invalid.', 45 | 'in_array' => 'The :attribute field does not exist in :other.', 46 | 'integer' => 'The :attribute must be an integer.', 47 | 'ip' => 'The :attribute must be a valid IP address.', 48 | 'json' => 'The :attribute must be a valid JSON string.', 49 | 'max' => [ 50 | 'numeric' => 'The :attribute may not be greater than :max.', 51 | 'file' => 'The :attribute may not be greater than :max kilobytes.', 52 | 'string' => 'The :attribute may not be greater than :max characters.', 53 | 'array' => 'The :attribute may not have more than :max items.', 54 | ], 55 | 'mimes' => 'The :attribute must be a file of type: :values.', 56 | 'mimetypes' => 'The :attribute must be a file of type: :values.', 57 | 'min' => [ 58 | 'numeric' => 'The :attribute must be at least :min.', 59 | 'file' => 'The :attribute must be at least :min kilobytes.', 60 | 'string' => 'The :attribute must be at least :min characters.', 61 | 'array' => 'The :attribute must have at least :min items.', 62 | ], 63 | 'not_in' => 'The selected :attribute is invalid.', 64 | 'numeric' => 'The :attribute must be a number.', 65 | 'present' => 'The :attribute field must be present.', 66 | 'regex' => 'The :attribute format is invalid.', 67 | 'required' => 'The :attribute field is required.', 68 | 'required_if' => 'The :attribute field is required when :other is :value.', 69 | 'required_unless' => 'The :attribute field is required unless :other is in :values.', 70 | 'required_with' => 'The :attribute field is required when :values is present.', 71 | 'required_with_all' => 'The :attribute field is required when :values is present.', 72 | 'required_without' => 'The :attribute field is required when :values is not present.', 73 | 'required_without_all' => 'The :attribute field is required when none of :values are present.', 74 | 'same' => 'The :attribute and :other must match.', 75 | 'size' => [ 76 | 'numeric' => 'The :attribute must be :size.', 77 | 'file' => 'The :attribute must be :size kilobytes.', 78 | 'string' => 'The :attribute must be :size characters.', 79 | 'array' => 'The :attribute must contain :size items.', 80 | ], 81 | 'string' => 'The :attribute must be a string.', 82 | 'timezone' => 'The :attribute must be a valid zone.', 83 | 'unique' => 'The :attribute has already been taken.', 84 | 'uploaded' => 'The :attribute failed to upload.', 85 | 'url' => 'The :attribute format is invalid.', 86 | 87 | /* 88 | |-------------------------------------------------------------------------- 89 | | Custom Validation Language Lines 90 | |-------------------------------------------------------------------------- 91 | | 92 | | Here you may specify custom validation messages for attributes using the 93 | | convention "attribute.rule" to name the lines. This makes it quick to 94 | | specify a specific custom language line for a given attribute rule. 95 | | 96 | */ 97 | 98 | 'custom' => [ 99 | 'attribute-name' => [ 100 | 'rule-name' => 'custom-message', 101 | ], 102 | ], 103 | 104 | /* 105 | |-------------------------------------------------------------------------- 106 | | Custom Validation Attributes 107 | |-------------------------------------------------------------------------- 108 | | 109 | | The following language lines are used to swap attribute place-holders 110 | | with something more reader friendly such as E-Mail Address instead 111 | | of "email". This simply helps us make messages a little cleaner. 112 | | 113 | */ 114 | 115 | 'attributes' => [], 116 | 117 | ]; 118 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/auth.php: -------------------------------------------------------------------------------- 1 | '用户名或密码错误。', 17 | 'throttle' => '您的尝试登录次数过多. 请 :seconds 秒后再试。', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/pagination.php: -------------------------------------------------------------------------------- 1 | '« 上一页', 17 | 'next' => '下一页 »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/passwords.php: -------------------------------------------------------------------------------- 1 | '密码至少是六位字符并且匹配。', 17 | 'reset' => '密码重置成功!', 18 | 'sent' => '密码重置邮件已发送!', 19 | 'token' => '密码重置令牌无效。', 20 | 'user' => '找不到该邮箱对应的用户。', 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/views/admin/admin.blade.php: -------------------------------------------------------------------------------- 1 | {{-- 这是管理后台公共视图模板:包含了左侧菜单栏,右侧内容区 --}} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | @yield('title', '管理后台') - lhz的个人主页 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | @yield('styles') 21 | 22 | 23 | 24 | 25 | {{--左侧垂直菜单栏--}} 26 |
27 |
28 | 29 | 32 | 33 |
34 | << 35 |
36 |
37 | 49 |
50 | {{--右侧内容区--}} 51 |
52 |
53 | 54 |
55 |
56 | @include('shared.messages') 57 | @yield('content') 58 |
59 | 60 |
61 | 62 | 63 | 64 | @yield('scripts') 65 | 66 | -------------------------------------------------------------------------------- /resources/views/admin/article/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('title', '新建文章') 4 | 5 | @section('content') 6 |
7 |
8 |
9 |

新增一篇文章

10 | 11 | @include('shared.errors') 12 | 13 | {{--新增文章表单--}} 14 |
15 | {{ csrf_field() }} 16 | 17 | 18 | 19 | 20 |
21 | 22 | 26 | 27 | 28 |
29 |
30 | 31 |
32 |
33 |
34 | 预览 35 |
36 |
37 |
38 |
39 | 40 |
41 | 42 | 43 |
44 | 45 |
46 | 47 |
48 |
49 |
50 | @endsection 51 | 52 | @section('scripts') 53 | 81 | @endsection 82 | -------------------------------------------------------------------------------- /resources/views/admin/article/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('title', '编辑文章') 4 | 5 | @section('content') 6 |
7 |
8 |
9 |

编辑文章

10 | 11 | @include('shared.errors') 12 | 13 | {{--新增文章表单--}} 14 |
15 | {{ csrf_field() }} 16 | {{ method_field('PATCH') }} 17 | 18 | 19 | 20 |
21 | 22 | 26 | 27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 |
35 | 36 |
37 |
38 |
39 |
40 |
41 | 42 | 43 |
44 | 45 |
46 | 47 |
48 |
49 |
50 | @endsection 51 | 52 | @section('scripts') 53 | 54 | 82 | @endsection 83 | -------------------------------------------------------------------------------- /resources/views/admin/article/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('title', '文章列表') 4 | 5 | @section('content') 6 | 添加文章 7 | 8 | 9 | 10 | 11 | 12 | 13 | @foreach ($articles as $article) 14 | 15 | 16 | 17 | 46 | 47 | @endforeach 48 |
标题简介操作
{{ $article->title }}{{ $article->intro }} 18 | 19 | @if( $article->hidden == 0) 20 | 21 | @else 22 | 23 | @endif 24 | 25 | 26 | 27 | 45 |
49 | 50 | {{ $articles->render() }} 51 | @endsection 52 | -------------------------------------------------------------------------------- /resources/views/admin/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('admin.admin') 2 | 3 | @section('title', '后台首页') 4 | 5 | @section('content') 6 |
7 |
8 |
9 | 10 | 11 |
12 |
13 |
14 | @endsection 15 | -------------------------------------------------------------------------------- /resources/views/article/list.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app_2columns') 2 | 3 | @section('title', '文章') 4 | 5 | @section('content-left') 6 | 7 |
8 |
9 | 文章列表 10 |
11 |
12 | @each('shared.article_little', $articles, 'article') 13 |
14 |
15 | {{ $articles->render() }} 16 | 17 | @endsection 18 | -------------------------------------------------------------------------------- /resources/views/auth/login.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app_imax') 2 | 3 | @section('title', '登录') 4 | 5 | @section('content') 6 |
7 |
8 |
9 |
10 |
登录
11 |
12 |
13 | {{ csrf_field() }} 14 | 15 |
16 | 17 | 18 |
19 | 20 | 21 | @if ($errors->has('email')) 22 | 23 | {{ $errors->first('email') }} 24 | 25 | @endif 26 |
27 |
28 | 29 |
30 | 31 | 32 |
33 | 34 | 35 | @if ($errors->has('password')) 36 | 37 | {{ $errors->first('password') }} 38 | 39 | @endif 40 |
41 |
42 | 43 |
44 |
45 |
46 | 49 |
50 |
51 |
52 | 53 |
54 |
55 | 58 | 59 | 60 | 找回密码 61 | 62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | @endsection 71 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/email.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app_imax') 2 | 3 | @section('title', '重置密码') 4 | 5 | 6 | @section('content') 7 |
8 |
9 |
10 |
11 |
重置密码
12 |
13 | @if (session('status')) 14 |
15 | {{ session('status') }} 16 |
17 | @endif 18 | 19 |
20 | {{ csrf_field() }} 21 | 22 |
23 | 24 | 25 |
26 | 27 | 28 | @if ($errors->has('email')) 29 | 30 | {{ $errors->first('email') }} 31 | 32 | @endif 33 |
34 |
35 | 36 |
37 |
38 | 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | @endsection 50 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/reset.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app_imax') 2 | 3 | @section('title', '重置密码') 4 | 5 | @section('content') 6 |
7 |
8 |
9 |
10 |
重置密码
11 | 12 |
13 | @if (session('status')) 14 |
15 | {{ session('status') }} 16 |
17 | @endif 18 | 19 |
20 | {{ csrf_field() }} 21 | 22 | 23 | 24 |
25 | 26 | 27 |
28 | 29 | 30 | @if ($errors->has('email')) 31 | 32 | {{ $errors->first('email') }} 33 | 34 | @endif 35 |
36 |
37 | 38 |
39 | 40 | 41 |
42 | 43 | 44 | @if ($errors->has('password')) 45 | 46 | {{ $errors->first('password') }} 47 | 48 | @endif 49 |
50 |
51 | 52 |
53 | 54 |
55 | 56 | 57 | @if ($errors->has('password_confirmation')) 58 | 59 | {{ $errors->first('password_confirmation') }} 60 | 61 | @endif 62 |
63 |
64 | 65 |
66 |
67 | 70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | @endsection 79 | -------------------------------------------------------------------------------- /resources/views/auth/register.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app_imax') 2 | 3 | @section('title', '注册') 4 | 5 | @section('content') 6 |
7 |
8 |
9 |
10 |
注册
11 |
12 |
13 | {{ csrf_field() }} 14 | 15 |
16 | 17 | 18 |
19 | 20 | 21 | @if ($errors->has('name')) 22 | 23 | {{ $errors->first('name') }} 24 | 25 | @endif 26 |
27 |
28 | 29 |
30 | 31 | 32 |
33 | 34 | 35 | @if ($errors->has('email')) 36 | 37 | {{ $errors->first('email') }} 38 | 39 | @endif 40 |
41 |
42 | 43 |
44 | 45 | 46 |
47 | 48 | 49 | @if ($errors->has('password')) 50 | 51 | {{ $errors->first('password') }} 52 | 53 | @endif 54 |
55 |
56 | 57 |
58 | 59 | 60 |
61 | 62 |
63 |
64 | 65 | 66 | 83 | 84 |
85 |
86 | 89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | @endsection 98 | -------------------------------------------------------------------------------- /resources/views/emails/email.blade.php: -------------------------------------------------------------------------------- 1 | {{-- 这是邮件视图模板--}} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | @yield('styles') 15 | 16 | 17 |
18 | @yield('content') 19 |
20 | 21 | 22 | 23 | @yield('script') 24 | 25 | 26 | -------------------------------------------------------------------------------- /resources/views/emails/new_comment.blade.php: -------------------------------------------------------------------------------- 1 | @extends('emails.email') 2 | 3 | @section('content') 4 | 点此查看 5 | @endsection 6 | -------------------------------------------------------------------------------- /resources/views/emails/new_message.blade.php: -------------------------------------------------------------------------------- 1 | @extends('emails.email') 2 | 3 | @section('content') 4 | 点此查看 5 | @endsection 6 | -------------------------------------------------------------------------------- /resources/views/errors/503.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Be right back. 5 | 6 | 7 | 8 | 39 | 40 | 41 |
42 |
43 |
Be right back.
44 |
45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app_2columns') 2 | 3 | @section('title', '首页') 4 | 5 | @section('content-left') 6 | 7 | @include('shared.slides') 8 | 9 | 10 |
11 |
12 | 最新文章 13 |
14 |
15 | @each('shared.article', $articles_new, 'article') 16 |
17 | 20 |
21 | @endsection 22 | -------------------------------------------------------------------------------- /resources/views/layouts/_footer.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 别拉了,到底了~ 6 |
7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /resources/views/layouts/_header.blade.php: -------------------------------------------------------------------------------- 1 | 70 | -------------------------------------------------------------------------------- /resources/views/layouts/app_2columns.blade.php: -------------------------------------------------------------------------------- 1 | {{-- 这是两栏布局视图模板:包含了导航栏、巨幕、作者信息侧栏、底部信息栏 --}} 2 | @extends('layouts.app_imax') 3 | 4 | @section('content') 5 |
6 |
7 | 8 | @yield('content-left') 9 |
10 | 11 |
12 | 13 | @include('shared.author_info') 14 | 15 | 16 | @include('shared.article_hot') 17 | 18 | 19 | @include('shared.message_new') 20 | 21 | 22 | @include('shared.links') 23 | 24 | 25 | @include('shared.ads') 26 |
27 |
28 | @endsection 29 | -------------------------------------------------------------------------------- /resources/views/layouts/app_imax.blade.php: -------------------------------------------------------------------------------- 1 | {{-- 这是带巨幕图的公共视图模板:包含了导航栏、巨幕、底部信息栏 --}} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | @yield('title', '无标题') - lhz的博客 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | @yield('styles') 21 | 22 | 23 | 24 | @include('layouts._header') 25 |
26 | 27 | 28 |
29 | 30 |
31 | @include('shared.messages') 32 | @yield('content') 33 | @include('layouts._footer') 34 |
35 | 36 | 37 | 38 | @yield('script') 39 | 40 | 41 | -------------------------------------------------------------------------------- /resources/views/shared/ads.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 广告位 5 |
6 |
7 | 34 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /resources/views/shared/article.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |
{{ $article->title }}
8 | {{ $article->view }} 9 | {{ $article->comment }} 10 | {{ $article->created_at }} 11 |

{{ $article->intro}}

12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /resources/views/shared/article_hot.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 热门文章 5 |
6 |
7 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /resources/views/shared/article_little.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 |
7 |
8 | {{ $article->view }} 9 | {{ $article->comment }} 10 | {{ $article->created_at->diffForHumans() }} 11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /resources/views/shared/author_info.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | SadCreeper 4 |
5 |
6 |
7 | 8 |
9 | 10 |

生活可以随心所欲,但不能随波逐流

11 | 12 | {{--微信弹出框--}} 13 | 14 | wechat 15 | 16 | 23 | {{--QQ弹出框--}} 24 | 25 | qq 26 | 27 | 34 | 35 | 36 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /resources/views/shared/errors.blade.php: -------------------------------------------------------------------------------- 1 | @if (count($errors) > 0) 2 |
3 |
    4 | @foreach($errors->all() as $error) 5 |
  • {{ $error }}
  • 6 | @endforeach 7 |
8 |
9 | @endif 10 | -------------------------------------------------------------------------------- /resources/views/shared/links.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 14 | -------------------------------------------------------------------------------- /resources/views/shared/message_new.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 最新留言 5 |
6 |
7 |
    8 | @foreach ($messages_new as $message) 9 |
  • 10 | @if( $message->user_id == 0) 11 | 匿名 12 | @else 13 | {{ $message->user->name }} 14 | @endif 15 | :{{ $message->content }} 16 |
  • 17 | @endforeach 18 |
19 |
20 | 24 |
25 | -------------------------------------------------------------------------------- /resources/views/shared/messages.blade.php: -------------------------------------------------------------------------------- 1 | @foreach (['danger', 'warning', 'success', 'info'] as $msg) 2 | @if(session()->has($msg)) 3 |
4 |

5 | {{ session()->get($msg) }} 6 |

7 |
8 | @endif 9 | @endforeach 10 | -------------------------------------------------------------------------------- /resources/views/shared/slides.blade.php: -------------------------------------------------------------------------------- 1 | {{--轮播--}} 2 | 23 | -------------------------------------------------------------------------------- /resources/views/shared/user_info.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{ Auth::user()->name }} 4 |
5 |
6 | 7 |
8 |
9 | -------------------------------------------------------------------------------- /resources/views/todos/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app_imax') 2 | 3 | @section('title', "TODO") 4 | 5 | @section('styles') 6 | 15 | @endsection 16 | 17 | @section('content') 18 | 19 |
20 |
21 |
22 | {{ csrf_field() }} 23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
    37 | @foreach($todos as $todo) 38 |
  • 39 | 40 |
    {{ $todo->content }}
    41 |
    42 | {{ csrf_field() }} 43 | {{ method_field('DELETE') }} 44 | 45 |
    46 |
  • 47 | @endforeach 48 |
49 |
50 |
51 | @endsection 52 | 53 | @section('script') 54 | {{--拖放排序--}} 55 | 56 | 86 | @endsection 87 | -------------------------------------------------------------------------------- /resources/views/vendor/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/views/vendor/notifications/email-plain.blade.php: -------------------------------------------------------------------------------- 1 | hasPages()) 2 |
    3 | {{-- Previous Page Link --}} 4 | @if ($paginator->onFirstPage()) 5 |
  • «
  • 6 | @else 7 |
  • 8 | @endif 9 | 10 | {{-- Pagination Elements --}} 11 | @foreach ($elements as $element) 12 | {{-- "Three Dots" Separator --}} 13 | @if (is_string($element)) 14 |
  • {{ $element }}
  • 15 | @endif 16 | 17 | {{-- Array Of Links --}} 18 | @if (is_array($element)) 19 | @foreach ($element as $page => $url) 20 | @if ($page == $paginator->currentPage()) 21 |
  • {{ $page }}
  • 22 | @else 23 |
  • {{ $page }}
  • 24 | @endif 25 | @endforeach 26 | @endif 27 | @endforeach 28 | 29 | {{-- Next Page Link --}} 30 | @if ($paginator->hasMorePages()) 31 |
  • 32 | @else 33 |
  • »
  • 34 | @endif 35 |
36 | @endif 37 | -------------------------------------------------------------------------------- /resources/views/vendor/pagination/default.blade.php: -------------------------------------------------------------------------------- 1 | @if ($paginator->hasPages()) 2 |
    3 | {{-- Previous Page Link --}} 4 | @if ($paginator->onFirstPage()) 5 |
  • «
  • 6 | @else 7 |
  • 8 | @endif 9 | 10 | {{-- Pagination Elements --}} 11 | @foreach ($elements as $element) 12 | {{-- "Three Dots" Separator --}} 13 | @if (is_string($element)) 14 |
  • {{ $element }}
  • 15 | @endif 16 | 17 | {{-- Array Of Links --}} 18 | @if (is_array($element)) 19 | @foreach ($element as $page => $url) 20 | @if ($page == $paginator->currentPage()) 21 |
  • {{ $page }}
  • 22 | @else 23 |
  • {{ $page }}
  • 24 | @endif 25 | @endforeach 26 | @endif 27 | @endforeach 28 | 29 | {{-- Next Page Link --}} 30 | @if ($paginator->hasMorePages()) 31 |
  • 32 | @else 33 |
  • »
  • 34 | @endif 35 |
36 | @endif 37 | -------------------------------------------------------------------------------- /resources/views/vendor/pagination/simple-bootstrap-4.blade.php: -------------------------------------------------------------------------------- 1 | @if ($paginator->hasPages()) 2 |
    3 | {{-- Previous Page Link --}} 4 | @if ($paginator->onFirstPage()) 5 |
  • «
  • 6 | @else 7 |
  • 8 | @endif 9 | 10 | {{-- Next Page Link --}} 11 | @if ($paginator->hasMorePages()) 12 |
  • 13 | @else 14 |
  • »
  • 15 | @endif 16 |
17 | @endif 18 | -------------------------------------------------------------------------------- /resources/views/vendor/pagination/simple-default.blade.php: -------------------------------------------------------------------------------- 1 | @if ($paginator->hasPages()) 2 |
    3 | {{-- Previous Page Link --}} 4 | @if ($paginator->onFirstPage()) 5 |
  • «
  • 6 | @else 7 |
  • 8 | @endif 9 | 10 | {{-- Next Page Link --}} 11 | @if ($paginator->hasMorePages()) 12 |
  • 13 | @else 14 |
  • »
  • 15 | @endif 16 |
17 | @endif 18 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | user(); 18 | })->middleware('auth:api'); 19 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 18 | })->describe('Display an inspiring quote'); 19 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | name('home'); 19 | 20 | //文章列表页 21 | Route::get('/article/list', 'ArticleController@list')->name('article.list'); 22 | //文章搜索页 23 | Route::get('/article/search', 'ArticleController@search')->name('article.search'); 24 | //文章资源路由 25 | Route::get('article/{article}', 'ArticleController@show')->name('article.show'); 26 | //markdown AJAX 解析 27 | Route::post('/markdown', 'ArticleController@markdown')->name('markdown'); 28 | //markdown AJAX 获取文章内容 29 | Route::get('/markdown/{article}', 'ArticleController@markdown_article')->name('markdown.article'); 30 | 31 | 32 | //评论资源路由 33 | Route::post('/comments', 'CommentsController@store')->middleware('throttle:5')->name('comments.store'); 34 | //回复(评论)资源路由 35 | Route::post('/replys', 'ReplysController@store')->middleware('throttle:5')->name('replys.store'); 36 | //回复(留言)资源路由 37 | Route::post('/remessags', 'RemessagesController@store')->middleware('throttle:5')->name('remessages.store'); 38 | //留言资源路由 39 | Route::get('messages', 'MessagesController@index')->name('messages.index'); 40 | Route::post('messages', 'MessagesController@store')->middleware('throttle:5')->name('messages.store'); 41 | 42 | //todo 资源路由 43 | Route::get('/todos', 'TodosController@index')->name('todos.index'); 44 | //Route::get('/todos/create', 'TodosController@create')->name('todos.create'); 45 | Route::post('/todos', 'TodosController@store')->name('todos.store'); 46 | //Route::get('/todos/{todo}', 'TodosController@show')->name('todos.show'); 47 | //Route::get('/todos/{todo}/edit', 'TodosController@edit')->name('todos.edit'); 48 | //Route::patch('/todos/{todo}', 'TodosController@update')->name('todos.update'); 49 | Route::delete('/todos/{todo}', 'TodosController@destroy')->name('todos.destroy'); 50 | 51 | //管理后台 52 | Route::group(['middleware' => ['auth'],'namespace' => 'Admin','prefix' => 'admin'],function(){ 53 | //首页 54 | Route::get('/','AdminController@index')->name('admin'); 55 | 56 | //文章隐藏 57 | Route::get('/article/hidden/{id}', 'ArticleController@hidden')->name('article.hidden'); 58 | 59 | //文章资源路由 60 | Route::resource('article','ArticleController', ['except' => 'show']); 61 | }); 62 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/debugbar/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | schedule-* 4 | compiled.php 5 | services.json 6 | events.scanned.php 7 | routes.scanned.php 8 | down 9 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/ExampleTest.php: -------------------------------------------------------------------------------- 1 | visit('/') 17 | ->see('Laravel'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | make(Illuminate\Contracts\Console\Kernel::class)->bootstrap(); 22 | 23 | return $app; 24 | } 25 | } 26 | --------------------------------------------------------------------------------