diff --git a/docs/q1.md b/docs/q1.md
new file mode 100644
index 0000000..690531d
--- /dev/null
+++ b/docs/q1.md
@@ -0,0 +1,2 @@
+我们需要全局缓存一个点赞的列表,使用 metadata.name 做key,存储到store并且开启持久化存储,如果已经点过赞,直接显示已
+ 经点赞的样式。同时我们的点赞接口是不会返回内容的,所以再捕获异常的时候不要提示异常信息。
\ No newline at end of file
diff --git a/src/api/halo-plugin/uni-halo.ts b/src/api/halo-plugin/uni-halo.ts
index 85772da..8fc919f 100644
--- a/src/api/halo-plugin/uni-halo.ts
+++ b/src/api/halo-plugin/uni-halo.ts
@@ -1,6 +1,10 @@
import { http } from '@/http/alova'
export interface IUniHaloConfig {
+ // 应用信息配置
+ app: {
+ name: string
+ }
base: {
// 博客域名
domain: string
diff --git a/src/components/post-detail/uh-guest-info-panel.vue b/src/components/post-detail/uh-guest-info-panel.vue
new file mode 100644
index 0000000..e1712e2
--- /dev/null
+++ b/src/components/post-detail/uh-guest-info-panel.vue
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 游客信息
+
+
+
+
+
+
+
+
+
+ 昵称 *
+
+ {{ rules.displayName }}
+
+
+
+
+ 邮箱 *
+
+ {{ rules.email }}
+
+
+
+
+ 网站
+
+
+
+
+
+ 保存
+
+
+
+
+
+
+
+
diff --git a/src/components/post-detail/uh-post-comment-panel.vue b/src/components/post-detail/uh-post-comment-panel.vue
index c57b458..3396361 100644
--- a/src/components/post-detail/uh-post-comment-panel.vue
+++ b/src/components/post-detail/uh-post-comment-panel.vue
@@ -2,8 +2,11 @@
import { createComment, createReply, listCommentReplies, listComments } from '@/api/halo-base/comment'
import { avatar } from '@/utils/imageHelper'
import { timeFrom } from '@/utils/base/timeFrom'
+import { useGuestStore } from '@/store/guest'
+import { useUpvoteStore } from '@/store/upvote'
import type { CommentV1alpha1PublicApiListCommentRepliesRequest, CommentV1alpha1PublicApiListComments1Request, CommentWithReplyVo, ReplyVo } from '@halo-dev/api-client'
import type { IHaloListResponseBase } from '@/api/types/halo'
+import UhGuestInfoPanel from './uh-guest-info-panel.vue'
interface IProps {
postName: string
@@ -20,6 +23,9 @@ const emits = defineEmits<{
(e: 'commented'): void
}>()
+const guestStore = useGuestStore()
+const upvoteStore = useUpvoteStore()
+
// --- 评论列表 ---
const commentList = ref([])
const commentPage = ref(1)
@@ -44,6 +50,26 @@ const replyLoadingMap = ref>({})
const replyHasNextMap = ref>({})
const replyPageMap = ref>({})
+// --- 游客信息面板 ---
+const showGuestPanel = ref(false)
+
+// --- 点赞(切换) ---
+async function handleUpvote(name: string) {
+ const nowUpvoted = await upvoteStore.toggle(name, 'comments')
+ // 更新本地计数
+ for (const comment of commentList.value) {
+ if (comment.metadata.name === name) {
+ comment.stats.upvote = Math.max(0, (comment.stats.upvote ?? 0) + (nowUpvoted ? 1 : -1))
+ break
+ }
+ const reply = comment.replies?.items?.find(r => r.metadata.name === name)
+ if (reply) {
+ reply.stats.upvote = Math.max(0, (reply.stats.upvote ?? 0) + (nowUpvoted ? 1 : -1))
+ break
+ }
+ }
+}
+
// --- 获取评论列表 ---
async function fetchComments(page = 1, append = false) {
commentLoading.value = true
@@ -152,13 +178,29 @@ function handleCancelReply() {
}
// --- 提交评论/回复 ---
-async function handleSubmit() {
+function handleSubmit() {
const text = inputText.value.trim()
if (!text || submitLoading.value)
return
+ // 检查游客信息,未设置直接弹出面板
+ if (!guestStore.isComplete) {
+ showGuestPanel.value = true
+ return
+ }
+
+ doSubmit(text)
+}
+
+async function doSubmit(text: string) {
submitLoading.value = true
try {
+ const owner = {
+ displayName: guestStore.info.displayName,
+ email: guestStore.info.email,
+ website: guestStore.info.website || undefined,
+ }
+
if (replyTarget.value) {
await createReply({
name: replyTarget.value.commentName,
@@ -167,6 +209,7 @@ async function handleSubmit() {
raw: text,
quoteReply: replyTarget.value.replyName || undefined,
allowNotification: true,
+ owner,
},
} as any)
}
@@ -182,6 +225,8 @@ async function handleSubmit() {
version: props.commentSubjectVersion,
},
allowNotification: true,
+ hidden: false,
+ owner,
},
} as any)
}
@@ -201,6 +246,16 @@ async function handleSubmit() {
}
}
+// --- 游客信息保存后自动提交 ---
+function handleGuestSaved() {
+ showGuestPanel.value = false
+ // 保存后如果有输入内容,自动提交
+ const text = inputText.value.trim()
+ if (text) {
+ doSubmit(text)
+ }
+}
+
// --- 查找被引用的回复 ---
function findQuotedReply(comment: CommentWithReplyVo, quoteReplyName: string): ReplyVo | undefined {
return comment.replies?.items?.find(r => r.metadata.name === quoteReplyName)
@@ -291,6 +346,24 @@ onMounted(() => {
+
+
+
+
+ {{ comment.stats.upvote || '' }}
+
+
+
{
回复
+
{
-
-
- 回复
+
+
+
+
+
+
+ {{ reply.stats.upvote || '' }}
+
+
+
+
+
+ 回复
+
@@ -422,4 +517,11 @@ onMounted(() => {
+
+
+
diff --git a/src/hooks/useShare.ts b/src/hooks/useShare.ts
new file mode 100644
index 0000000..0219189
--- /dev/null
+++ b/src/hooks/useShare.ts
@@ -0,0 +1,47 @@
+import { storeToRefs } from 'pinia'
+import { useUniHaloConfigStore } from '@/store/config'
+
+export interface IShareAppMessageOption {
+ title?: string
+ path: string
+ query?: string
+ imageUrl?: string
+ onlyAppNameTitle?: boolean
+}
+
+/**
+ * 应用分享
+ */
+export function useAppShare() {
+ const { config } = storeToRefs(useUniHaloConfigStore())
+
+ const setShareOptions = (options: IShareAppMessageOption) => {
+ const { onlyAppNameTitle = false } = options
+ if (!options.path) {
+ return
+ }
+
+ const title = onlyAppNameTitle ? config.value.app.name : options.title
+
+ onShareAppMessage(() => {
+ return {
+ title,
+ path: options.path + (options.query ? `?${options.query}` : ''),
+ imageUrl: options.imageUrl,
+ }
+ })
+
+ onShareTimeline(() => {
+ return {
+ title,
+ path: options.path,
+ imageUrl: options.imageUrl,
+ query: options.query,
+ }
+ })
+ }
+
+ return {
+ setShareOptions,
+ }
+}
diff --git a/src/pages/auth/login.vue b/src/pages/auth/login.vue
index ecdfe74..6821304 100644
--- a/src/pages/auth/login.vue
+++ b/src/pages/auth/login.vue
@@ -1,40 +1,378 @@
-
-
-
- 登录页
+
+
+
+
+ 欢迎回来
+ 登录你的账号,探索更多精彩
-
+
+
+
+
+ 登录
+
+
+ 注册
+
+
+
+
+
+
+
+ 用户名
+
+
+
+
+ {{ loginErrors.username }}
+
+
+
+
+ 密码
+
+
+
+
+
+
+
+ {{ loginErrors.password }}
+
+
+
+
+ 登录
+
+
+
+
+
+
+
+ 用户名
+
+
+
+
+ {{ registerErrors.username }}
+
+
+
+
+ 密码
+
+
+
+
+
+
+
+ {{ registerErrors.password }}
+
+
+
+
+ 确认密码
+
+
+
+
+
+
+
+ {{ registerErrors.confirmPassword }}
+
+
+
+
+ 注册
+
+
+
+
+
+
+ 其他方式
+
+
+
+
+
+
+
+
+ 微信一键登录
+
+
+
+
+
+ 游客身份访问
+
+
+
+
+
+ 登录或注册即代表同意
+
+ 《用户协议》
+ 和
+ 《隐私政策》
+
+
+
+
+
diff --git a/src/pages/auth/register.vue b/src/pages/auth/register.vue
deleted file mode 100644
index 767097c..0000000
--- a/src/pages/auth/register.vue
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
- 注册页
-
-
-
-
diff --git a/src/pages/gallery/gallery-bak.vue b/src/pages/gallery/gallery-bak.vue
deleted file mode 100644
index 3c233ae..0000000
--- a/src/pages/gallery/gallery-bak.vue
+++ /dev/null
@@ -1,348 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 最新精选
-
-
-
- 显示图片的名称
-
-
- 显示描述/日期
-
-
-
-
-
-
-
-
-
- 我的相册
- 共 30 组记录
-
-
-
-
-
-
-
-
-
-
- {{ group.displayName }}
- {{ group.images.length }} 张图片
-
-
-
-
-
-
-
-
-
-
-
-
- {{ group.displayName }}
-
-
- {{ group.images.length }} 张
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 无数据
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/pages/gallery/gallery.vue b/src/pages/gallery/gallery.vue
index 05813b2..7b5d7ef 100644
--- a/src/pages/gallery/gallery.vue
+++ b/src/pages/gallery/gallery.vue
@@ -1,9 +1,10 @@
-
+
diff --git a/src/pages/home/home.vue b/src/pages/home/home.vue
index 864ef8f..373ef75 100644
--- a/src/pages/home/home.vue
+++ b/src/pages/home/home.vue
@@ -1,5 +1,6 @@
-
+
@@ -223,7 +231,7 @@ onLoad(async () => {
复制
@@ -258,7 +266,7 @@ onLoad(async () => {
diff --git a/src/pages/mine/mine.vue b/src/pages/mine/mine.vue
index 352386b..9935e47 100644
--- a/src/pages/mine/mine.vue
+++ b/src/pages/mine/mine.vue
@@ -2,38 +2,92 @@
import { storeToRefs } from 'pinia'
import { LOGIN_PAGE } from '@/router/config'
import { useUserStore } from '@/store'
+import { useGuestStore } from '@/store/guest'
import { useTokenStore } from '@/store/token'
-import i18n, { t } from '@/locale/index'
-import { setTabbarItem } from '@/tabbar/i18n'
+import GuestInfoPanel from '@/components/post-detail/uh-guest-info-panel.vue'
-defineOptions({
- name: 'Mine',
-})
+defineOptions({ name: 'Mine' })
definePage({
style: {
navigationBarTitleText: '我的',
navigationBarBackgroundColor: '#ffffff',
- enablePullDownRefresh: true,
},
})
const userStore = useUserStore()
const tokenStore = useTokenStore()
-// 使用storeToRefs解构userInfo
+const guestStore = useGuestStore()
+
const { userInfo } = storeToRefs(userStore)
-// 微信小程序下登录
-async function handleLogin() {
- // #ifdef MP-WEIXIN
- // 微信登录
- await tokenStore.wxLogin()
+/** 是否已登录 */
+const hasLogin = computed(() => tokenStore.hasLogin)
+/** 是否已填写游客信息 */
+const hasGuestInfo = computed(() => guestStore.isComplete)
+/** 显示的头像 */
+const displayAvatar = computed(() => {
+ if (hasLogin.value && userInfo.value.avatar) {
+ return userInfo.value.avatar
+ }
+ return '/static/images/default-avatar.png'
+})
+
+/** 显示的名称 */
+const displayName = computed(() => {
+ if (hasLogin.value) {
+ return userInfo.value.nickname || userInfo.value.username
+ }
+ if (hasGuestInfo.value) {
+ return guestStore.info.displayName
+ }
+ return '未登录'
+})
+
+/** 显示的副标题 */
+const displaySubtitle = computed(() => {
+ if (hasLogin.value) {
+ return userInfo.value.role || userInfo.value.username
+ }
+ if (hasGuestInfo.value) {
+ return guestStore.info.email
+ }
+ return '登录后解锁更多功能'
+})
+
+/** 用户状态标签 */
+const statusLabel = computed(() => {
+ if (hasLogin.value) return '已登录'
+ if (hasGuestInfo.value) return '游客'
+ return '未登录'
+})
+
+const statusColor = computed(() => {
+ if (hasLogin.value) return 'bg-green-50 text-green-600'
+ if (hasGuestInfo.value) return 'bg-amber-50 text-amber-600'
+ return 'bg-gray-100 text-gray-500'
+})
+
+// ---- 游客信息编辑 ----
+const showGuestPanel = ref(false)
+
+function handleEditGuest() {
+ showGuestPanel.value = true
+}
+
+function handleGuestSaved() {
+ showGuestPanel.value = false
+ uni.showToast({ title: '保存成功', icon: 'success' })
+}
+
+// ---- 登录/退出 ----
+function handleLogin() {
+ // #ifdef MP-WEIXIN
+ tokenStore.wxLogin()
// #endif
// #ifndef MP-WEIXIN
- uni.navigateTo({
- url: `${LOGIN_PAGE}`,
- })
+ uni.navigateTo({ url: LOGIN_PAGE })
// #endif
}
@@ -43,93 +97,121 @@ function handleLogout() {
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
- // 清空用户信息
- useTokenStore().logout()
- // 执行退出登录逻辑
- uni.showToast({
- title: '退出登录成功',
- icon: 'success',
- })
- // #ifdef MP-WEIXIN
- // 微信小程序,去首页
- // uni.reLaunch({ url: '/pages/index/index' })
- // #endif
- // #ifndef MP-WEIXIN
- // 非微信小程序,去登录页
- // uni.navigateTo({ url: LOGIN_PAGE })
- // #endif
+ tokenStore.logout()
+ uni.showToast({ title: '已退出登录', icon: 'success' })
}
},
})
}
-const current = ref(uni.getLocale())
-const languages = [
- {
- value: 'zh-Hans',
- name: '中文',
- checked: 'true',
- },
- {
- value: 'en',
- name: '英文',
- },
+// ---- 功能导航 ----
+interface NavItem {
+ icon: string
+ label: string
+ path?: string
+ showArrow?: boolean
+}
+
+const navList: NavItem[] = [
+ { icon: 'file', label: '免责声明', path: '', showArrow: true },
+ { icon: 'chat', label: '在线客服', path: '', showArrow: true },
+ { icon: 'edit', label: '意见反馈', path: '', showArrow: true },
+ { icon: 'info-circle', label: '关于项目', path: '/subpkg-blog/about/about', showArrow: true },
]
-function radioChange(evt) {
- // console.log(evt)
- current.value = evt.detail.value
- // 下面2句缺一不可!!!
- uni.setLocale(evt.detail.value)
- i18n.global.locale = evt.detail.value
-
- // 底部tabbar需要重新设置一下
- setTabbarItem()
- // 本页的标题也需要重新设置一下
- uni.setNavigationBarTitle({
- title: t('i18n.title'),
- })
+function handleNavClick(item: NavItem) {
+ if (item.path) {
+ uni.navigateTo({ url: item.path })
+ }
+ else {
+ uni.showToast({ title: '即将开放,敬请期待', icon: 'none' })
+ }
}
-
-
- {{ userInfo.username ? '已登录' : '未登录' }}
-
-
- {{ JSON.stringify(userInfo, null, 2) }}
-
-
-
-
-
- 切换语言
-
-
-
-
-
+
+ {{ displaySubtitle }}
+
+
+
+
+
+
+
+
+
+
+ 填写游客信息(用于评论互动)
+
+
+
+
+
+
+ 账号:{{ userInfo.username }}
-
-
-
-
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+ 退出登录
+
+
+ 立即登录
@@ -137,5 +219,12 @@ function radioChange(evt) {
+
+
+
diff --git a/src/pages/moments/moments.vue b/src/pages/moments/moments.vue
index 8cdd1bd..6ac4f38 100644
--- a/src/pages/moments/moments.vue
+++ b/src/pages/moments/moments.vue
@@ -1,4 +1,5 @@
-
+
diff --git a/src/router/config.ts b/src/router/config.ts
index dbe1dbe..2d5f3b9 100644
--- a/src/router/config.ts
+++ b/src/router/config.ts
@@ -9,9 +9,9 @@ export const LOGIN_STRATEGY = LOGIN_STRATEGY_MAP.DEFAULT_NO_NEED_LOGIN
export const isNeedLoginMode = LOGIN_STRATEGY === LOGIN_STRATEGY_MAP.DEFAULT_NEED_LOGIN
export const LOGIN_PAGE = '/pages/auth/login'
-export const REGISTER_PAGE = '/pages/auth/register'
+export const REGISTER_PAGE = '/pages/auth/login'
-export const LOGIN_PAGE_LIST = [LOGIN_PAGE, REGISTER_PAGE]
+export const LOGIN_PAGE_LIST = [LOGIN_PAGE]
// 在 definePage 里面配置了 excludeLoginPath 的页面,功能与 EXCLUDE_LOGIN_PATH_LIST 相同
export const excludeLoginPathList = getAllPages('excludeLoginPath').map(page => page.path)
diff --git a/src/store/config.ts b/src/store/config.ts
index f9515cb..c602a0b 100644
--- a/src/store/config.ts
+++ b/src/store/config.ts
@@ -4,6 +4,9 @@ import type { IUniHaloConfig } from '@/api/halo-plugin/uni-halo'
import { deepMerge } from '@/utils/base/deepMerge'
const defaultConfig: IUniHaloConfig = {
+ app: {
+ name: 'uni-halo',
+ },
base: {
domain: import.meta.env.VITE_UNI_HALO_DOMAIN,
token: import.meta.env.VITE_UNI_HALO_TOKEN,
diff --git a/src/store/guest.ts b/src/store/guest.ts
new file mode 100644
index 0000000..3b535b3
--- /dev/null
+++ b/src/store/guest.ts
@@ -0,0 +1,48 @@
+import { defineStore } from 'pinia'
+
+export interface IGuestInfo {
+ displayName: string
+ email: string
+ website: string
+}
+
+const GuestStoreKey = 'UNI_HALO_GUEST_INFO'
+
+const defaultGuestInfo: IGuestInfo = {
+ displayName: '',
+ email: '',
+ website: '',
+}
+
+/**
+ * 游客信息状态管理
+ */
+export const useGuestStore = defineStore('guest', () => {
+ const info = ref({ ...defaultGuestInfo, ...(uni.getStorageSync(GuestStoreKey) ?? {}) })
+
+ /** 是否已填写游客信息 */
+ const isComplete = computed(() => {
+ return !!(info.value.displayName.trim() && info.value.email.trim())
+ })
+
+ /** 保存游客信息 */
+ function save(data: IGuestInfo) {
+ info.value = { ...data }
+ uni.setStorageSync(GuestStoreKey, info.value)
+ }
+
+ /** 清除游客信息 */
+ function clear() {
+ info.value = { ...defaultGuestInfo }
+ uni.removeStorageSync(GuestStoreKey)
+ }
+
+ return {
+ info,
+ isComplete,
+ save,
+ clear,
+ }
+}, {
+ persist: false, // 手动管理持久化
+})
diff --git a/src/store/upvote.ts b/src/store/upvote.ts
new file mode 100644
index 0000000..d06d082
--- /dev/null
+++ b/src/store/upvote.ts
@@ -0,0 +1,47 @@
+import { defineStore } from 'pinia'
+import { downvote, upvote } from '@/api/halo-base/trackers'
+
+const UpvoteStoreKey = 'UNI_HALO_UPVOTED_SET'
+
+/**
+ * 全局点赞状态管理
+ * 使用 metadata.name 作为 key,持久化存储
+ */
+export const useUpvoteStore = defineStore('upvote', () => {
+ const upvotedSet = ref>(new Set(uni.getStorageSync(UpvoteStoreKey) ?? []))
+
+ /** 是否已点赞 */
+ function isUpvoted(name: string): boolean {
+ return upvotedSet.value.has(name)
+ }
+
+ /** 切换点赞状态 */
+ async function toggle(name: string, plural: 'comments' | 'posts' = 'comments'): Promise {
+ const alreadyUpvoted = upvotedSet.value.has(name)
+ try {
+ if (alreadyUpvoted) {
+ await downvote({ group: 'content.halo.run', plural, name })
+ upvotedSet.value.delete(name)
+ }
+ else {
+ await upvote({ group: 'content.halo.run', plural, name })
+ upvotedSet.value.add(name)
+ }
+ // 持久化
+ uni.setStorageSync(UpvoteStoreKey, Array.from(upvotedSet.value))
+ return !alreadyUpvoted
+ }
+ catch {
+ // 接口不返回内容,静默处理
+ return alreadyUpvoted
+ }
+ }
+
+ return {
+ upvotedSet,
+ isUpvoted,
+ toggle,
+ }
+}, {
+ persist: false, // 手动管理持久化
+})
diff --git a/src/subpkg-blog/post-detail/post-detail.vue b/src/subpkg-blog/post-detail/post-detail.vue
index fe9b998..9059108 100644
--- a/src/subpkg-blog/post-detail/post-detail.vue
+++ b/src/subpkg-blog/post-detail/post-detail.vue
@@ -3,15 +3,15 @@ import { useRequest } from '@/hooks/useRequest'
import { markdownConfig } from '@/config/markdown/config'
import { useUniHaloConfigStore } from '@/store/config'
import { queryPostByName, queryPostNavigationByName } from '@/api/halo-base/post'
-import { upvote } from '@/api/halo-base/trackers'
import { completeUrl } from '@/utils/url'
import { cover } from '@/utils/imageHelper'
import { timeFrom } from '@/utils/base/timeFrom'
import { formatNumberUnit } from '@/utils/base/digital'
+import { useUpvoteStore } from '@/store/upvote'
import type { NavigationPostVo, PostV1alpha1PublicApiQueryPostByNameRequest, PostVo } from '@halo-dev/api-client'
-import type { VoteRequest } from '@/api/halo-base/trackers'
import mpHtml from '@/components/mp-html/components/mp-html/mp-html.vue'
import UhPostCommentPanel from '@/components/post-detail/uh-post-comment-panel.vue'
+import copy from '@/utils/base/clipboard'
interface IPostDetailLoadOptions {
metadataName: string
@@ -37,14 +37,17 @@ const { data: navigation, run: fetchNavigation } = useRequest upvoteStore.isUpvoted(postName))
+
// --- 计算属性 ---
const coverUrl = computed(() => {
const raw = post.value?.spec?.cover
- return raw ? completeUrl(raw) : ''
+ return raw ? cover(raw) : ''
})
const categories = computed(() => {
@@ -80,42 +83,28 @@ function handleBack() {
}
async function handleUpvote() {
- if (isUpvoted.value)
- return
- try {
- await upvote({
- group: 'content.halo.run',
- plural: 'posts',
- name: postName,
- } as VoteRequest)
- isUpvoted.value = true
- upvoteCount.value = (post.value?.stats?.upvote ?? 0) + 1
- uni.showToast({ title: '点赞成功', icon: 'none' })
- }
- catch {
- uni.showToast({ title: '点赞失败', icon: 'none' })
- }
+ const nowUpvoted = await upvoteStore.toggle(postName, 'posts')
+ upvoteCount.value = Math.max(0, (post.value?.stats?.upvote ?? 0) + (nowUpvoted ? 1 : -1))
}
function handleShare() {
// #ifdef MP-WEIXIN
// 微信小程序中由页面右上角菜单处理分享
// #endif
- // #ifdef H5
- uni.setClipboardData({
- data: post.value?.status?.permalink ?? '',
- success: () => {
- uni.showToast({ title: '链接已复制', icon: 'none' })
- },
- })
+ // #ifndef MP-WEIXIN
+ copy(post.value?.status?.permalink ?? '', '链接已复制')
// #endif
}
+function handleScrollToTop() {
+ uni.pageScrollTo({ scrollTop: 0, duration: 300 })
+}
+
function handleNavigatePost(name: string) {
postName = name
fetchPost({ name })
fetchNavigation({ name })
- uni.pageScrollTo({ scrollTop: 0, duration: 300 })
+ handleScrollToTop()
}
async function loadData() {
@@ -133,10 +122,6 @@ onPageScroll(({ scrollTop }) => {
beforeScrollTop = scrollTop
})
-function handleScrollToTop() {
- uni.pageScrollTo({ scrollTop: 0, duration: 300 })
-}
-
// --- 生命周期 ---
onLoad((options: IPostDetailLoadOptions) => {
postName = options.metadataName
@@ -153,6 +138,16 @@ onShareAppMessage(() => {
return {
title: post.value?.spec?.title ?? '文章详情',
path: `/subpkg-blog/post-detail/post-detail?metadataName=${postName}`,
+ imageUrl: coverUrl.value,
+ }
+})
+
+onShareTimeline(() => {
+ return {
+ title: post.value?.spec?.title ?? '文章详情',
+ path: `/subpkg-blog/post-detail/post-detail`,
+ query: `metadataName=${postName}`,
+ imageUrl: coverUrl.value,
}
})
@@ -162,26 +157,15 @@ const showCommentPanel = ref(false)
function handleOpenCommentPanel() {
showCommentPanel.value = true
}
+function handleScrollContentToTop() {
+ uni.pageScrollTo({ scrollTop: 236, duration: 300 })
+}
-
-
-
-
-
-
-
-
- {{ post?.spec?.title ?? '笔记详情' }}
-
-
-
-
-
+
@@ -190,24 +174,34 @@ function handleOpenCommentPanel() {
-
+
-
+
+
+
+
+
+
-
- {{ post?.spec?.title ?? '加载中...'
- }}
+
+ {{ post?.spec?.title ?? '加载中...' }}
-
+
{{ cat.spec?.displayName }}
-
+
# {{ tag.spec?.displayName }}
@@ -230,8 +224,10 @@ function handleOpenCommentPanel() {
-
+
{{ post.owner.displayName }}
{{ post.owner.bio }}
@@ -240,21 +236,28 @@ function handleOpenCommentPanel() {
-
+ :scroll-table="true" :use-anchor="true"
+ />
+ class="box-border w-full flex flex-col gap-y-2 border-0 border-gray-100 rounded-xl border-solid p-4 pt-0"
+ >
-
+
-
+
上一篇
@@ -264,11 +267,15 @@ function handleOpenCommentPanel() {
-
+
-
+
下一篇
@@ -285,19 +292,25 @@ function handleOpenCommentPanel() {
- 加载中...
+
+ 加载中...
+
-
+
文章导航
-
+
@@ -309,8 +322,10 @@ function handleOpenCommentPanel() {
-
+
@@ -327,7 +342,8 @@ function handleOpenCommentPanel() {
+ class="uh-shadow-md uh-backdrop-blur box-border h-46px flex flex-1 items-center justify-around border border-white rounded-full border-solid bg-white/95 p-1"
+ >
@@ -357,25 +373,28 @@ function handleOpenCommentPanel() {
-
+
+
+ @click="handleScrollToTop"
+ >
-
+ @close="showCommentPanel = false" @commented="loadData"
+ />
diff --git a/src/utils/base/clipboard.ts b/src/utils/base/clipboard.ts
index 687a613..2c52bed 100644
--- a/src/utils/base/clipboard.ts
+++ b/src/utils/base/clipboard.ts
@@ -1,16 +1,16 @@
/**
* 复制文本到剪贴板
* @param {string} content 要复制的文本
- * @param {boolean} showToast 是否显示复制成功提示
+ * @param {string} toastText 复制成功提示内容
*/
-export function copy(content: string, showToast: boolean = false) {
+export function copy(content: string, toastText?: string) {
uni.setClipboardData({
data: content,
showToast: false,
success: () => {
- if (showToast) {
+ if (toastText) {
uni.showToast({
- title: '复制成功',
+ title: toastText,
icon: 'none',
})
}