manto07m 2 år sedan
förälder
incheckning
4e70e47ec0

+ 33 - 1
app/Http/Controllers/MessageController.php

@@ -113,6 +113,7 @@ class MessageController extends Controller
     public function edit(message $message)
     {
         //
+
     }
 
     /**
@@ -125,6 +126,34 @@ class MessageController extends Controller
     public function update(UpdatemessageRequest $request, message $message)
     {
         //
+        $preview = "";
+        if ($request->preview == "preview") {
+            $preview = str_replace("\n", "", $request->content);
+            $preview = str_replace(" ", "", $preview);
+            $preview = strip_tags($preview);
+            $preview = mb_substr($preview, 0, 55) . "...";
+        }
+        if (is_string($request->thumbnail)) {
+            $imageName = $request->thumbnail;
+        } else {
+            $imageName = time() . '.' . $request->thumbnail->extension();
+            $request->thumbnail->move(public_path('images'), $imageName);
+        }
+
+        $message = Message::where('id', $request->id)
+            ->where('author_id', $request->User()->id)
+            ->update([
+                'title' => $request->title,
+                'content' => $request->content,
+                'preview' => $preview,
+                'tag' => $request->tag,
+                'thumbnail' => $imageName,
+                'updated_at' => now(),
+            ]);
+        if ($message == 0) {
+            abort(403, '你沒有編輯此貼文的權限!');
+        }
+        return $message;
     }
 
     /**
@@ -133,9 +162,12 @@ class MessageController extends Controller
      * @param  \App\Models\message  $message
      * @return \Illuminate\Http\Response
      */
-    public function destroy(message $message)
+    public function destroy(Request $request, Message $message)
     {
         //
+        $message = Message::where('id', $request->id)->delete();
+
+        return $message;
     }
 
     public function count()

+ 3 - 1
app/Http/Requests/UpdatemessageRequest.php

