瀏覽代碼

修改 controller

oransheep 2 年之前
父節點
當前提交
49409581ed

+ 53 - 8
app/Http/Controllers/BlogController.php

@@ -14,7 +14,33 @@ class BlogController extends Controller
      */
     public function index()
     {
-        //
+        return Blog::all();
+    }
+
+    public function index_page(Request $request)
+    {
+        return Blog::offset($request->offset)->limit($request->rows)->get();
+    }
+
+    public function sidebar(Request $request)
+    {
+        return [
+            // 'recentPosts' => Blog::whereIn('id', $request->rankingList)->get(),
+            'recentPosts' => Blog::limit(4)->get(),
+            'categories' => [
+                ['category' => 'Fashion', 'icon' => 'WatchIcon'],
+                ['category' => 'Food', 'icon' => 'ShoppingCartIcon'],
+                ['category' => 'Gaming', 'icon' => 'CommandIcon'],
+                ['category' => 'Quote', 'icon' => 'HashIcon'],
+                ['category' => 'Video', 'icon' => 'VideoIcon'],
+            ]
+        ];
+    }
+
+    public function total_count()
+    {
+        $list = Blog::all();
+        return $list->count();
     }
 
     /**
@@ -35,7 +61,15 @@ class BlogController extends Controller
      */
     public function store(Request $request)
     {
-        //
+        Blog::insert([
+            'title' => $request->title,
+            'content' => $request->content,
+            'tags' => $request->tags,
+            'authorId' => $request->userId,
+            'bookmarked' => 0,
+            'created_at' => now(),
+            'updated_at' => now(),
+        ]);
     }
 
     /**
@@ -44,9 +78,11 @@ class BlogController extends Controller
      * @param  \App\Models\Blog  $blog
      * @return \Illuminate\Http\Response
      */
-    public function show(Blog $blog)
+    public function show(Request $request)
     {
-        //
+        $blog = Blog::where('id', '=', $request->blogId)->first();
+        $blog->tags = json_decode($blog->tags);
+        return $blog;
     }
 
     /**
@@ -55,9 +91,18 @@ class BlogController extends Controller
      * @param  \App\Models\Blog  $blog
      * @return \Illuminate\Http\Response
      */
-    public function edit(Blog $blog)
+    public function edit(Request $request)
     {
-        //
+        $blog = Blog::where('id', $request->blogId)->first();
+
+        if ($blog->authorId == $request->userId) {
+            $blog->update([
+                'title' => $request->title,
+                'content' => $request->content,
+                'tags' => $request->tags,
+                'updated_at' => now(),
+            ]);
+        }
     }
 
     /**
@@ -78,8 +123,8 @@ class BlogController extends Controller
      * @param  \App\Models\Blog  $blog
      * @return \Illuminate\Http\Response
      */
-    public function destroy(Blog $blog)
+    public function destroy(Request $request)
     {
-        //
+        Blog::where('id', '=', $request->blogId)->delete();
     }
 }

+ 23 - 4
app/Http/Controllers/BlogImageController.php

@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
 
 use App\Models\BlogImage;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Storage;
 
 class BlogImageController extends Controller
 {
@@ -14,7 +15,7 @@ class BlogImageController extends Controller
      */
     public function index()
     {
-        //
+        return BlogImage::all();
     }
 
     /**
@@ -35,7 +36,25 @@ class BlogImageController extends Controller
      */
     public function store(Request $request)
     {
-        //
+
+        $save_name = time() . '.jpg';
+        $saveImgPath = 'blog/banner/' . $save_name;
+
+        BlogImage::insert([
+            'blogId' => $request->blogId,
+            'saveName' => $save_name,
+            'fileName' => $request->fileName,
+            'created_at' => now(),
+            'updated_at' => now(),
+        ]);
+
+        if ($request->bannerImage) {
+            $image_64 = $request->bannerImage;
+            $replace = substr($image_64, 0, strpos($image_64, ',') + 1);
+            $image = str_replace($replace, '', $image_64);
+            $image = str_replace(' ', '+', $image);
+            Storage::disk('local')->put($saveImgPath, base64_decode($image));
+        }
     }
 
     /**
@@ -44,9 +63,9 @@ class BlogImageController extends Controller
      * @param  \App\Models\BlogImage  $blogImage
      * @return \Illuminate\Http\Response
      */
-    public function show(BlogImage $blogImage)
+    public function show(Request $request)
     {
-        //
+        return BlogImage::where('id', '=', $request->blogId)->first();
     }
 
     /**

+ 22 - 5
app/Http/Controllers/CommentController.php

@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
 
 use App\Models\Comment;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
 
 class CommentController extends Controller
 {
@@ -17,6 +18,16 @@ class CommentController extends Controller
         //
     }
 
+    public function index_count()
+    {
+        return Comment::select('blogId', DB::raw('count(*) as total'))->groupBy('blogId')->reorder('total', 'desc')->get();
+    }
+
+    public function index_by_blog(Request $request)
+    {
+        return Comment::where('blogId', '=', $request->blogId)->get();
+    }
+
     /**
      * Show the form for creating a new resource.
      *
@@ -35,7 +46,13 @@ class CommentController extends Controller
      */
     public function store(Request $request)
     {
-        //
+        Comment::insert([
+            'authorId' => $request->user()->id,
+            'comment' => $request->comment,
+            'blogId' => $request->blogId,
+            'created_at' => now(),
+            'updated_at' => now(),
+        ]);
     }
 
     /**
@@ -44,9 +61,9 @@ class CommentController extends Controller
      * @param  \App\Models\Comment  $comment
      * @return \Illuminate\Http\Response
      */
-    public function show(Comment $comment)
+    public function show(Request $request)
     {
-        //
+        return Comment::where('id', '=', $request->commentId)->first();
     }
 
     /**
@@ -78,8 +95,8 @@ class CommentController extends Controller
      * @param  \App\Models\Comment  $comment
      * @return \Illuminate\Http\Response
      */
-    public function destroy(Comment $comment)
+    public function destroy(Request $request)
     {
-        //
+        Comment::where('id', '=', $request->commentId)->delete();
     }
 }

