feat:更新博客评论模块
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { cloudService } from './index'
|
||||
import { IBlog, IBlogCategory, IBlogStats, IBlogVisit, INewBlog, IQueryBlog } from '@/types/blog'
|
||||
import { IBlog, IBlogCategory, IBlogComment, IBlogStats, IBlogVisit, INewBlog, IQueryBlog } from '@/types/blog'
|
||||
|
||||
import qs from 'qs'
|
||||
import { IPageRecord } from '@/types'
|
||||
@@ -45,6 +45,19 @@ export const queryLatestBlogApi = (): Promise<IBlog[]> =>
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
export const queryBlogCommentApi = (blogId: number): Promise<IBlogComment[]> =>
|
||||
cloudService({
|
||||
url: `/blog-service/blog/comment/${blogId}`,
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
export const addBlogCommentApi = (blogComment: IBlogComment): Promise<boolean> =>
|
||||
cloudService({
|
||||
url: '/blog-service/blog/comment',
|
||||
method: 'put',
|
||||
data: blogComment
|
||||
})
|
||||
|
||||
export const queryAdminBlogApi = (currentPage: number,
|
||||
pageSize: number): Promise<IPageRecord<IBlog>> =>
|
||||
cloudService({
|
||||
|
||||
@@ -13,16 +13,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import BlogCommentItem from '@/components/Blog/Comment/BlogCommentItem.vue'
|
||||
import { onMounted } from 'vue'
|
||||
import { useBlogStore } from '@/store/blog'
|
||||
import { flattenToTwoLevel } from '@/utils/blog/blogUtil'
|
||||
|
||||
const blogStore = useBlogStore()
|
||||
|
||||
onMounted(() => {
|
||||
blogStore.queryBlogComment(blogStore.currentBlogId)
|
||||
blogStore.blogNestedCommentList = flattenToTwoLevel(blogStore.blogCommentList)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
<div class="blog-comment-edit">
|
||||
<div class="comment-title">
|
||||
<el-input v-model="blogComment.name"
|
||||
placeholder="请输入Github用户名"/>
|
||||
:maxlength="10" show-word-limit
|
||||
placeholder="请输入昵称"/>
|
||||
<el-input v-model="blogComment.website"
|
||||
:maxlength="50" show-word-limit
|
||||
placeholder="请输入个人博客网站"/>
|
||||
</div>
|
||||
|
||||
<el-input v-model="blogComment.content"
|
||||
placeholder="有什么想和我说的呢" maxlength="500"
|
||||
placeholder="有什么想和我说的呢" :maxlength="500"
|
||||
:rows="7" show-word-limit type="textarea"
|
||||
/>
|
||||
|
||||
@@ -28,6 +30,7 @@
|
||||
|
||||
<el-button type="primary"
|
||||
:disabled="blogComment.content.length === 0"
|
||||
@click="sendCommentClick"
|
||||
class="send-button">发送</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -36,24 +39,59 @@
|
||||
<script setup lang="ts">
|
||||
import EmojiPicker from 'vue3-emoji-picker'
|
||||
import 'vue3-emoji-picker/css'
|
||||
import { defineProps, ref, onMounted } from 'vue'
|
||||
import { useBlogStore } from '@/store/blog.ts'
|
||||
import { deepCopyObject } from 'vue3-common/utils/dataUtil'
|
||||
import { IBlogComment } from '@/types/blog.ts'
|
||||
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const blogStore = useBlogStore()
|
||||
const emojiPopoverRef = ref()
|
||||
|
||||
const blogComment = reactive({
|
||||
const props = defineProps({
|
||||
parentId: {
|
||||
required: true,
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
|
||||
const blogComment = ref<IBlogComment>({
|
||||
id: 0,
|
||||
blogId: 0,
|
||||
name: '',
|
||||
website: '',
|
||||
content: ''
|
||||
content: '',
|
||||
ipAddress: '',
|
||||
userAgent: '',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: ''
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
blogComment.value = deepCopyObject(blogStore.getEmptyBlogComment())
|
||||
})
|
||||
|
||||
const onSelectEmoji = (emoji) => {
|
||||
if (blogComment.content.length <= 498) {
|
||||
blogComment.content += emoji.i
|
||||
if (blogComment.value.content.length <= 498) {
|
||||
blogComment.value.content += emoji.i
|
||||
}
|
||||
|
||||
emojiPopoverRef.value.hide()
|
||||
}
|
||||
|
||||
const sendCommentClick = async () => {
|
||||
blogComment.value.parentId = props.parentId
|
||||
blogComment.value.blogId = blogStore.currentBlogId
|
||||
|
||||
if (!blogComment.value.name) {
|
||||
blogComment.value.name = 'Anonymous'
|
||||
}
|
||||
|
||||
await blogStore.addBlogComment(blogComment.value)
|
||||
blogComment.value = deepCopyObject(blogStore.getEmptyBlogComment())
|
||||
blogStore.isShowBlogCommentEdit = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div class="blog-comment-card">
|
||||
<el-avatar :size="50" :src="`https://github.com/${props.comment.name}.png`" alt="未加载"/>
|
||||
<el-avatar :src="`https://api.dicebear.com/6.x/adventurer/svg?seed=${props.comment.name}`"
|
||||
:size="50" alt="未加载"/>
|
||||
|
||||
<div class="blog-comment-content">
|
||||
<div class="basic-info">
|
||||
<span>{{ props.comment.name }}</span>
|
||||
<span class="content">Chrome 137.0.0.0</span>
|
||||
<span class="content">macOS 10.15.7</span>
|
||||
<span class="content">{{ getBrowser(props.comment.userAgent) }}</span>
|
||||
<span class="content">{{ getOsInfo(props.comment.userAgent) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="sub-info">
|
||||
@@ -19,17 +20,19 @@
|
||||
|
||||
<p>{{ props.comment.content }}</p>
|
||||
|
||||
<blog-comment-edit v-if="blogComment.isShowEdit"/>
|
||||
<blog-comment-edit v-if="blogComment.isShowEdit"
|
||||
:parent-id="props.comment.id"/>
|
||||
|
||||
<div class="reply-list">
|
||||
<div class="blog-comment-card" v-for="(item, index) in props.replyList" :key="index">
|
||||
<el-avatar :size="50" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'" />
|
||||
<el-avatar :src="`https://api.dicebear.com/6.x/adventurer/svg?seed=${item.name}`"
|
||||
:size="50" alt="未加载"/>
|
||||
|
||||
<div class="blog-comment-content">
|
||||
<div class="basic-info">
|
||||
<span>{{ item.name }}</span>
|
||||
<span class="content">Chrome 137.0.0.0</span>
|
||||
<span class="content">macOS 10.15.7</span>
|
||||
<span class="content">{{ getBrowser(props.comment.userAgent) }}</span>
|
||||
<span class="content">{{ getOsInfo(props.comment.userAgent) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="sub-info">
|
||||
@@ -48,12 +51,18 @@ import BlogCommentEdit from '@/components/Blog/Comment/BlogCommentEdit.vue'
|
||||
import 'vue3-emoji-picker/css'
|
||||
import { defineProps, PropType, reactive } from 'vue'
|
||||
import { IBlogComment } from '@/types/blog'
|
||||
import { useBlogStore } from '@/store/blog.ts'
|
||||
import { UAParser } from 'ua-parser-js'
|
||||
|
||||
const blogStore = useBlogStore()
|
||||
|
||||
const props = defineProps({
|
||||
comment: {
|
||||
required: true,
|
||||
type: Object as PropType<IBlogComment>
|
||||
},
|
||||
replyList: {
|
||||
required: true,
|
||||
type: Object as PropType<IBlogComment[]>
|
||||
}
|
||||
})
|
||||
@@ -63,12 +72,23 @@ const blogComment = reactive({
|
||||
})
|
||||
|
||||
const replyClick = () => {
|
||||
blogStore.currentBlogComment = blogStore.getEmptyBlogComment()
|
||||
blogComment.isShowEdit = true
|
||||
}
|
||||
|
||||
const cancelClick = () => {
|
||||
blogComment.isShowEdit = false
|
||||
}
|
||||
|
||||
const getOsInfo = (userAgent: string) => {
|
||||
const uaParse = new UAParser(userAgent)
|
||||
return `${uaParse.getOS().name} ${uaParse.getOS().version}`
|
||||
}
|
||||
|
||||
const getBrowser = (userAgent: string) => {
|
||||
const uaParse = new UAParser(userAgent)
|
||||
return `${uaParse.getBrowser().name} ${uaParse.getBrowser().version}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<span>-------------本文结束♥感谢您的阅读♥给个五星好评吧~~-------------</span>
|
||||
</div>
|
||||
|
||||
<blog-comment-edit />
|
||||
<blog-comment-edit :parent-id="0"/>
|
||||
|
||||
<blog-comment />
|
||||
</div>
|
||||
@@ -44,15 +44,19 @@ import 'md-editor-v3/lib/style.css'
|
||||
import { useBlogStore } from '@/store/blog.ts'
|
||||
import { getBasicBlog } from '@/utils/blog/blogUtil.ts'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { onMounted } from 'vue'
|
||||
import { computed, onMounted } from 'vue'
|
||||
|
||||
const blogStore = useBlogStore()
|
||||
const route = useRoute()
|
||||
|
||||
const currentUrl = new URL(window.location.href)
|
||||
|
||||
const blogComment = computed(() => blogStore.getEmptyBlogComment())
|
||||
|
||||
onMounted(async () => {
|
||||
await blogStore.queryBlogById(route.params.id as number)
|
||||
const blogId = route.params.id as number
|
||||
blogStore.currentBlogId = blogId
|
||||
await blogStore.queryBlogById(blogId)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
63
src/layout/mobile-home/TitleBar.vue
Normal file
63
src/layout/mobile-home/TitleBar.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="title-bar">
|
||||
<div class="left-container">
|
||||
<el-button v-if="appStore.isShowMobileBack"
|
||||
type="info" :icon="Back" size="small"
|
||||
circle color="#FFFFFF"
|
||||
@click="goBackClick" />
|
||||
<div v-else class="logo-container">
|
||||
<img :src="getAssetsImageFile('logo/logo.png')" alt="暂无图片" class="logo"/>
|
||||
<span>{{ appStore.appName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="title-container">{{ title }}</span>
|
||||
|
||||
<div class="right-container">
|
||||
<svg-icon v-if="appStore.isWebSocket"
|
||||
name="home-websocket" style="color: #FFFFFF;"></svg-icon>
|
||||
<el-button type="info" :icon="Setting" size="small"
|
||||
circle color="#FFFFFF" @click="openSettingClick"/>
|
||||
|
||||
<el-drawer
|
||||
v-model="appStore.isShowSetting"
|
||||
title="系统设置" :show-close="false"
|
||||
size="50%" class="setting-drawer">
|
||||
<mobile-setting />
|
||||
</el-drawer>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { SvgIcon } from 'vue3-common'
|
||||
import MobileSetting from '@/components/Mobile/MobileSetting.vue'
|
||||
import { Back } from '@element-plus/icons-vue'
|
||||
import { Setting } from '@element-plus/icons-vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { computed } from 'vue'
|
||||
import { getAssetsImageFile } from '@/utils'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const router = useRouter()
|
||||
|
||||
const title = computed(() => router.currentRoute.value.meta.title)
|
||||
|
||||
const goBackClick = () => {
|
||||
appStore.isShowMobileBack = false
|
||||
history.back()
|
||||
}
|
||||
|
||||
const openSettingClick = () => {
|
||||
appStore.isShowSetting = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.setting-drawer {
|
||||
.el-drawer__header {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,33 +1,6 @@
|
||||
<template>
|
||||
<section class="layout-mobile-home">
|
||||
<div class="title-bar">
|
||||
<div class="left-container">
|
||||
<el-button v-if="appStore.isShowMobileBack"
|
||||
type="info" :icon="Back" size="small"
|
||||
circle color="#FFFFFF"
|
||||
@click="goBackClick" />
|
||||
<div v-else class="logo-container">
|
||||
<img :src="getAssetsImageFile('logo/logo.png')" alt="暂无图片" class="logo"/>
|
||||
<span>Sweet Hut</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="title-container">{{ title }}</span>
|
||||
|
||||
<div class="right-container">
|
||||
<svg-icon v-if="appStore.isWebSocket"
|
||||
name="home-websocket" style="color: #FFFFFF;"></svg-icon>
|
||||
<el-button type="info" :icon="Setting" size="small"
|
||||
circle color="#FFFFFF" @click="openSettingClick"/>
|
||||
|
||||
<el-drawer
|
||||
v-model="appStore.isShowSetting"
|
||||
title="系统设置" :show-close="false"
|
||||
size="50%" class="setting-drawer">
|
||||
<mobile-setting />
|
||||
</el-drawer>
|
||||
</div>
|
||||
</div>
|
||||
<title-bar />
|
||||
|
||||
<router-view />
|
||||
|
||||
@@ -36,37 +9,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { SvgIcon } from 'vue3-common'
|
||||
import MobileSetting from '@/components/Mobile/MobileSetting.vue'
|
||||
import { Back } from '@element-plus/icons-vue'
|
||||
import { Setting } from '@element-plus/icons-vue'
|
||||
import TitleBar from '@/layout/mobile-home/TitleBar.vue'
|
||||
import TabBar from '@/layout/mobile-home/TabBar.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { computed } from 'vue'
|
||||
import { getAssetsImageFile } from '@/utils'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const router = useRouter()
|
||||
|
||||
const title = computed(() => router.currentRoute.value.meta.title)
|
||||
|
||||
const goBackClick = () => {
|
||||
appStore.isShowMobileBack = false
|
||||
history.back()
|
||||
}
|
||||
|
||||
const openSettingClick = () => {
|
||||
appStore.isShowSetting = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "@/styles/mobile.home.layout.module.scss";
|
||||
|
||||
.setting-drawer {
|
||||
.el-drawer__header {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useDark, useToggle } from '@vueuse/core'
|
||||
|
||||
export const useAppStore = defineStore('ipp', {
|
||||
state: () => ({
|
||||
appName: 'Sweet Hut',
|
||||
sidebar: {
|
||||
// !!:转为布尔值
|
||||
// 保存当前菜单栏显示和隐藏的状态
|
||||
|
||||
@@ -4,19 +4,32 @@ import {
|
||||
IBlogLatest, IBlogNestedComment, IBlogStats, INewBlog, IQueryBlog
|
||||
} from '@/types/blog'
|
||||
import {
|
||||
addBlogApi, deleteBlogApi, queryAdminBlogApi, queryAdminBlogByIdApi, queryAdminBlogCategoryApi,
|
||||
addBlogApi, addBlogCommentApi, deleteBlogApi, queryAdminBlogApi, queryAdminBlogByIdApi, queryAdminBlogCategoryApi,
|
||||
queryBlogApi, queryBlogByConditionApi, queryBlogByIdApi,
|
||||
queryBlogCategoryApi, queryBlogStatsApi, queryLatestBlogApi, updateBlogApi
|
||||
queryBlogCategoryApi, queryBlogCommentApi, queryBlogStatsApi, queryLatestBlogApi, updateBlogApi
|
||||
} from '@/apis/blog.ts'
|
||||
import { IHandleApi } from 'vue3-common/types'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ImagePathEnum } from '@/types'
|
||||
import { flattenToTwoLevel } from '@/utils/blog/blogUtil.ts'
|
||||
|
||||
export const useBlogStore = defineStore('blog', {
|
||||
state: () => ({
|
||||
blogList: [] as IBlog[],
|
||||
blogCommentList: [] as IBlogComment[],
|
||||
blogNestedCommentList: [] as IBlogNestedComment[],
|
||||
currentBlogComment: {
|
||||
id: 0,
|
||||
blogId: 0,
|
||||
name: '',
|
||||
website: '',
|
||||
content: '',
|
||||
ipAddress: '',
|
||||
userAgent: '',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: ''
|
||||
} as IBlogComment,
|
||||
currentBlogId: 0,
|
||||
currentBlog: {
|
||||
id: 0,
|
||||
@@ -77,193 +90,18 @@ export const useBlogStore = defineStore('blog', {
|
||||
},
|
||||
async queryBlogById(id: number) {
|
||||
this.currentBlog = await queryBlogByIdApi(id)
|
||||
await this.queryBlogComment(this.currentBlogId)
|
||||
this.blogNestedCommentList = flattenToTwoLevel(this.blogCommentList)
|
||||
},
|
||||
async queryAdminBlogById(id: number) {
|
||||
this.currentBlog = await queryAdminBlogByIdApi(id)
|
||||
},
|
||||
async queryBlogComment(blogId: number) {
|
||||
this.blogCommentList = [
|
||||
{
|
||||
id: 1,
|
||||
blogId,
|
||||
name: 'Cxx0822',
|
||||
website: 'https://zhangsan.com',
|
||||
content: '这篇文章写得非常好,对我理解前端框架很有帮助,期待更多类似内容!',
|
||||
ipAddress: '114.114.114.114',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-15 08:30:22'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
blogId,
|
||||
name: '李四',
|
||||
website: '',
|
||||
content: '请问文中提到的性能优化方案在实际项目中效果如何?有没有遇到什么坑?',
|
||||
ipAddress: '127.0.0.1',
|
||||
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13.2; rv:109.0) Gecko/20100101 Firefox/114.0',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-15 14:15:47'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
blogId,
|
||||
name: '作者',
|
||||
website: 'https://blog.example.com',
|
||||
content: '回复 @李四:实际应用中效果显著,但需要注意兼容性问题,特别是旧版本浏览器的支持情况。',
|
||||
ipAddress: '192.168.1.100',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0',
|
||||
parentId: 2,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-16 09:22:10'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
blogId,
|
||||
name: '王五',
|
||||
website: 'https://wangwu.dev',
|
||||
content: '能否分享一下文章中提到的代码示例?想学习具体实现方式。',
|
||||
ipAddress: '203.0.113.5',
|
||||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_4 like Mac OS X) AppleWebKit/605.1.15',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-16 16:38:55'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
blogId,
|
||||
name: '赵六',
|
||||
website: '',
|
||||
content: '前端性能优化确实是个重要课题,我在项目中也遇到过类似问题,感谢分享经验!',
|
||||
ipAddress: '103.235.46.133',
|
||||
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-17 10:12:30'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
blogId,
|
||||
name: '林七',
|
||||
website: 'https://linqi.com',
|
||||
content: '这个框架的状态管理方案看起来很新颖,和Redux相比有什么优势吗?',
|
||||
ipAddress: '172.16.31.10',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-10 15:45:18'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
blogId,
|
||||
name: '作者',
|
||||
website: 'https://blog.example.com',
|
||||
content: '回复 @林七:最大的优势是更简洁的API和更好的TypeScript支持,尤其适合小型到中型项目。',
|
||||
ipAddress: '192.168.1.100',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0',
|
||||
parentId: 6,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-11 09:10:22'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
blogId,
|
||||
name: '孙八',
|
||||
website: 'https://sunba.dev',
|
||||
content: '已经按照文章中的步骤实践了,效果不错!不过在SSR场景下遇到了一些问题...',
|
||||
ipAddress: '192.168.3.11',
|
||||
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13.2; rv:109.0) Gecko/20100101 Firefox/114.0',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-12 11:22:35'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
blogId,
|
||||
name: '周九',
|
||||
website: '',
|
||||
content: '请问文章中的示例代码是否支持IE11?我们项目还在使用旧浏览器。',
|
||||
ipAddress: '172.16.58.3',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko',
|
||||
parentId: 0,
|
||||
isApproved: false, // 未审核
|
||||
createTime: '2025-06-08 08:08:08'
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
blogId,
|
||||
name: '吴十',
|
||||
website: 'https://wushi.net',
|
||||
content: '前端工程化真的很重要,之前项目因为没有规范导致维护困难,感谢分享最佳实践!',
|
||||
ipAddress: '192.168.127.12',
|
||||
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-09 14:30:45'
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
blogId,
|
||||
name: '郑十一',
|
||||
website: '',
|
||||
content: '回复 @周九:需要添加polyfill,具体可以参考这篇文档:https://example.com/ie-support',
|
||||
ipAddress: '172.16.17.32',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
||||
parentId: 9,
|
||||
isApproved: false, // 未审核
|
||||
createTime: '2025-06-08 09:15:22'
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
blogId,
|
||||
name: '钱十二',
|
||||
website: 'https://qianshier.com',
|
||||
content: '这个UI组件库的设计风格我很喜欢,请问有移动端适配方案吗?',
|
||||
ipAddress: '10.10.10.10',
|
||||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_4 like Mac OS X) AppleWebKit/605.1.15',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-05 16:20:10'
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
blogId,
|
||||
name: '作者',
|
||||
website: 'https://blog.example.com',
|
||||
content: '回复 @钱十二:有的,组件库内置了响应式设计,支持移动端自适应布局。',
|
||||
ipAddress: '192.168.1.100',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0',
|
||||
parentId: 12,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-06 10:05:33'
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
blogId,
|
||||
name: '冯十三',
|
||||
website: 'https://fengshisan.dev',
|
||||
content: '文档很详细,但是在Tree Shaking时遇到了问题,请问如何配置?',
|
||||
ipAddress: '192.168.3.11',
|
||||
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13.2; rv:109.0) Gecko/20100101 Firefox/114.0',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-07 09:45:15'
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
blogId,
|
||||
name: '陈十四',
|
||||
website: '',
|
||||
content: '性能测试部分的数据很有参考价值,能否分享一下测试环境和工具?',
|
||||
ipAddress: '172.16.31.10',
|
||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
||||
parentId: 0,
|
||||
isApproved: true,
|
||||
createTime: '2025-06-04 14:12:28'
|
||||
}
|
||||
]
|
||||
this.blogCommentList = await queryBlogCommentApi(blogId)
|
||||
},
|
||||
async addBlogComment(blogComment: IBlogComment) {
|
||||
await addBlogCommentApi(blogComment)
|
||||
await this.queryBlogById(blogComment.blogId)
|
||||
},
|
||||
async queryBlogCategory() {
|
||||
this.blogCategoryList = await queryBlogCategoryApi()
|
||||
@@ -311,6 +149,20 @@ export const useBlogStore = defineStore('blog', {
|
||||
title: '',
|
||||
topValue: 0
|
||||
}
|
||||
},
|
||||
getEmptyBlogComment(): IBlogComment {
|
||||
return {
|
||||
blogId: 0,
|
||||
content: '',
|
||||
createTime: '',
|
||||
id: 0,
|
||||
ipAddress: '',
|
||||
isApproved: true,
|
||||
name: '',
|
||||
parentId: 0,
|
||||
userAgent: '',
|
||||
website: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@ export enum ImagePathEnum {
|
||||
FOOD = 'food',
|
||||
TRAVEL = 'travel',
|
||||
PRODUCT = 'product',
|
||||
JOURNAL = 'JOURNAL',
|
||||
JOURNAL = 'journal',
|
||||
LEDGER = 'ledger',
|
||||
USER = 'user'
|
||||
}
|
||||
|
||||
@@ -192,4 +192,3 @@ export function flattenToTwoLevel(comments: IBlogComment[]): IBlogNestedComment[
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user