| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- <template>
- <content-with-sidebar v-if="Object.keys(blogDetail).length" class="cws-container cws-sidebar-right blog-wrapper">
- <!-- content -->
- <div class="blog-detail-wrapper">
- <b-row>
- <!-- blogs -->
- <b-col cols="12">
- <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.authorId)" />
- </b-media-aside>
- <b-media-body>
- <small class="text-muted mr-50">by</small>
- <small>
- <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.updated_at) }}</small>
- </b-media-body>
- </b-media>
- <div class="my-1 py-25">
- <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.content" />
- <!-- user commnets -->
- <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>
- <b-media-body>
- <h6 class="font-weight-bolder">
- {{ user.fullName }}
- </h6>
- <b-card-text>
- {{ user.comment }}
- </b-card-text>
- </b-media-body>
- </b-media>
- <!-- eslint-enable -->
- <hr class="my-2">
- <div class="d-flex align-items-center justify-content-between" id="commentIcon">
- <div class="d-flex align-items-center">
- <div class="d-flex align-items-center mr-1">
- <b-link class="mr-50">
- <feather-icon icon="MessageSquareIcon" size="21" class="text-body" />
- </b-link>
- <b-link>
- <div class="text-body">
- {{ blogComments.length }}
- </div>
- </b-link>
- </div>
- <div class="d-flex align-items-center">
- <b-link class="mr-50">
- <feather-icon size="21" icon="BookmarkIcon" class="text-body" />
- </b-link>
- <b-link>
- <div class="text-body">
- {{ kFormatter(blogDetail.bookmarked) }}
- </div>
- </b-link>
- </div>
- </div>
- <!-- dropdown -->
- <div class="blog-detail-share">
- <b-dropdown variant="link" toggle-class="p-0" no-caret right>
- <template #button-content>
- <feather-icon size="21" icon="Share2Icon" class="text-body" />
- </template>
- <b-dropdown-item v-for="icon in socialShareIcons" :key="icon" href="#">
- <feather-icon :icon="icon" size="18" />
- </b-dropdown-item>
- </b-dropdown>
- </div>
- <!--/ dropdown -->
- </div>
- </b-card>
- </b-col>
- <!--/ blogs -->
- <!-- blog comment -->
- <b-col id="blogComment" cols="12" class="mt-2">
- <h6 class="section-label">
- Comment
- </h6>
- <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.authorId)" size="38" />
- </b-media-aside>
- <b-media-body>
- <h6 class="font-weight-bolder mb-25">
- {{ getUserFullName(comment.authorId) }}
- </h6>
- <b-card-text>{{ dateFormat(comment.updated_at) }}</b-card-text>
- <b-card-text>
- {{ comment.comment }}
- </b-card-text>
- <b-link>
- <div class="d-inline-flex align-items-center">
- <feather-icon icon="CornerUpLeftIcon" size="18" class="mr-50" />
- <span>Reply</span>
- </div>
- </b-link>
- </b-media-body>
- </b-media>
- </b-card>
- </b-col>
- <!--/ blog comment -->
- <!-- Leave a Blog Comment -->
- <b-col cols="12" class="mt-2">
- <h6 class="section-label">
- Leave a Comment
- </h6>
- <b-card>
- <b-form>
- <b-row>
- <b-col cols="12">
- <b-form-group class="mb-2">
- <b-form-textarea id="comment-text" v-model="commentText" name="textarea" rows="4" placeholder="請輸入內容" />
- </b-form-group>
- </b-col>
- <b-col cols="12">
- <!-- <b-form-checkbox id="checkbox-1" v-model="commentCheckmark" name="checkbox-1" class="mb-2">
- Save my name, email, and website in this browser for the next time I comment.
- </b-form-checkbox> -->
- </b-col>
- <b-col cols="12">
- <b-button v-ripple.400="'rgba(255, 255, 255, 0.15)'" variant="primary" @click="postComment">
- Post Comment
- </b-button>
- </b-col>
- </b-row>
- </b-form>
- </b-card>
- </b-col>
- <!--/ Leave a Blog Comment -->
- </b-row>
- <!--/ blogs -->
- </div>
- <!--/ content -->
- <!-- sidebar -->
- <div slot="sidebar" class="blog-sidebar py-2 py-lg-0">
- <!-- input search -->
- <b-form-group class="blog-search">
- <b-input-group class="input-group-merge">
- <b-form-input id="search-input" v-model="search_query" placeholder="Search here" />
- <b-input-group-append class="cursor-pointer" is-text>
- <feather-icon icon="SearchIcon" />
- </b-input-group-append>
- </b-input-group>
- </b-form-group>
- <!--/ input search -->
- <!-- recent posts -->
- <div class="blog-recent-posts mt-3">
- <h6 class="section-label mb-75">
- Recent Posts
- </h6>
- <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 } }">
- <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">
- {{ recentpost.title }}
- </b-link>
- </h6>
- <span class="text-muted mb-0">
- {{ dateFormat(recentpost.updated_at) }}
- </span>
- </b-media-body>
- </b-media>
- </div>
- <!--/ recent posts -->
- <!-- categories -->
- <div class="blog-categories mt-3">
- <h6 class="section-label mb-1">
- Categories
- </h6>
- <div v-for="category in blogSidebar.categories" :key="category.icon"
- class="d-flex justify-content-start align-items-center mb-75">
- <b-link>
- <b-avatar rounded size="32" :variant="tagsColor(category.category)" class="mr-75">
- <feather-icon :icon="category.icon" size="16" />
- </b-avatar>
- </b-link>
- <b-link>
- <div class="blog-category-title text-body">
- {{ category.category }}
- </div>
- </b-link>
- </div>
- </div>
- <!--/ categories -->
- </div>
- </content-with-sidebar>
- </template>
- <script>
- import {
- BFormInput,
- BMedia,
- BAvatar,
- BMediaAside,
- BMediaBody,
- BImg,
- BLink,
- BFormGroup,
- BInputGroup,
- BInputGroupAppend,
- BCard,
- BRow,
- BCol,
- BBadge,
- BCardText,
- BDropdown,
- BDropdownItem,
- BForm,
- BFormTextarea,
- BFormCheckbox,
- BButton,
- } from 'bootstrap-vue'
- import Ripple from 'vue-ripple-directive'
- import { kFormatter } from '@core/utils/filter'
- import ContentWithSidebar from '@core/layouts/components/content-with-sidebar/ContentWithSidebar.vue'
- import useJwt from '@/auth/jwt/useJwt'
- import { format } from 'date-fns'
- import { zhTW } from 'date-fns/locale'
- import { getUserData } from '@/auth/utils'
- export default {
- components: {
- BFormInput,
- BMedia,
- BAvatar,
- BMediaAside,
- BMediaBody,
- BLink,
- BCard,
- BRow,
- BCol,
- BFormGroup,
- BInputGroup,
- BInputGroupAppend,
- BImg,
- BBadge,
- BCardText,
- BDropdown,
- BForm,
- BDropdownItem,
- BFormTextarea,
- BFormCheckbox,
- BButton,
- ContentWithSidebar,
- },
- directives: {
- Ripple,
- },
- data() {
- return {
- blogId: this.$route.params.id,
- search_query: '',
- commentCheckmark: '',
- blogDetail: {},
- blogImageList: [],
- blogComments: [],
- blogSidebar: {},
- commentCount: [],
- commentText: '',
- socialShareIcons: ['GithubIcon', 'GitlabIcon', 'FacebookIcon', 'TwitterIcon', 'LinkedinIcon'],
- userData: getUserData(),
- }
- },
- created() {
- 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.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') {
- var el = document.getElementById('commentIcon');
- el.scrollIntoView({ behavior: "smooth" });
- }
- }, 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) {
- if (tag === 'Quote') return 'light-info'
- if (tag === 'Gaming') return 'light-danger'
- if (tag === 'Fashion') return 'light-primary'
- if (tag === 'Video') return 'light-warning'
- if (tag === 'Food') return 'light-success'
- return 'light-primary'
- },
- dateFormat(date) {
- return format(new Date(date), 'yyyy-MM-dd hh:mm', { locale: zhTW });
- },
- getUserAvatar(userId) {
- return ('/images/_/_/_/_/MessagePractise/resources/js/src/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 ('/images/_/_/_/_/MessagePractise/storage/app/blog/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/store', {
- comment: this.commentText,
- blogId: this.$route.params.id,
- })
- .then(res => {
- this.blogComments.push({
- userId: this.userData.id,
- userFullName: this.userData.name,
- commented_at: new Date(),
- commentText: this.commentText,
- })
- this.commentText = ''
- })
- },
- }
- }
- </script>
- <style lang="scss">
- @import '~@resources/scss/vue/pages/page-blog.scss';
- </style>
|