@@ -13,7 +13,7 @@ class UpdatemessageRequest extends FormRequest
      */
     public function authorize()
     {
-        return false;
+        return true;
     }
 
     /**
@@ -25,6 +25,8 @@ class UpdatemessageRequest extends FormRequest
     {
         return [
             //
+            'title' => 'required',
+            'content' => 'required',
         ];
     }
 }

+ 20 - 2
resources/js/src/@core/auth/jwt/jwtService.js

@@ -47,7 +47,25 @@ export default class JwtService {
                     let failedRequest = error.config;
 
                     //Method to get new token
-                    error = "你沒有在" + failedRequest.url  + "使用" + failedRequest.method + "的權限! 如有問題請聯絡管理員"
+                    error = "401錯誤! \n你沒有在" + failedRequest.url + "使用" + failedRequest.method + "的權限! 如有問題請聯絡管理員"
+                } else if (error.request && error.request.status === 403) {
+                    // Set Failed Request
+                    let failedRequest = error.config;
+
+                    //Method to get new token
+                    error = "403錯誤! \n你沒有在" + failedRequest.url + "使用" + failedRequest.method + "的權限! 如有問題請聯絡管理員"
+                } else if (error.request && error.request.status === 422) {
+                    // Set Failed Request
+                    let failedRequest = error.config;
+
+                    //Method to get new token
+                    error = "422錯誤! 請檢查是否有未填寫的欄位!"
+                }else if (error.request && error.request.status === 500) {
+                    // Set Failed Request
+                    let failedRequest = error.config;
+
+                    //Method to get new token
+                    error = "500錯誤! 伺服器發生錯誤!"
                 }
                 throw error;
             },
@@ -103,5 +121,5 @@ export default class JwtService {
     getData(url, ...args) {
         return this.axiosIns.get(url, ...args)
     }
-    
+
 }

+ 0 - 1
resources/js/src/views/Login.vue

@@ -231,7 +231,6 @@ export default {
 						useJwt.setToken(response.data.token);
 						localStorage.setItem('userData', response.data.user);
 						this.$ability.update(defineRulesFor(response.data.user));
-						console.log(this.$route.query.redirect)
 						if (this.$route.query.redirect)
 							this.$router.push({ path: this.$route.query.redirect });
 						else

+ 5 - 5
resources/js/src/views/SecondPage.vue

@@ -25,8 +25,8 @@ export default {
   },
   data() {
     return {
-      tweenedNumber: 4000,
-      number: 4000,
+      tweenedNumber: 5800,
+      number: 5800,
     }
   },
   computed: {
@@ -38,9 +38,9 @@ export default {
     countDown(){
       this.number = 0;
     },
-    reset(){
-      this.number = 4000;
-    }
+    reset(){ 
+      this.number = 5800;
+    }  
   },
   watch: {
     number: function (newValue) {

+ 68 - 15
resources/js/src/views/pages/blog/BlogEdit.vue

@@ -14,9 +14,9 @@
       </b-media-aside>
       <b-media-body>
         <h6 class="mb-25">
-          {{ blogEdit.userFullName }}
+          {{ userData.name }}
         </h6>
-        <b-card-text>{{ blogEdit.createdTime }}</b-card-text>
+        <b-card-text>{{ formatTime(blogEdit.created_at) }}</b-card-text>
       </b-media-body>
     </b-media>
     <!--/ media -->
@@ -31,7 +31,7 @@
             class="mb-2">
             <b-form-input
               id="blog-edit-title"
-              v-model="blogEdit.blogTitle" />
+              v-model="blogEdit.title" />
           </b-form-group>
         </b-col>
         <b-col md="6">
@@ -41,7 +41,7 @@
             class="mb-2">
             <v-select
               id="blog-edit-category"
-              v-model="blogEdit.blogCategories"
+              v-model="blogEdit.category"
               :dir="$store.state.appConfig.isRTL ? 'rtl' : 'ltr'"
               multiple
               :options="categoryOption" />
@@ -54,7 +54,7 @@
             class="mb-2">
             <quill-editor
               id="blog-content"
-              v-model="blogEdit.excerpt"
+              v-model="blogEdit.content"
               :options="snowOption" />
           </b-form-group>
         </b-col>
@@ -72,16 +72,16 @@
               <b-media-aside>
                 <b-img
                   ref="refPreviewEl"
-                  :src="blogEdit.featuredImage"
+                  :src="formatImage(blogEdit.thumbnail)"
                   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>
+                <small class="text-muted">圖片建議尺寸為 800x400,容量上限為 10MB</small>
                 <b-card-text class="my-50">
                   <b-link id="blog-image-text">
-                    C:\fakepath\{{ blogFile ? blogFile.name : 'banner.jpg' }}
+                    {{ blogEdit.thumbnail }}
                   </b-link>
                 </b-card-text>
                 <div class="d-inline-block">
@@ -89,7 +89,7 @@
                     ref="refInputEl"
                     v-model="blogFile"
                     accept=".jpg, .png, .gif"
-                    placeholder="Choose file"
+                    placeholder="選擇圖片"
                     @input="inputImageRenderer" />
                 </div>
               </b-media-body>
@@ -102,8 +102,9 @@
           <b-button
             v-ripple.400="'rgba(255, 255, 255, 0.15)'"
             variant="primary"
-            class="mr-1">
-            發布貼文
+            class="mr-1"
+            @click="editComment()">
+            變更貼文
           </b-button>
           <b-button
             v-ripple.400="'rgba(186, 191, 199, 0.15)'"
@@ -143,6 +144,8 @@ import { useInputImageRenderer } from '@core/comp-functions/forms/form-utils'
 import { ref } from '@vue/composition-api'
 import { getUserData } from '@/auth/utils'
 import moment from 'moment'
+import useJwt from '@/auth/jwt/useJwt'
+import ToastificationContent from "@core/components/toastification/ToastificationContent.vue";
 
 export default {
   components: {
@@ -172,7 +175,7 @@ export default {
       userData: getUserData(),
       blogEdit: {},
       blogFile: null,
-      categoryOption: ['Fashion', 'Food', 'Gaming', 'Quote', 'Video'],
+      categoryOption: ['台灣小吃', '美食', '熱炒店', '吃到飽'],
       statusOption: ['Published', 'Pending', 'Draft'],
       snowOption: {
         theme: 'snow',
@@ -180,9 +183,15 @@ export default {
     }
   },
   created() {
-    this.$http.get('/blog/list/data/edit').then(res => {
-      this.blogEdit = res.data
-    })
+    useJwt.postData('/api/message/detail', { 'id': this.$route.params.id }).then(response => {
+      this.blogEdit = response.data.blog;
+      this.blogEdit.category = response.data.blog.tag.split(',');
+      if(this.blogEdit.author_id != this.userData.id){
+        this.$router.push({ name: 'pages-blog-list' });
+      }
+    }).catch(error => {
+      console.log(error)
+    });
   },
   setup() {
     const refInputEl = ref(null)
@@ -198,6 +207,47 @@ export default {
       inputImageRenderer,
     }
   },
+  methods: {
+    formatTime(value) {
+      return moment(value).format("LLL");
+    },
+    formatTag(value) {
+      return value.split(",");
+    },
+    formatImage(value) {
+      return value.includes("http") ? value : "/images/" + value;
+    },
+    editComment() {
+      let formData = new FormData();
+      formData.append('id', this.$route.params.id);
+      formData.append('title', this.blogEdit.title);
+      formData.append('content', this.blogEdit.content);
+      formData.append('preview', "preview");
+      let tag = '';
+      if (this.blogEdit.category.length > 0) {
+        tag = this.blogEdit.category.join(',');
+      }
+      formData.append('tag', tag);
+      let thumbnail = this.blogFile == null ? this.blogEdit.thumbnail : this.blogFile;
+      formData.append('thumbnail', thumbnail);
+
+      useJwt.postData('/api/message/editMessage', formData).then(response => {
+        //this.$router.push({ name: 'pages-blog-list' });
+      }).catch(error => {
+        console.log(error)
+        this.$toast({
+          component: ToastificationContent,
+          props: {
+            title: `錯誤`,
+            icon: 'AlertTriangleIcon',
+            variant: 'warning',
+            text: error,
+          },
+        })
+      });
+
+    },
+  }
 }
 </script>
 
@@ -205,4 +255,7 @@ export default {
 @import '~@resources/scss/vue/libs/vue-select.scss';
 @import '~@resources/scss/vue/libs/quill.scss';
 @import '~@resources/scss/vue/pages/page-blog.scss';
+.custom-file-input:lang(en)~.custom-file-label::after {
+  content: '選擇檔案';
+}
 </style>

+ 20 - 3
resources/js/src/views/pages/blog/BlogList.vue

@@ -84,14 +84,22 @@
                   <feather-icon style="color: white;" icon="MoreVerticalIcon" />
                 </template>
 
-                <b-dropdown-item :to="{ name: 'pages-blog-edit', params: { id: blog.id } }">
+                <b-dropdown-item v-if="(blog.author_id == userData.id)"
+                  :to="{ name: 'pages-blog-edit', params: { id: blog.id } }">
                   <feather-icon
                     icon="EditIcon"
                     size="16" />
                   <span class="align-middle ml-50">編輯貼文</span>
                 </b-dropdown-item>
+                <b-dropdown-item v-else>
+                  <feather-icon
+                    icon="MinusCircleIcon"
+                    size="16" />
+                  <span class="align-middle ml-50">暫無功能</span>
+                </b-dropdown-item>
 
-                <b-dropdown-item href="#">
+                <b-dropdown-item v-if="$can('mange', $route.name) || (blog.author_id == userData.id)"
+                  @click="deleteData(blog.id)">
                   <feather-icon
                     icon="Trash2Icon"
                     size="16" />
@@ -247,6 +255,7 @@ import {
   BDropdownItem,
 } from 'bootstrap-vue'
 import { kFormatter } from '@core/utils/filter'
+import { getUserData } from '@/auth/utils'
 import ContentWithSidebar from '@core/layouts/components/content-with-sidebar/ContentWithSidebar.vue'
 import useJwt from '@/auth/jwt/useJwt'
 import moment from 'moment'
@@ -285,6 +294,7 @@ export default {
       perPage: 6,
       nameList: [],
       commentList: [],
+      userData: getUserData(),
     }
   },
   created() {
@@ -313,6 +323,14 @@ export default {
         console.log(error)
       });
     },
+    deleteData(id) {
+      useJwt.postData('/api/message/deleteMessage', { "id": id }).then(response => {
+        console.log(response.data)
+        this.getAllData();
+      }).catch(error => {
+        console.log(error)
+      });
+    },
     tagsColor(tag) {
       if (tag === '台灣小吃') return 'light-success'
       if (tag.includes('美食')) return 'light-info'
@@ -343,7 +361,6 @@ export default {
   computed: {
     blogLists() {
       const items = this.blogList;
-      // Return just page of items needed
       return items.slice(
         (this.currentPage - 1) * this.perPage,
         this.currentPage * this.perPage

+ 7 - 3
resources/js/src/views/pages/blog/BlogPost.vue

@@ -76,7 +76,7 @@
                   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>
+                <small class="text-muted">圖片建議尺寸為 800x400,容量上限為 10MB</small>
                 <b-card-text class="my-50">
                   <b-link id="blog-image-text">
                     \\{{ blogFile ? blogFile.name : '尚未上傳' }}
@@ -86,8 +86,8 @@
                   <b-form-file
                     ref="refInputEl"
                     v-model="blogFile"
-                    accept=".jpg, .png, .gif"
-                    placeholder="Choose file"
+                    accept=".jpg, .png, .gif, .jfif"
+                    placeholder="選擇圖片"
                     @input="inputImageRenderer" />
                 </div>
               </b-media-body>
@@ -142,6 +142,7 @@ import { ref } from '@vue/composition-api'
 import { getUserData } from '@/auth/utils'
 import moment from 'moment'
 import useJwt from '@/auth/jwt/useJwt'
+import ToastificationContent from "@core/components/toastification/ToastificationContent.vue";
 
 export default {
   components: {
@@ -235,4 +236,7 @@ export default {
 @import '~@resources/scss/vue/libs/vue-select.scss';
 @import '~@resources/scss/vue/libs/quill.scss';
 @import '~@resources/scss/vue/pages/page-blog.scss';
+.custom-file-input:lang(en)~.custom-file-label::after {
+  content: '選擇檔案';
+}
 </style>

+ 4 - 2
routes/api.php

@@ -90,9 +90,11 @@ Route::post('/message/count', [MessageController::class, 'count']);
 Route::post('/message/user', [UserController::class, 'index']);
 
 Route::middleware('auth:sanctum')->group(function () {
-    //
     Route::post('/message/storeComment', [MessageController::class, 'storeComment']);
     Route::post('/message/storeMessage', [MessageController::class, 'store']);
+    Route::post('/message/editMessage', [MessageController::class, 'update']);
 });
 
-
+Route::middleware(['auth:sanctum', 'abilities:Admin'])->group(function () {
+    Route::post('/message/deleteMessage', [MessageController::class, 'destroy']);
+});