+ 85 - 0
app/Http/Controllers/UserController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\User;
+use Illuminate\Http\Request;
+
+class UserController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        return User::all();
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function show(Request $request)
+    {
+        return User::where('id', '=', $request->userId)->first();
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function edit($id)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, $id)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Request $request)
+    {
+        return User::where('id', '=', $request->userId)->delete();
+    }
+}

+ 30 - 0
app/Http/Requests/CommentRequest.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CommentRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return false;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, mixed>
+     */
+    public function rules()
+    {
+        return [
+            //
+        ];
+    }
+}

+ 1 - 1
app/Models/Blog.php

@@ -13,7 +13,7 @@ class Blog extends Model
         'title',
         'content',
         'tags',
-        'writer',
+        'authorId',
         'bookmarked',
     ];
 }

+ 2 - 2
app/Models/BlogImage.php

@@ -11,7 +11,7 @@ class BlogImage extends Model
 
     protected $fillable = [
         'blogId',
-        'path',
-        'name',
+        'saveName',
+        'fileName',
     ];
 }

+ 1 - 1
app/Models/Comment.php

@@ -10,7 +10,7 @@ class Comment extends Model
     use HasFactory;
 
     protected $fillable = [
-        'writer',
+        'authorId',
         'comment',
         'blogId',
     ];

+ 1 - 1
database/factories/BlogFactory.php

@@ -21,7 +21,7 @@ class BlogFactory extends Factory
             'title' => $this->faker->realText($maxNbChars = 20, $indexSize = 2),
             'content' => $this->faker->realText($maxNbChars = 200, $indexSize = 2),
             'tags' => json_encode(['Gaming', 'Video', 'Fashion']),
-            'writer' => $this->faker->randomElement(User::query()->get('id')),
+            'authorId' => $this->faker->randomElement(User::query()->get('id')),
             'bookmarked' => rand(0,10000),
         ];
     }

+ 1 - 1
database/factories/CommentFactory.php

@@ -19,7 +19,7 @@ class CommentFactory extends Factory
     public function definition()
     {
         return [
-            'writer' => $this->faker->randomElement(User::query()->get('id')),
+            'authorId' => $this->faker->randomElement(User::query()->get('id')),
             'comment' => $this->faker->realText($maxNbChars = 200, $indexSize = 2),
             'blogId' => $this->faker->randomElement(Blog::query()->get('id')),
         ];

+ 1 - 1
database/migrations/2022_12_14_051611_create_blogs_table.php

@@ -18,7 +18,7 @@ return new class extends Migration
             $table->string('title');
             $table->string('content');
             $table->string('tags');
-            $table->string('writer');
+            $table->string('authorId');
             $table->integer('bookmarked');
             $table->timestamps();
         });

+ 1 - 1
database/migrations/2022_12_14_060941_create_comments_table.php

@@ -15,7 +15,7 @@ return new class extends Migration
     {
         Schema::create('comments', function (Blueprint $table) {
             $table->id();
-            $table->integer('writer');
+            $table->integer('authorId');
             $table->string('comment');
             $table->integer('blogId');
             $table->timestamps();

+ 2 - 2
database/migrations/2022_12_19_151815_create_blog_images_table.php

@@ -16,8 +16,8 @@ return new class extends Migration
         Schema::create('blog_images', function (Blueprint $table) {
             $table->id();
             $table->integer('blogId');
-            $table->string('path');
-            $table->string('name');
+            $table->string('saveName');
+            $table->string('fileName');
             $table->timestamps();
         });
     }

+ 91 - 45
resources/js/src/views/blog/BlogDetail.vue

@@ -6,33 +6,32 @@
       <b-row>
         <!-- blogs -->
         <b-col cols="12">
-          <b-card :img-src="getImg(blogDetail.blog.path)" img-top img-alt="Blog Detail Pic"
-            :title="blogDetail.blog.title">
+          <b-card :img-src="getBannerImg(blogDetail.id)" img-top img-alt="Blog Detail Pic" :title="blogDetail.title">
             <b-media no-body>
               <b-media-aside vertical-align="center" class="mr-50">
-                <b-avatar href="javascript:void(0)" size="24" :src="getUserAvatar(blogDetail.blog.userId)" />
+                <b-avatar href="javascript:void(0)" size="24" :src="getUserAvatar(blogDetail.authorId)" />
               </b-media-aside>
               <b-media-body>
                 <small class="text-muted mr-50">by</small>
                 <small>
-                  <b-link class="text-body">{{ blogDetail.blog.userFullName }}</b-link>
+                  <b-link class="text-body">{{ getUserFullName(blogDetail.authorId) }}</b-link>
                 </small>
                 <span class="text-muted ml-75 mr-50">|</span>
-                <small class="text-muted">{{ dateFormat(blogDetail.blog.createdTime) }}</small>
+                <small class="text-muted">{{ dateFormat(blogDetail.updated_at) }}</small>
               </b-media-body>
             </b-media>
             <div class="my-1 py-25">
-              <b-link v-for="tag in blogDetail.blog.tags" :key="tag">
+              <b-link v-for="tag in blogDetail.tags" :key="tag">
                 <b-badge pill class="mr-75" :variant="tagsColor(tag)">
                   {{ tag }}
                 </b-badge>
               </b-link>
             </div>
             <!-- eslint-disable vue/no-v-html -->
-            <div class="blog-content" v-html="blogDetail.blog.content" />
+            <div class="blog-content" v-html="blogDetail.content" />
 
             <!-- user commnets -->
-            <b-media v-for="user in blogDetail.blog.UserComment" :key="user.avatar" no-body>
+            <b-media v-for="user in blogDetail.UserComment" :key="user.avatar" no-body>
               <b-media-aside>
                 <b-avatar size="60" :src="user.avatar" />
               </b-media-aside>
@@ -56,7 +55,7 @@
                   </b-link>
                   <b-link>
                     <div class="text-body">
-                      {{ blogDetail.blog.comments ? kFormatter(blogDetail.blog.comments) : 0 }}
+                      {{ blogComments.length }}
                     </div>
                   </b-link>
                 </div>
@@ -66,7 +65,7 @@
                   </b-link>
                   <b-link>
                     <div class="text-body">
-                      {{ kFormatter(blogDetail.blog.bookmarked) }}
+                      {{ kFormatter(blogDetail.bookmarked) }}
                     </div>
                   </b-link>
                 </div>
@@ -94,18 +93,18 @@
           <h6 class="section-label">
             Comment
           </h6>
-          <b-card v-for="(comment, index) in blogDetail.comments" :key="index">
+          <b-card v-for="(comment, index) in blogComments" :key="index">
             <b-media no-body>
               <b-media-aside class="mr-75">
-                <b-avatar :src="getUserAvatar(comment.userId)" size="38" />
+                <b-avatar :src="getUserAvatar(comment.authorId)" size="38" />
               </b-media-aside>
               <b-media-body>
                 <h6 class="font-weight-bolder mb-25">
-                  {{ comment.userFullName }}
+                  {{ getUserFullName(comment.authorId) }}
                 </h6>
-                <b-card-text>{{ dateFormat(comment.commentedAt) }}</b-card-text>
+                <b-card-text>{{ dateFormat(comment.updated_at) }}</b-card-text>
                 <b-card-text>
-                  {{ comment.commentText }}
+                  {{ comment.comment }}
                 </b-card-text>
                 <b-link>
                   <div class="d-inline-flex align-items-center">
@@ -129,7 +128,7 @@
               <b-row>
                 <b-col cols="12">
                   <b-form-group class="mb-2">
-                    <b-form-textarea id="comment-text" name="textarea" rows="4" placeholder="請輸入內容" />
+                    <b-form-textarea id="comment-text" v-model="commentText" name="textarea" rows="4" placeholder="請輸入內容" />
                   </b-form-group>
                 </b-col>
                 <b-col cols="12">
@@ -173,20 +172,19 @@
         <b-media v-for="(recentpost, index) in blogSidebar.recentPosts" :key="index" no-body
           :class="index ? 'mt-2' : ''">
           <b-media-aside class="mr-2">
-            <b-link :to="{ name: 'blog-detail', params: { id: recentpost.id } }" @click="pageReload">
-              <b-img :src="getImg(recentpost.path)" :alt="getImg(recentpost.path).slice(6)" width="100" rounded
+            <b-link :to="{ name: 'blog-detail', params: { id: recentpost.id } }">
+              <b-img :src="getBannerImg(recentpost.id)" :alt="getBannerImg(recentpost.id).slice(6)" width="100" rounded
                 height="70" />
             </b-link>
           </b-media-aside>
           <b-media-body>
             <h6 class="blog-recent-post-title">
-              <b-link :to="{ name: 'blog-detail', params: { id: recentpost.id } }" class="text-body-heading"
-                @click="pageReload">
+              <b-link :to="{ name: 'blog-detail', params: { id: recentpost.id } }" class="text-body-heading">
                 {{ recentpost.title }}
               </b-link>
             </h6>
             <span class="text-muted mb-0">
-              {{ dateFormat(recentpost.createdTime) }}
+              {{ dateFormat(recentpost.updated_at) }}
             </span>
           </b-media-body>
         </b-media>
@@ -284,19 +282,38 @@ export default {
       search_query: '',
       commentCheckmark: '',
       blogDetail: {},
+      blogComments: [],
       blogSidebar: {},
+      commentCount: [],
+      commentText: '',
       socialShareIcons: ['GithubIcon', 'GitlabIcon', 'FacebookIcon', 'TwitterIcon', 'LinkedinIcon'],
       userData: getUserData(),
     }
   },
   created() {
-    useJwt.getPost('/api/get_blog/detail', { blogId: this.blogId }).then(res => {
-      this.blogDetail = res.data
-    })
+    useJwt.getPost('/api/user/index').then(res => {
+      this.userList = res.data;
+    });
 
-    useJwt.getPost('/api/get_blog/sidebar').then(res => {
-      this.blogSidebar = res.data
-    })
+    useJwt.getPost('/api/blog-image/index').then(res => {
+      this.blogImageList = res.data;
+    });
+
+    useJwt.getPost('/api/blog/show', { blogId: this.blogId }).then(res => {
+      this.blogDetail = res.data;
+    });
+
+    useJwt.getPost('/api/blog/sidebar').then(res => {
+      this.blogSidebar = res.data;
+    });
+
+    useJwt.getPost('/api/comment/index-by-blog', { blogId: this.blogId }).then(res => {
+      this.blogComments = res.data;
+    });
+
+    useJwt.getPost('/api/comment/index-count', { blogId: this.blogId }).then(res => {
+      this.commentCount = res.data;
+    });
 
     setTimeout(() => {
       if (this.$route.hash == '#blogComment') {
@@ -305,6 +322,13 @@ export default {
       }
     }, 500);
   },
+  watch: {
+    $route(to, from) {
+      useJwt.getPost('/api/blog/detail', { blogId: this.$route.params.id }).then(res => {
+        this.blogDetail = res.data
+      })
+    }
+  },
   methods: {
     kFormatter,
     tagsColor(tag) {
@@ -316,37 +340,59 @@ export default {
       return 'light-primary'
     },
     dateFormat(date) {
-      return format(new Date(date), 'yyyy-MM-dd hh:mm', { locale: zhTW })
+      return format(new Date(date), 'yyyy-MM-dd hh:mm', { locale: zhTW });
     },
     getUserAvatar(userId) {
-      return require('@/assets/images/avatars/' + userId + '-small.png')
+      return require('@/assets/images/avatars/' + userId + '-small.png');
     },
-    getImg(imagePath) {
-      return require('@/assets/images/' + imagePath)
+    getUserFullName(userId) {
+      for (var i = 0; i < this.userList.length; i++) {
+        if (this.userList[i].id == userId) {
+          return this.userList[i].name;
+        }
+      }
+      return 'none';
+    },
+    getBannerImg(blogId) {
+      var imagePath;
+      for (var i = 0; i < this.blogImageList.length; i++) {
+        if (this.blogImageList[i].blogId == blogId) {
+          imagePath = this.blogImageList[i].saveName;
+        }
+      }
+      return require('@/assets/images/banner/' + imagePath);
+    },
+    getCommentCount(blogId) {
+      for (var i = 0; i < this.commentCount.length; i++) {
+        if (this.commentCount[i].blogId == blogId) {
+          return this.commentCount[i].total;
+        }
+      }
+      return 0;
+    },
+    getCommentRank() {
+      var rankingList = [];
+      for (var i = 0; i < 4; i++) {
+        rankingList.push(this.commentCount[i].blogId);
+      }
+      return rankingList;
     },
     postComment() {
-      useJwt.getPost('/api/comment/post', {
-        comment: document.getElementById("comment-text").value,
+      useJwt.getPost('/api/comment/store', {
+        comment: this.commentText,
         blogId: this.$route.params.id,
       })
         .then(res => {
-          this.blogDetail.comments.push({
+          this.blogComments.push({
             userId: this.userData.id,
             userFullName: this.userData.name,
-            commentedAt: new Date(),
-            commentText: document.getElementById("comment-text").value,
+            commented_at: new Date(),
+            commentText: this.commentText,
           })
-          document.getElementById("comment-text").value = ''
+          this.commentText = ''
         })
     },
-    goDetail(id) {
-      this.$router.push({ name: 'blog-detail', params: { id: id } })
-      this.$router.go()
-    },
-    pageReload() {
-      this.$router.go()
-    },
-  },
+  }
 }
 </script>
 

+ 67 - 12
resources/js/src/views/blog/BlogEdit.vue

@@ -3,13 +3,13 @@
     <!-- media -->
     <b-media no-body vertical-align="center">
       <b-media-aside class="mr-75">
-        <b-avatar size="38" :src="getUserAvatar(blogEdit.userId)" />
+        <b-avatar size="38" :src="getUserAvatar(blogEdit.authorId)" />
       </b-media-aside>
       <b-media-body>
         <h6 class="mb-25">
-          {{ blogEdit.userFullName }}
+          {{ getUserFullName(blogEdit.authorId) }}
         </h6>
-        <b-card-text>{{ dateFormat(blogEdit.createdTime) }}</b-card-text>
+        <b-card-text>{{ dateFormat(blogEdit.updated_at) }}</b-card-text>
       </b-media-body>
     </b-media>
     <!--/ media -->
@@ -19,18 +19,18 @@
       <b-row>
         <b-col md="6">
           <b-form-group label="Title" label-for="blog-edit-title" class="mb-2">
-            <b-form-input id="blog-edit-title" v-model="blogEdit.blogTitle" />
+            <b-form-input id="blog-edit-title" v-model="blogEdit.title" />
           </b-form-group>
         </b-col>
         <b-col md="6">
           <b-form-group label="Category" label-for="blog-edit-category" class="mb-2">
-            <v-select id="blog-edit-category" v-model="blogEdit.blogCategories"
+            <v-select id="blog-edit-category" v-model="blogEdit.tags"
               :dir="$store.state.appConfig.isRTL ? 'rtl' : 'ltr'" multiple :options="categoryOption" />
           </b-form-group>
         </b-col>
         <b-col cols="12">
           <b-form-group label="Content" label-for="blog-content" class="mb-2">
-            <quill-editor id="blog-content" v-model="blogEdit.excerpt" :options="snowOption" />
+            <quill-editor id="blog-content" v-model="blogEdit.content" :options="snowOption" />
           </b-form-group>
         </b-col>
         <b-col cols="12" class="mb-2">
@@ -40,15 +40,15 @@
             </h4>
             <b-media no-body vertical-align="center" class="flex-column flex-md-row">
               <b-media-aside>
-                <b-img ref="refPreviewEl" :src="blogEdit.featuredImage" height="110" width="170"
+                <b-img ref="refPreviewEl" :src="getBannerImg(blogEdit.id)" height="110" width="170"
                   class="rounded mr-2 mb-1 mb-md-0" />
               </b-media-aside>
               <b-media-body>
                 <small class="text-muted">Required image resolution 800x400, image size 10mb.</small>
                 <b-card-text class="my-50">
-                  <b-link id="blog-image-text">
+                  <!-- <b-link id="blog-image-text">
                     C:\fakepath\{{ blogFile ? blogFile.name : 'banner.jpg' }}
-                  </b-link>
+                  </b-link> -->
                 </b-card-text>
                 <div class="d-inline-block">
                   <b-form-file ref="refInputEl" v-model="blogFile" accept=".jpg, .png, .gif" placeholder="Choose file"
@@ -139,9 +139,17 @@ export default {
     }
   },
   created() {
-    useJwt.getPost('/api/get_blog/edit', { blogId: this.blogId }).then(res => {
-      this.blogEdit = res.data
-    })
+    useJwt.getPost('/api/user/index').then(res => {
+      this.userList = res.data;
+    });
+
+    useJwt.getPost('/api/blog-image/index').then(res => {
+      this.blogImageList = res.data;
+    });
+
+    useJwt.getPost('/api/blog/show', { blogId: this.blogId }).then(res => {
+      this.blogEdit = res.data;
+    });
   },
   setup() {
     const refInputEl = ref(null)
@@ -149,6 +157,7 @@ export default {
 
     const { inputImageRenderer } = useInputImageRenderer(refInputEl, base64 => {
       refPreviewEl.value.src = base64
+      
     })
 
     return {
@@ -164,8 +173,54 @@ export default {
     getUserAvatar(userId) {
       return require('@/assets/images/avatars/' + userId + '-small.png')
     },
+    getUserFullName(userId) {
+      for (var i = 0; i < this.userList.length; i++) {
+        if (this.userList[i].id == userId) {
+          return this.userList[i].name;
+        }
+      }
+      return 'none';
+    },
+    getBannerImg(blogId) {
+      var imagePath;
+      for (var i = 0; i < this.blogImageList.length; i++) {
+        if (this.blogImageList[i].blogId == blogId) {
+          imagePath = this.blogImageList[i].saveName;
+        }
+      }
+      return require('@/assets/images/banner/' + imagePath);
+    },
+    getBase64(file) {
+      return new Promise(function (resolve, reject) {
+        var reader = new FileReader();
+        reader.onload = function () { resolve(reader.result); };
+        reader.onerror = reject;
+        reader.readAsDataURL(file);
+      });
+    },
     saveChanges() {
+      var imageSaveName = Date.now();
+
+      console.log(this.$refs.refPreviewEl.src)
+
+      console.log(this.blogId)
+      console.log(this.blogEdit.blogTitle)
       console.log(this.blogEdit.excerpt)
+
+      // useJwt.getPost('/api/blog/after_edit', {
+      //   blogId: this.blogId,
+      //   blogTitle: this.blogEdit.blogTitle,
+      //   blogContent: this.blogEdit.excerpt,
+      //   blogTags: this.blogEdit.blogCategories,
+      //   blogImage: this.blogFile.name,
+      //   saveName: imageSaveName,
+      // });
+
+      // // save image to /app/blog/banner
+      // var promise = this.getBase64(this.blogFile);
+      // promise.then(function (result) {
+      //   useJwt.getPost('/api/blog/save_banner', { blogImageFile: result, saveName: imageSaveName});
+      // });
     }
   },
 }

+ 73 - 29
resources/js/src/views/blog/BlogList.vue

@@ -7,7 +7,7 @@
         <b-col v-for="(blog, index) in blogList.slice(0, Math.ceil(blogList.length / 2))" :key="index" md="12">
           <b-card tag="article" no-body>
             <b-link :to="{ name: 'blog-detail', params: { id: blog.id } }">
-              <b-img :src="getImg(blog.path)" :alt="getImg(blog.path).slice(5)" class="card-img-top" />
+              <b-img :src="getBannerImg(blog.id)" :alt="getBannerImg(blog.id).slice(5)" class="card-img-top" />
             </b-link>
             <b-card-body>
               <b-card-title>
@@ -18,15 +18,15 @@
               </b-card-title>
               <b-media no-body>
                 <b-media-aside vertical-align="center" class="mr-50">
-                  <b-avatar href="javascript:void(0)" size="24" :src="getUserAvatar(blog.userId)" />
+                  <b-avatar href="javascript:void(0)" size="24" :src="getUserAvatar(blog.authorId)" />
                 </b-media-aside>
                 <b-media-body>
                   <small class="text-muted mr-50">by</small>
                   <small>
-                    <b-link class="text-body">{{ blog.userFullName }}</b-link>
+                    <b-link class="text-body">{{ getUserFullName(blog.authorId) }}</b-link>
                   </small>
                   <span class="text-muted ml-75 mr-50">|</span>
-                  <small class="text-muted">{{ dateFormat(blog.blogPosted) }}</small>
+                  <small class="text-muted">{{ dateFormat(blog.updated_at) }}</small>
                 </b-media-body>
               </b-media>
               <div class="my-1 py-25">
@@ -37,14 +37,14 @@
                 </b-link>
               </div>
               <b-card-text class="blog-content-truncate">
-                {{ blog.excerpt }}
+                {{ blog.content }}
               </b-card-text>
               <hr>
               <div class="d-flex justify-content-between align-items-center">
                 <b-link :to="{ path: `/blog/${blog.id}#blogComment` }">
                   <div class="d-flex align-items-center text-body">
                     <feather-icon icon="MessageSquareIcon" class="mr-50" />
-                    <span class="font-weight-bold">{{ blog.comment ? kFormatter(blog.comment) : 0 }} Comments</span>
+                    <span class="font-weight-bold">{{ getCommentCount(blog.id) }} Comments</span>
                   </div>
                 </b-link>
                 <b-link :to="{ name: 'blog-detail', params: { id: blog.id } }" class="font-weight-bold">
@@ -59,7 +59,7 @@
         <b-col v-for="(blog, index) in blogList.slice(Math.ceil(blogList.length / 2))" :key="index" md="12">
           <b-card tag="article" no-body>
             <b-link :to="{ name: 'blog-detail', params: { id: blog.id } }">
-              <b-img :src="getImg(blog.path)" :alt="getImg(blog.path).slice(5)" class="card-img-top" />
+              <b-img :src="getBannerImg(blog.id)" :alt="getBannerImg(blog.id).slice(5)" class="card-img-top" />
             </b-link>
             <b-card-body>
               <b-card-title>
@@ -70,15 +70,15 @@
               </b-card-title>
               <b-media no-body>
                 <b-media-aside vertical-align="center" class="mr-50">
-                  <b-avatar href="javascript:void(0)" size="24" :src="getUserAvatar(blog.userId)" />
+                  <b-avatar href="javascript:void(0)" size="24" :src="getUserAvatar(blog.authorId)" />
                 </b-media-aside>
                 <b-media-body>
                   <small class="text-muted mr-50">by</small>
                   <small>
-                    <b-link class="text-body">{{ blog.userFullName }}</b-link>
+                    <b-link class="text-body">{{ getUserFullName(blog.authorId) }}</b-link>
                   </small>
                   <span class="text-muted ml-75 mr-50">|</span>
-                  <small class="text-muted">{{ dateFormat(blog.blogPosted) }}</small>
+                  <small class="text-muted">{{ dateFormat(blog.updated_at) }}</small>
                 </b-media-body>
               </b-media>
               <div class="my-1 py-25">
@@ -89,14 +89,14 @@
                 </b-link>
               </div>
               <b-card-text class="blog-content-truncate">
-                {{ blog.excerpt }}
+                {{ blog.content }}
               </b-card-text>
               <hr>
               <div class="d-flex justify-content-between align-items-center">
                 <b-link :to="{ path: `/blog/${blog.id}#blogComment` }">
                   <div class="d-flex align-items-center text-body">
                     <feather-icon icon="MessageSquareIcon" class="mr-50" />
-                    <span class="font-weight-bold">{{ blog.comment ? kFormatter(blog.comment) : 0 }} Comments</span>
+                    <span class="font-weight-bold">{{ getCommentCount(blog.id) }} Comments</span>
                   </div>
                 </b-link>
                 <b-link :to="{ name: 'blog-detail', params: { id: blog.id } }" class="font-weight-bold">
@@ -147,7 +147,7 @@
           :class="index ? 'mt-2' : ''">
           <b-media-aside class="mr-2">
             <b-link :to="{ name: 'blog-detail', params: { id: recentpost.id } }">
-              <b-img :src="getImg(recentpost.path)" :alt="getImg(recentpost.path).slice(6)" width="100" rounded
+              <b-img :src="getBannerImg(recentpost.id)" :alt="getBannerImg(recentpost.id).slice(6)" width="100" rounded
                 height="70" />
             </b-link>
           </b-media-aside>
@@ -158,7 +158,7 @@
               </b-link>
             </h6>
             <span class="text-muted mb-0">
-              {{ dateFormat(recentpost.createdTime) }}
+              {{ dateFormat(recentpost.updated_at) }}
             </span>
           </b-media-body>
         </b-media>
@@ -243,7 +243,10 @@ export default {
   data() {
     return {
       search_query: '',
+      userList: [],
+      blogImageList: [],
       blogList: [],
+      commentCount: [],
       blogSidebar: {},
       currentPage: 1,
       perPage: 4,
@@ -251,17 +254,29 @@ export default {
     }
   },
   created() {
-    useJwt.getPost('/api/get_blog/list/total').then(res => {
-      this.rows = res.data
-    })
+    useJwt.getPost('/api/blog/total-count').then(res => {
+      this.rows = res.data;
+    });
 
-    useJwt.getPost('/api/get_blog/list/perpage', { offset: 0, rows: this.perPage }).then(res => {
-      this.blogList = res.data
-    })
+    useJwt.getPost('/api/user/index').then(res => {
+      this.userList = res.data;
+    });
 
-    useJwt.getPost('/api/get_blog/sidebar').then(res => {
-      this.blogSidebar = res.data
-    })
+    useJwt.getPost('/api/comment/index-count').then(res => {
+      this.commentCount = res.data;
+    });
+
+    useJwt.getPost('/api/blog-image/index').then(res => {
+      this.blogImageList = res.data;
+    });
+
+    useJwt.getPost('/api/blog/index-page', { offset: 0, rows: this.perPage }).then(res => {
+      this.blogList = res.data;
+    });
+
+    useJwt.getPost('/api/blog/sidebar').then(res => {
+      this.blogSidebar = res.data;
+    });
   },
   methods: {
     kFormatter,
@@ -274,17 +289,46 @@ export default {
       return 'light-primary'
     },
     dateFormat(date) {
-      return format(new Date(date), 'yyyy-MM-dd hh:mm', { locale: zhTW })
+      return format(new Date(date), 'yyyy-MM-dd hh:mm', { locale: zhTW });
     },
     getUserAvatar(userId) {
-      return require('@/assets/images/avatars/' + userId + '-small.png')
+      return require('@/assets/images/avatars/' + userId + '-small.png');
+    },
+    getUserFullName(userId) {
+      for (var i = 0; i < this.userList.length; i++) {
+        if (this.userList[i].id == userId) {
+          return this.userList[i].name;
+        }
+      }
+      return 'none';
+    },
+    getBannerImg(blogId) {
+      var imagePath;
+      for (var i = 0; i < this.blogImageList.length; i++) {
+        if (this.blogImageList[i].blogId == blogId) {
+          imagePath = this.blogImageList[i].saveName;
+        }
+      }
+      return require('@/assets/images/banner/' + imagePath);
+    },
+    getCommentCount(blogId) {
+      for (var i = 0; i < this.commentCount.length; i++) {
+        if (this.commentCount[i].blogId == blogId) {
+          return this.commentCount[i].total;
+        }
+      }
+      return 0;
     },
-    getImg(imagePath) {
-      return require('@/assets/images/' + imagePath)
+    getCommentRank() {
+      var rankingList = [];
+      for (var i = 0; i < 4; i++) {
+        rankingList.push(this.commentCount[i].blogId);
+      }
+      return rankingList;
     },
     getBlogListPerpage() {
-      useJwt.getPost('/api/get_blog/list/perpage', { offset: ((this.currentPage - 1) * this.perPage), rows: this.perPage }).then(res => {
-        this.blogList = res.data
+      useJwt.getPost('/api/blog/index-page', { offset: ((this.currentPage - 1) * this.perPage), rows: this.perPage }).then(res => {
+        this.blogList = res.data;
       })
     },
   },

+ 48 - 161
routes/api.php

@@ -5,6 +5,8 @@ use Illuminate\Support\Facades\Route;
 use Illuminate\Support\Facades\Hash;
 use Illuminate\Validation\ValidationException;
 use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\File;
+use Illuminate\Support\Facades\Storage;
 
 use App\Models\User;
 use App\Models\Message;
@@ -12,6 +14,11 @@ use App\Models\Blog;
 use App\Models\Comment;
 use App\Models\BlogImage;
 
+use App\Http\Controllers\UserController;
+use App\Http\Controllers\BlogController;
+use App\Http\Controllers\BlogImageController;
+use App\Http\Controllers\CommentController;
+
 /*
 |--------------------------------------------------------------------------
 | API Routes
@@ -53,136 +60,45 @@ Route::middleware('auth:sanctum')->post('/logout', function (Request $request) {
     return $user;
 });
 
-Route::middleware('auth:sanctum')->post('/comment/post', function (Request $request) {
-    $request->validate([
-        'comment' => 'required',
-        'blogId' => 'required',
-    ]);
-
-    Comment::insert([
-        'writer' => $request->user()->id,
-        'comment' => $request->comment,
-        'blogId' => $request->blogId,
-        'created_at' => now(),
-        'updated_at' => now(),
-    ]);
-
-    return 'success';
-});
-
-Route::middleware('auth:sanctum')->post('/comment/delete', function (Request $request) {
-    $request->validate([
-        'commentID' => 'required',
-    ]);
-
-    Comment::where('id', '=', $request->commentID)->delete();
-
-    return 'success';
-});
-
-Route::middleware('auth:sanctum')->post('/get_blog/list', function (Request $request) {
-    $blogList = DB::select("SELECT 
-            blogs.id, 
-            title, 
-            content AS excerpt, 
-            tags, 
-            users.id AS userId, 
-            users.name AS userFullName, 
-            blogs.created_at AS blogPosted, 
-            t.total AS comment,
-            path
-        FROM [laravel_kevin].[dbo].[blogs]
-        LEFT JOIN [dbo].[users] ON [blogs].[writer] = [users].[id]
-        LEFT JOIN (
-            SELECT [blogId],COUNT(*) AS total
-            FROM [laravel_kevin].[dbo].[comments]
-            GROUP BY [blogId]) as t ON [blogs].[id] = [t].[blogId]
-        LEFT JOIN [dbo].[blog_images] ON [blogs].[id] = [blog_images].[blogId]
-        ORDER BY blogs.id DESC");
-    foreach($blogList as $blog) {
-        $blog->tags = json_decode($blog->tags);
-    }
-
-    return $blogList;
-});
-
-Route::middleware('auth:sanctum')->post('/get_blog/list/perpage', function (Request $request) {
-    $request->validate([
-        'offset' => 'required',
-        'rows' => 'required',
-    ]);
-    $blogList = DB::select("SELECT 
-            blogs.id, 
-            title, 
-            content AS excerpt, 
-            tags, 
-            users.id AS userId, 
-            users.name AS userFullName, 
-            blogs.created_at AS blogPosted, 
-            t.total AS comment,
-            path
-        FROM [laravel_kevin].[dbo].[blogs]
-        LEFT JOIN [dbo].[users] ON [blogs].[writer] = [users].[id]
-        LEFT JOIN (
-            SELECT [blogId],COUNT(*) AS total
-            FROM [laravel_kevin].[dbo].[comments]
-            GROUP BY [blogId]) as t ON [blogs].[id] = [t].[blogId]
-        LEFT JOIN [dbo].[blog_images] ON [blogs].[id] = [blog_images].[blogId]
-        ORDER BY blogs.id DESC
-        OFFSET " . $request->offset . " ROW
-        FETCH NEXT " . $request->rows . " ROWS ONLY");
-    foreach($blogList as $blog) {
-        $blog->tags = json_decode($blog->tags);
-    }
-
-    return $blogList;
+Route::middleware('auth:sanctum')->group(function () {
+    //users controller
+    Route::post('/user/index', [UserController::class, 'index']);
+    Route::post('/user/show', [UserController::class, 'show']);
+    Route::post('/user/destroy', [UserController::class, 'destroy']);
+
+    //blogs controller
+    Route::post('/blog/index', [BlogController::class, 'index']);
+    Route::post('/blog/index-page', [BlogController::class, 'index_page']);
+    Route::post('/blog/sidebar', [BlogController::class, 'sidebar']);
+    Route::post('/blog/total-count', [BlogController::class, 'total_count']);
+    Route::post('/blog/show', [BlogController::class, 'show']);
+    Route::post('/blog/store', [BlogController::class, 'store']);
+    Route::post('/blog/edit', [BlogController::class, 'edit']);
+    Route::post('/blog/destroy', [BlogController::class, 'destroy']);
+
+    //blogs image controller
+    Route::post('/blog-image/index', [BlogImageController::class, 'index']);
+    Route::post('/blog-image/show', [BlogImageController::class, 'show']);
+    Route::post('/blog-image/store', [BlogImageController::class, 'store']);
+
+    //comments controller
+    Route::post('/comment/index-by-blog', [CommentController::class, 'index_by_blog']);
+    Route::post('/comment/index-count', [CommentController::class, 'index_count']);
+    Route::post('/comment/show', [CommentController::class, 'show']);
+    Route::post('/comment/store', [CommentController::class, 'store']);
+    Route::post('/comment/destroy', [CommentController::class, 'destroy']);
 });
 
-Route::middleware('auth:sanctum')->post('/get_blog/list/total', function (Request $request) {
-    $blogList = DB::select("SELECT COUNT(*) AS total
-        FROM [laravel_kevin].[dbo].[blogs]");
 
-    return $blogList[0]->total;
-});
-
-Route::middleware('auth:sanctum')->post('/get_blog/detail', function (Request $request) {
-    $request->validate([
-        'blogId' => 'required',
-    ]);
-    $blog = DB::select("SELECT 
-            title, 
-            content, 
-            tags, 
-            users.id AS userId, 
-            users.name AS userFullName, 
-            blogs.created_at AS createdTime, 
-            bookmarked, 
-            t.total AS comments,
-            path
-        FROM [laravel_kevin].[dbo].[blogs]
-        LEFT JOIN [dbo].[users] ON [blogs].[writer] = [users].[id]
-        LEFT JOIN (
-            SELECT [blogId],COUNT(*) AS total
-            FROM [laravel_kevin].[dbo].[comments]
-            GROUP BY [blogId]) as t ON [blogs].[id] = [t].[blogId]
-        LEFT JOIN [dbo].[blog_images] ON [blogs].[id] = [blog_images].[blogId]
-        WHERE blogs.id=" . $request->blogId);
-    $blog[0]->tags = json_decode($blog[0]->tags);
-
-    $comments = DB::select("SELECT comment AS commentText, comments.created_at AS commentedAt, users.id AS userId, users.name AS userFullName
-        FROM [laravel_kevin].[dbo].[comments]
-        RIGHT JOIN [dbo].[users] ON [comments].[writer] = [users].[id]
-        WHERE [blogId]=" . $request->blogId);
-    return ['blog' => $blog[0], 'comments' => $comments];
-});
+//todo count blog comment
 
-Route::middleware('auth:sanctum')->post('/get_blog/sidebar', function (Request $request) {
+Route::middleware('auth:sanctum')->post('/blog/sideba', function (Request $request) {
     $recentPosts = DB::select("SELECT TOP(4) 
             blogs.id, 
             title, 
-            blogs.created_at AS createdTime, 
+            blogs.updated_at AS updatedTime, 
             t.total AS comments, 
-            path
+            saveName
         FROM [laravel_kevin].[dbo].[blogs]
         LEFT JOIN [dbo].[users] ON [blogs].[writer] = [users].[id]
         LEFT JOIN (
@@ -203,49 +119,20 @@ Route::middleware('auth:sanctum')->post('/get_blog/sidebar', function (Request $
     return ['recentPosts' => $recentPosts, 'categories' => $categories];
 });
 
-Route::middleware('auth:sanctum')->post('/get_blog/edit', function (Request $request) {
+Route::post('/blog-image/fake', function (Request $request) {
     $request->validate([
         'blogId' => 'required',
     ]);
-    $data = DB::select("SELECT 
-            title AS blogTitle,
-            content AS excerpt,
-            tags AS blogCategories,
-            users.id AS userId,
-            users.name AS userFullName,
-            blogs.created_at AS createdTime
-        FROM [laravel_kevin].[dbo].[blogs]
-        RIGHT JOIN [dbo].[users] ON [blogs].[writer] = [users].[id]
-        WHERE blogs.id=" . $request->blogId);
-    $data[0]->blogCategories = json_decode($data[0]->blogCategories);
-
-    return $data[0];
-});
 
-Route::middleware('auth:sanctum')->post('/get_blog/image_insert', function (Request $request) {
-    $request->validate([
-        'blogId' => 'required',
-        'path' => 'required',
-        'name' => 'required',
-    ]);
-
-    BlogImage::insert([
-        'blogId' => $request->blogId,
-        'path' => $request->path,
-        'name' => $request->name,
-        'created_at' => now(),
-        'updated_at' => now(),
-    ]);
-
-    // for ( $i=$request->blogId ; $i<11 ; $i++ ) {
-    //     BlogImage::insert([
-    //         'blogId' => $i,
-    //         'path' => 'banner/banner-'.$i.'.jpg',
-    //         'name' => 'banner-'.$i,
-    //         'created_at' => now(),
-    //         'updated_at' => now(),
-    //     ]);
-    // }
+    for ( $i=$request->blogId ; $i<11 ; $i++ ) {
+        BlogImage::insert([
+            'blogId' => $i,
+            'saveName' => 'banner-'.$i.'.jpg',
+            'fileName' => 'banner-'.$i.'.jpg',
+            'created_at' => now(),
+            'updated_at' => now(),
+        ]);
+    }
 
     return 'success';
 });