diff --git a/src/App.ku.vue b/src/App.ku.vue
index 5bf77d6..b7975fb 100644
--- a/src/App.ku.vue
+++ b/src/App.ku.vue
@@ -28,10 +28,7 @@ defineExpose({
-
-
- {{ helloKuRoot }},这里可以配置全局的东西
-
+
diff --git a/src/api/halo.ts b/src/api/halo.ts
index f1a603b..a4f02d3 100644
--- a/src/api/halo.ts
+++ b/src/api/halo.ts
@@ -45,7 +45,7 @@ const COMMENT_WIDGET_CAPTCHA_COOKIES = 'comment-widget-captcha'
*/
export function getPostList(params: IPostListReq) {
return http.Get>('/apis/api.content.halo.run/v1alpha1/posts', {
- params,
+ query: params,
meta: { requestFrom: RequestFrom.Halo },
})
}
@@ -124,6 +124,7 @@ export function getPostByTagName(tagName: string, params: IPostListReq) {
export function getPostCommentList(params: ICommentListReq) {
return http.Get>('/apis/api.halo.run/v1alpha1/comments', {
params,
+ cacheFor: 0,
meta: { requestFrom: RequestFrom.Halo },
})
}
@@ -134,6 +135,7 @@ export function getPostCommentList(params: ICommentListReq) {
export function getPostCommentReplyList(commentName: string, params: ICommentListReq) {
return http.Get>(`/apis/api.halo.run/v1alpha1/comments/${commentName}/reply`, {
params,
+ cacheFor: 0,
meta: { requestFrom: RequestFrom.Halo },
})
}
diff --git a/src/api/types/halo.ts b/src/api/types/halo.ts
index 53d47a3..711c43e 100644
--- a/src/api/types/halo.ts
+++ b/src/api/types/halo.ts
@@ -27,6 +27,13 @@ export interface IListResult {
totalPages: number
}
+export interface IOwner {
+ avatar?: string
+ displayName?: string
+ bio?: string
+ metadata:{name:string}
+}
+
/* ---------- 文章 Post ---------- */
export interface IPostSpec {
@@ -34,6 +41,7 @@ export interface IPostSpec {
slug: string
excerpt?: string
cover?: string
+ owner:IOwner
/** 发布时间(Halo 2.x 结构,旧项目直接使用) */
publishTime?: string
deleted: boolean
@@ -83,6 +91,7 @@ export interface IContent {
export interface IPost {
metadata: IMetadata
spec: IPostSpec
+ owner: IOwner
status?: IPostStatus
content?: IContent
categories?: ICategory[]
@@ -270,13 +279,28 @@ export type ICommentListRes = IListResult
export interface IMoment {
metadata: IMetadata
+ /** 作者(公开接口在顶层返回;spec.owner 只是作者用户名) */
+ owner?: {
+ avatar?: string
+ bio?: string
+ displayName: string
+ name: string
+ [key: string]: unknown
+ }
spec: {
- content: string
- owner: {
- displayName: string
- avatar?: string
- website?: string
+ content: {
+ /** 正文 HTML */
+ html?: string
+ raw?: string
+ /** 多媒体(图片/视频/音频均在此,勿误读成 spec.medium) */
+ medium?: {
+ type?: 'PHOTO' | 'VIDEO' | 'AUDIO'
+ url?: string
+ [key: string]: unknown
+ }[]
+ [key: string]: unknown
}
+ owner?: string
visible: 'PUBLIC' | 'PRIVATE'
allowComment: boolean
approved: boolean
@@ -285,6 +309,13 @@ export interface IMoment {
tags?: string[]
releaseTime?: string
}
+ /** 互动数据(公开接口返回:点赞/评论数) */
+ stats?: {
+ approvedComment?: number
+ totalComment?: number
+ upvote?: number
+ [key: string]: unknown
+ }
status?: {
permalink: string
approved?: boolean
diff --git a/src/api/types/uni-halo.ts b/src/api/types/uni-halo.ts
index cf7656b..159fef3 100644
--- a/src/api/types/uni-halo.ts
+++ b/src/api/types/uni-halo.ts
@@ -77,10 +77,6 @@ export interface IPageConfig {
/** 审计模式配置 */
export interface IAuditConfig {
auditModeEnabled?: boolean
- auditModeData?: {
- jsonUrl?: string
- jsonData?: string
- }
}
/** 审核模式数据(公开接口 GET /audit-data 返回) */
@@ -119,6 +115,15 @@ export interface IAppConfig {
pluginConfig?: IPluginConfig
pageConfig?: IPageConfig
auditConfig?: IAuditConfig
+ /**
+ * 站点级展示偏好默认(L0,插件端 GeneralConfig.preferences 经 getConfigs additive 下发;
+ * 客户端 layout.home/cardType/isAvatarRadius 的站点默认来源,本地偏好可覆盖)
+ */
+ preferences?: {
+ homeListLayout?: string
+ articleCardType?: string
+ avatarRadius?: boolean
+ }
[key: string]: unknown
}
@@ -139,10 +144,6 @@ export interface IQRCodeInfo {
[key: string]: unknown
}
-export interface IQRCodeImg {
- [key: string]: unknown
-}
-
/** 检查更新结果(uhalo-upgrade 对接) */
export interface IUpdateCheckRes {
code: number
diff --git a/src/api/uni-halo.ts b/src/api/uni-halo.ts
index bbeee8b..ef99dfd 100644
--- a/src/api/uni-halo.ts
+++ b/src/api/uni-halo.ts
@@ -124,15 +124,6 @@ export function getQRCodeInfo(key: string) {
})
}
-/**
- * 获取文章二维码图片
- */
-export function getQRCodeImg(postId: string) {
- return http.Get>(`/apis/api.unihalo.ialley.cn/v1alpha1/plugins/plugin-uni-halo/getQRCodeImg/${postId}`, {
- meta: { requestFrom: RequestFrom.Halo },
- })
-}
-
/* ==================== 恋爱模块 ==================== */
/**
diff --git a/src/components/uh-article-card/uh-article-card.vue b/src/components/uh-article-card/uh-article-card.vue
index a0b6d76..abfd507 100644
--- a/src/components/uh-article-card/uh-article-card.vue
+++ b/src/components/uh-article-card/uh-article-card.vue
@@ -1,12 +1,8 @@
-
-
-
-
-
-
- 置顶
- {{ article.spec.title }}
+
+
+ 置顶
+
+
+
+ {{ article.spec.title }}
-
+
{{ article.status?.excerpt }}
-
-
-
diff --git a/src/components/uh-category-mini-card/uh-category-mini-card.vue b/src/components/uh-category-mini-card/uh-category-mini-card.vue
deleted file mode 100644
index b134f61..0000000
--- a/src/components/uh-category-mini-card/uh-category-mini-card.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
-
-
- {{ category.spec.displayName }}
-
- 共 {{ category.postCount ?? 0 }} 篇
-
-
-
-
-
diff --git a/src/components/uh-comment-item/uh-comment-item.vue b/src/components/uh-comment-item/uh-comment-item.vue
index f7e5659..7786acc 100644
--- a/src/components/uh-comment-item/uh-comment-item.vue
+++ b/src/components/uh-comment-item/uh-comment-item.vue
@@ -1,157 +1,95 @@
-
-
-
-
+
+
+
+
+
+
+ {{ comment.spec.owner.displayName }}
+
+
+
+ {{ createTimeText }}
+
+
+ 回复
+
+
+ 复制
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-comment-list/uh-comment-list.vue b/src/components/uh-comment-list/uh-comment-list.vue
index ca1638b..ae2bfeb 100644
--- a/src/components/uh-comment-list/uh-comment-list.vue
+++ b/src/components/uh-comment-list/uh-comment-list.vue
@@ -1,206 +1,176 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-home-banner - 副本/uh-home-banner.vue b/src/components/uh-home-banner - 副本/uh-home-banner.vue
new file mode 100644
index 0000000..1988987
--- /dev/null
+++ b/src/components/uh-home-banner - 副本/uh-home-banner.vue
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ dateParts.day }}
+
+
+
+
+ {{ dateParts.monthEn }}
+
+ {{ dateParts.year }}
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+ {{ currentItem.authorName }}
+
+
+ {{ authorDateText }}
+
+
+
+ {{ currentTitle }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-home-banner/uh-home-banner.vue b/src/components/uh-home-banner/uh-home-banner.vue
new file mode 100644
index 0000000..80b0ebf
--- /dev/null
+++ b/src/components/uh-home-banner/uh-home-banner.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentBanner.title }}
+
+ {{ currentBanner.date }}
+
+
+
+
+
+
+
+ 哈喽,想看些什么 { 内容 } 呢~
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-home-category/uh-home-category.vue b/src/components/uh-home-category/uh-home-category.vue
new file mode 100644
index 0000000..69ad8d1
--- /dev/null
+++ b/src/components/uh-home-category/uh-home-category.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+ 精选分类
+
+
+
+
+
+
+
+
+
+ 还没有任何分类~
+
+
+
+
+
+
+
+ {{ category.spec.displayName }}
+
+ 共 {{ category.postCount ?? 0 }} 篇
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-home-quick-nav/uh-home-quick-nav.vue b/src/components/uh-home-quick-nav/uh-home-quick-nav.vue
new file mode 100644
index 0000000..5a10646
--- /dev/null
+++ b/src/components/uh-home-quick-nav/uh-home-quick-nav.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+ 快捷导航
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-navbar/uh-navbar.vue b/src/components/uh-navbar/uh-navbar.vue
new file mode 100644
index 0000000..0130bb1
--- /dev/null
+++ b/src/components/uh-navbar/uh-navbar.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+ 返回
+
+
+
+
+ {{visibleTitle}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-scroll-top/uh-scroll-top.vue b/src/components/uh-scroll-top/uh-scroll-top.vue
new file mode 100644
index 0000000..8306e6c
--- /dev/null
+++ b/src/components/uh-scroll-top/uh-scroll-top.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-section-title/uh-section-title.vue b/src/components/uh-section-title/uh-section-title.vue
new file mode 100644
index 0000000..eb23017
--- /dev/null
+++ b/src/components/uh-section-title/uh-section-title.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/uh-swiper/uh-swiper.vue b/src/components/uh-swiper/uh-swiper.vue
deleted file mode 100644
index 7a031ac..0000000
--- a/src/components/uh-swiper/uh-swiper.vue
+++ /dev/null
@@ -1,421 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ dateParts.day }}
-
-
-
-
- {{ dateParts.monthEn }}
- {{ dateParts.year }}
-
-
-
- {{ title }}
-
-
-
-
-
-
-
-
-
-
- {{ currentItem.authorName }}
- {{ authorDateText }}
-
-
- {{ currentTitle }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/config/appConfig.ts b/src/config/appConfig.ts
index d665a2f..8332e78 100644
--- a/src/config/appConfig.ts
+++ b/src/config/appConfig.ts
@@ -45,9 +45,5 @@ export const DefaultAppConfigs: IAppConfig = {
},
auditConfig: {
auditModeEnabled: false,
- auditModeData: {
- jsonUrl: '',
- jsonData: '',
- },
},
}
diff --git a/src/config/appSettings.ts b/src/config/appSettings.ts
index af06aa2..4ce32f8 100644
--- a/src/config/appSettings.ts
+++ b/src/config/appSettings.ts
@@ -3,8 +3,6 @@
*/
export interface IAppSettings {
- /** 是否每次启动都显示启动页 */
- showStartPage: boolean
/** 评论头像是否圆形 */
isAvatarRadius: boolean
banner: {
@@ -25,12 +23,6 @@ export interface IAppSettings {
/** 是否屏蔽广告 */
disabled: boolean
}
- /** 评论弹幕(文章详情) */
- barrage: {
- use: boolean
- /** 弹幕位置(rightToLeft / leftBottom) */
- type: string
- }
gallery: {
/** 是否使用瀑布流 */
useWaterfull: boolean
@@ -55,7 +47,6 @@ export interface IAppSettings {
}
export const DefaultAppSettings: IAppSettings = {
- showStartPage: false,
isAvatarRadius: false,
banner: {
useDot: true,
@@ -69,10 +60,6 @@ export const DefaultAppSettings: IAppSettings = {
timeout: 3,
disabled: false,
},
- barrage: {
- use: false,
- type: 'leftBottom',
- },
gallery: {
useWaterfull: true,
},
diff --git a/src/config/markdown.ts b/src/config/markdown.ts
index a92afb8..5985a22 100644
--- a/src/config/markdown.ts
+++ b/src/config/markdown.ts
@@ -5,6 +5,8 @@
*/
import { checkImageUrl } from '@/utils/url'
+const primaryColor = '#B9E424'
+
export const markdownConfig = {
/** 图片域名前缀(mp-html 相对路径补全,源自旧配置 domain: BASE_API) */
domain: import.meta.env.VITE_SERVER_BASEURL || '',
@@ -34,52 +36,55 @@ export const markdownConfig = {
blockquote: `
padding: 8px 15px;
color: #606266;
- background: #f2f6fc;
- border-left: 5px solid #50bfff;
+ background-color: rgb(255 255 255 / 55%);
+ backdrop-filter: blur(24rpx) saturate(160%);
+ -webkit-backdrop-filter: blur(24rpx) saturate(160%);
+ border-left: 5px solid ${primaryColor};
border-radius: 4px;
line-height: 26px;
margin-bottom: 18px;
+ box-shadow: 0 0px 12px rgba(0, 0, 0, 0.035);
`,
ul: 'padding-left: 15px;line-height: 1.85;',
ol: 'padding-left: 15px;line-height: 1.85;',
li: 'margin-bottom: 12px;line-height: 1.85;',
h1: `
margin: 30px 0 20px;
- color: var(--main);
+ color: ${primaryColor};
line-height: 24px;
position: relative;
font-size:1.2em;
`,
h2: `
- color: var(--main);
+ color: ${primaryColor};
line-height: 24px;
position: relative;
margin: 22px 0 16px;
font-size: 1.16em;
`,
h3: `
- color: var(--main);
+ color: ${primaryColor};
line-height: 24px;
position: relative;
margin: 26px 0 18px;
font-size: 1.14em;
`,
h4: `
- color: var(--main);
+ color: ${primaryColor};
line-height: 24px;
margin-bottom: 18px;
position: relative;
font-size: 1.12em;
`,
h5: `
- color: var(--main);
+ color: ${primaryColor};
line-height: 24px;
margin-bottom: 14px;
position: relative;
font-size: 1.1em;
`,
h6: `
- color: #303133;
+ color: ${primaryColor};
line-height: 24px;
margin-bottom: 14px;
position: relative;
@@ -95,7 +100,7 @@ export const markdownConfig = {
video: 'width: 100%',
},
/** 容器样式 */
- containStyle: 'font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;padding:12px;font-size: 14px;color: #606266;word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 6px;background-color:#FFFFFF;',
+ containStyle: 'font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;padding:12px;font-size: 14px;color: #606266;word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 0px;background-color:transparent;',
/** 加载图 / 空图(来自应用配置 imagesConfig) */
loadingGif: checkImageUrl(undefined),
emptyGif: checkImageUrl(undefined),
diff --git a/src/hooks/useDataLoadingStatus.ts b/src/hooks/useDataLoadingStatus.ts
index eccfee2..ff5f8c5 100644
--- a/src/hooks/useDataLoadingStatus.ts
+++ b/src/hooks/useDataLoadingStatus.ts
@@ -5,8 +5,8 @@ export enum DataLoadingStatusEnum {
Success = 'success',
}
-export function useDataLoadingStatus() {
- const loadingStatus = ref(DataLoadingStatusEnum.Loading)
+export function useDataLoadingStatus(status?:DataLoadingStatusEnum) {
+ const loadingStatus = ref(status??DataLoadingStatusEnum.Loading)
function resetLoadingStatus() {
loadingStatus.value = DataLoadingStatusEnum.Loading
diff --git a/src/http/interceptor.ts b/src/http/interceptor.ts
index 9ec7d3f..1e39b23 100644
--- a/src/http/interceptor.ts
+++ b/src/http/interceptor.ts
@@ -2,7 +2,6 @@ import type { CustomRequestOptions } from '@/http/types';
import { useTokenStore } from '@/store';
import { getEnvBaseUrl } from '@/utils';
import { stringifyQuery } from './tools/queryString';
-import qs from 'qs';
// 请求基准地址
const baseUrl = getEnvBaseUrl();
diff --git a/src/http/types.ts b/src/http/types.ts
index 7096c34..690044a 100644
--- a/src/http/types.ts
+++ b/src/http/types.ts
@@ -3,7 +3,6 @@
*/
export type CustomRequestOptions = UniApp.RequestOptions & {
query?: Record
- params?: Record
/** 出错时是否隐藏错误提示 */
hideErrorToast?: boolean
} & IUniUploadFileOptions // 添加uni.uploadFile参数类型
diff --git a/src/pages-blog/article-detail/article-detail.vue b/src/pages-blog/article-detail/article-detail.vue
index 9669270..661d2ce 100644
--- a/src/pages-blog/article-detail/article-detail.vue
+++ b/src/pages-blog/article-detail/article-detail.vue
@@ -1,740 +1,626 @@
-
-
-
-
-
+
+
+
-
-
-
-
- {{ result?.spec.title }}
-
-
-
- 作者:{{ result?.owner?.displayName || bloggerInfo.nickname }}
- 时间:{{ formatPublishTime(result?.spec.publishTime) }}
-
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
- {{ result?.stats?.visit ?? 0 }}
- 阅读
-
-
- {{ result?.stats?.upvote ?? 0 }}
- 喜欢
-
-
- {{ result?.stats?.comment ?? 0 }}
- 评论
-
-
- {{ result?.content?.raw.length || 0 }}
- 字数
-
-
-
-
+
+
+
+
+
+ {{ result?.owner?.displayName }}
+
+
+ {{ result?.spec.title }}
+
+
+
+ {{ item.spec.displayName }}
+
+
+ #{{ item.spec.displayName }}
+
+
-
-
-
- 分类:
-
- 未选择分类
-
-
-
- {{ item.spec.displayName }}
-
-
-
-
- 标签:
-
- 未选择标签
-
-
-
- {{ item.spec.displayName }}
-
-
-
-
-
- 原文:
-
-
-
- {{ originalURL }}
-
-
- 阅读原文
-
-
-
-
+
+
+ 原文
+
+ {{originalURL}}
+
+
+
+ 日期
+ {{ formatPublishTime(result?.spec.publishTime) }}
+
+
+
+ 阅读
+ {{ result?.stats?.visit ?? 0 }}
+
+
+ 喜欢
+ {{ result?.stats?.upvote ?? 0 }}
+
+
+ 评论
+ {{ result?.stats?.comment ?? 0 }}
+
+
+ 字数
+ {{ result?.content?.raw.length || 0 }}
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- 版权声明
-
-
-
- 版权归属:{{ postDetailConfig.copyrightAuthor }}
-
-
- 版权说明:{{ postDetailConfig.copyrightDesc }}
-
-
- 侵权处理:{{ postDetailConfig.copyrightViolation }}
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+ 版权声明
+
+
+ 版权归属:{{ postDetailConfig.copyrightAuthor }}
+
+
+ 版权说明:{{ postDetailConfig.copyrightDesc }}
+
+
+ 侵权处理:{{ postDetailConfig.copyrightViolation }}
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+ 点赞
+
+
+
+ 评论
+
+
+
+ 收藏
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/src/pages-blog/moment-detail/moment-detail.vue b/src/pages-blog/moment-detail/moment-detail.vue
index af217d1..7821709 100644
--- a/src/pages-blog/moment-detail/moment-detail.vue
+++ b/src/pages-blog/moment-detail/moment-detail.vue
@@ -35,7 +35,11 @@ const bloggerInfo = computed(() => {
const calcUseTagRandomColor = computed(() => !!haloConfigs.value.pageConfig?.momentConfig?.useTagRandomColor)
-const startConfig = computed(() => haloConfigs.value.appConfig?.startConfig as { title?: string } | undefined)
+/** 站点名称(原 startConfig.title 已随启动页下线,改读 appConfig.appInfo.name) */
+const siteName = computed(() => {
+ const appInfo = haloConfigs.value.appConfig?.appInfo as { name?: string } | undefined
+ return appInfo?.name || bloggerInfo.value.nickname || 'uni-halo'
+})
/* ---------------- 状态 ---------------- */
const loading = ref<'loading' | 'success' | 'error'>('loading')
@@ -73,16 +77,18 @@ async function handleGetData() {
const res = await getMomentByName(queryName.value)
uni.setNavigationBarTitle({ title: '瞬间详情' })
- const medium = (res.data.spec as unknown as { medium?: { type?: string, url: string }[] }).medium || []
+ const medium = (res.data.spec.content?.medium || [])
+ .map(x => ({ ...x, url: x.url || '' }))
+ const owner = res.data.owner
const tempResult = {
...res.data,
+ // 无顶层 owner(如个别历史接口)时兜底为博主信息
+ owner: owner?.displayName
+ ? owner
+ : { displayName: bloggerInfo.value.nickname || '', name: bloggerInfo.value.nickname || '', avatar: bloggerInfo.value.avatar },
spec: {
...res.data.spec,
- owner: {
- displayName: bloggerInfo.value.nickname,
- avatar: bloggerInfo.value.avatar,
- },
- newHtml: removeTagLinksCompletely((res.data.spec as unknown as { content?: { html?: string } }).content?.html || ''),
+ newHtml: removeTagLinksCompletely(res.data.spec.content?.html || ''),
},
images: medium.filter(x => x.type === 'PHOTO').map(x => ({ ...x, url: checkThumbnailUrl(x.url, true) })),
videos: medium.filter(x => x.type === 'VIDEO').map(x => ({ ...x, id: generateUUID() })),
@@ -170,11 +176,11 @@ onPullDownRefresh(() => {
onShareAppMessage(() => ({
path: `/pages-blog/moment-detail/moment-detail?name=${moment.value?.metadata.name}`,
- title: moment.value?.spec.owner?.displayName || '',
+ title: moment.value?.owner?.displayName || '',
}))
onShareTimeline(() => ({
- title: moment.value?.spec.owner?.displayName || '',
+ title: moment.value?.owner?.displayName || '',
query: moment.value ? `name=${moment.value.metadata.name}` : '',
}))
@@ -189,14 +195,25 @@ onShareTimeline(() => ({
-
+
- {{ moment.spec.owner?.displayName || bloggerInfo.nickname }}
+ {{ moment.owner?.displayName || bloggerInfo.nickname }}
{{ formatTime(moment.spec.releaseTime) }}
+
+
+
+
+ {{ moment.stats.upvote || 0 }}
+
+
+
+ {{ moment.stats.totalComment || 0 }}
+
+
@@ -255,7 +272,7 @@ onShareTimeline(() => ({
:key="audio.url"
:src="audio.url"
:poster="bloggerInfo.avatar"
- :name="`来自${startConfig?.title || bloggerInfo.nickname}的声音`"
+ :name="`来自${siteName}的声音`"
:author="bloggerInfo.nickname"
/>
diff --git a/src/pages-blog/setting/setting.vue b/src/pages-blog/setting/setting.vue
index 443ba51..42bbf5a 100644
--- a/src/pages-blog/setting/setting.vue
+++ b/src/pages-blog/setting/setting.vue
@@ -1,260 +1,338 @@
-
-
-
-
-
- 布局
- 应用以及文章列表布局设置
-
-
-
-
- 首页文章布局
-
- {{ homeLayout.selectLabel }}
-
-
+
+
+
+
+ 你的偏好仅保存在本机。未自定义的项自动跟随站长在插件后台配置的「站点默认」;点击底部「重置为站点默认」可清空全部本地偏好。
+
+
+
+
+
+
+ 布局
+ 应用以及文章列表布局设置
+
+
+
+
+ {{ def.label }}
+ 跟随站点默认
+ 已自定义
-
-
- 文章卡片样式
-
- {{ articleCardStyle.selectLabel }}
-
-
+
+ {{ enumLabelOf(def, valueOf(def.path)) }}
+
+
-
-
-
- 功能
- 一些常用的功能性设置
-
-
-
- 图库瀑布流模式
-
-
-
- 友链简洁模式
-
-
-
- 是否圆形头像
-
-
-
- 轮播图指示器
-
-
-
-
- 指示器位置
-
-
- {{ item.name }}
+
+
+
+ 功能
+ 一些常用的功能性设置
+
+
+
+
+
+
+ {{ def.label }}
+
+ 跟随站点默认
+ 已自定义
+ 跟随默认
+
-
+
+
+
+ {{ def.label }}
+
+ 跟随站点默认
+ 已自定义
+ 跟随默认
+
+
+
+ {{ enumLabelOf(def, valueOf(def.path)) }}
+
+
+
+
-
-
- 保存设置
-
-
- 恢复默认设置
-
-
- 返回
+
+
+ 重置为站点默认
+
+
+
+
+
+ {{ enumSheet.def.label }}
+
+
+ 跟随站点默认
+
+
+
+ {{ opt.label }}
+
+
+
+
diff --git a/src/pages/tabbar/about/about.vue b/src/pages/tabbar/about/about.vue
index 521675c..2896028 100644
--- a/src/pages/tabbar/about/about.vue
+++ b/src/pages/tabbar/about/about.vue
@@ -159,6 +159,15 @@ async function handleGetNavList() {
path: '/pages-blog/about/about',
show: !!basicConfig.value?.showAboutSystem,
},
+ {
+ key: 'setting',
+ title: '偏好设置',
+ icon: 'settings',
+ iconColor: '#03a9f4',
+ rightText: '首页布局、卡片样式等本地偏好',
+ path: '/pages-blog/setting/setting',
+ show: true,
+ },
]
}
diff --git a/src/pages/tabbar/category/category.vue b/src/pages/tabbar/category/category.vue
index 2a3728f..e57f189 100644
--- a/src/pages/tabbar/category/category.vue
+++ b/src/pages/tabbar/category/category.vue
@@ -1,384 +1,183 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
- {{ item.spec.displayName }}
-
-
- 共 {{ item.postCount }} 篇文章
-
-
-
-
- {{ loadMoreText }}
-
-
-
-
-
-
-
- {{ item.spec.displayName }}
-
-
-
-
-
-
-
-
-
-
- {{ loadMoreText }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ item.spec.displayName }}
+
+
+ 共 {{ item.postCount }} 篇文章
+
+
+
+
+
+ {{ loadMoreText }}
+
+
+
-
-
diff --git a/src/pages/tabbar/gallery/gallery.vue b/src/pages/tabbar/gallery/gallery.vue
index 697ea0c..f0f41bb 100644
--- a/src/pages/tabbar/gallery/gallery.vue
+++ b/src/pages/tabbar/gallery/gallery.vue
@@ -1,292 +1,250 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {{ cate.spec.displayName }}({{cate.status?.photoCount??0}})
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
- 刷新试试
-
-
+
+
+
+
+ 刷新试试
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ loadMoreText }}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ loadMoreText }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/tabbar/home/home.vue b/src/pages/tabbar/home/home.vue
index b11b461..284f6a5 100644
--- a/src/pages/tabbar/home/home.vue
+++ b/src/pages/tabbar/home/home.vue
@@ -1,419 +1,228 @@
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
-
-
-
- 快捷导航
-
-
-
-
-
-
-
-
- {{ item.title }}
-
-
-
-
-
+
+
-
-
-
-
- 精选分类
-
-
-
-
-
-
-
- 还没有任何分类~
-
-
-
-
-
-
-
-
-
-
- 最新列表
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ loadMoreText }}
-
-
-
-
-
-
-
-
+
+
+ 最新内容
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ loadMoreText }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/tabbar/moments/moments.vue b/src/pages/tabbar/moments/moments.vue
index e89d88c..5f57c3e 100644
--- a/src/pages/tabbar/moments/moments.vue
+++ b/src/pages/tabbar/moments/moments.vue
@@ -20,6 +20,8 @@ definePage({
style: {
navigationBarTitleText: '瞬间',
enablePullDownRefresh: true,
+ // 玻璃拟态试验:下拉/回弹露出的窗口底色对齐壁纸底部色调
+ backgroundColor: '#f4efff',
},
})
@@ -36,7 +38,11 @@ const bloggerInfo = computed(() => {
}
})
-const startConfig = computed(() => haloConfigs.value.appConfig?.startConfig as { title?: string } | undefined)
+/** 站点名称(原 startConfig.title 已随启动页下线,改读 appConfig.appInfo.name) */
+const siteName = computed(() => {
+ const appInfo = haloConfigs.value.appConfig?.appInfo as { name?: string } | undefined
+ return appInfo?.name || bloggerInfo.value.nickname || 'uni-halo'
+})
/** 依赖插件(plugin-moments) */
const uniHaloPluginId = 'plugin-moments'
@@ -46,7 +52,14 @@ const uniHaloPluginAvailable = ref(true)
const loading = ref<'loading' | 'success' | 'error'>('loading')
const queryParams = ref({ size: 10, page: 1 })
const hasNext = ref(false)
-const dataList = ref<(IMoment & { images?: { type?: string, url: string }[], videos?: { id?: string, url: string }[], audios?: { type?: string, url: string }[], spec: { newHtml?: string } })[]>([])
+/** 列表卡片:medium 已按类型拆为 images/videos/audios + 正文 tag 清理 */
+type MomentCard = IMoment & {
+ images?: { type?: string, url: string }[]
+ videos?: { id?: string, url: string }[]
+ audios?: { type?: string, url: string }[]
+ spec: IMoment['spec'] & { newHtml?: string }
+}
+const dataList = ref([])
const isLoadMore = ref(false)
const loadMoreText = ref(t('common.loading'))
const videoContexts = ref>({})
@@ -58,18 +71,20 @@ function removeTagLinksCompletely(htmlString: string): string {
return htmlString.replace(regex, '')
}
-/** 瞬间项映射(medium 拆分为 images/videos/audios + 内容 tag 清理) */
-function mapMomentItem(item: IMoment) {
- const medium = (item.spec as unknown as { medium?: { type?: string, url: string }[] }).medium || []
+/** 瞬间项映射(spec.content.medium 拆分为 images/videos/audios + 内容 tag 清理 + 作者兜底) */
+function mapMomentItem(item: IMoment): MomentCard {
+ const medium = (item.spec.content?.medium || [])
+ .map(x => ({ ...x, url: x.url || '' }))
+ const owner = item.owner
return {
...item,
+ // 无顶层 owner(如个别历史接口)时兜底为博主信息
+ owner: owner?.displayName
+ ? owner
+ : { displayName: bloggerInfo.value.nickname || '', name: bloggerInfo.value.nickname || '', avatar: bloggerInfo.value.avatar },
spec: {
...item.spec,
- owner: {
- displayName: bloggerInfo.value.nickname,
- avatar: bloggerInfo.value.avatar,
- },
- newHtml: removeTagLinksCompletely((item.spec as unknown as { content?: { html?: string } }).content?.html || ''),
+ newHtml: removeTagLinksCompletely(item.spec.content?.html || ''),
},
images: medium.filter(x => x.type === 'PHOTO').map(x => ({ ...x, url: checkThumbnailUrl(x.url, true) })),
videos: medium.filter(x => x.type === 'VIDEO').map(x => ({ ...x, id: generateUUID() })),
@@ -251,7 +266,15 @@ onReachBottom(() => {
-
+
+
+
+
+
+
+
+
+
{
-
+
-
-
+
+
-
+
- {{ moment.spec.owner?.displayName || bloggerInfo.nickname }}
+ {{ moment.owner?.displayName || bloggerInfo.nickname }}
{{ formatMomentTime(moment.spec.releaseTime) }}
@@ -320,7 +343,7 @@ onReachBottom(() => {
:key="audio.url"
:src="audio.url"
:poster="bloggerInfo.avatar"
- :name="`来自${startConfig?.title || bloggerInfo.nickname}的声音`"
+ :name="`来自${siteName}的声音`"
:author="bloggerInfo.nickname"
/>
@@ -349,9 +372,21 @@ onReachBottom(() => {
{{ tag }}
+
+
+
+
+
+ {{ moment.stats.upvote || 0 }}
+
+
+
+ {{ moment.stats.totalComment || 0 }}
+
+
-
+
@@ -362,3 +397,99 @@ onReachBottom(() => {
+
+
diff --git a/src/store/appConfig.ts b/src/store/appConfig.ts
index 6b65d0a..3a919e3 100644
--- a/src/store/appConfig.ts
+++ b/src/store/appConfig.ts
@@ -12,6 +12,8 @@ import type { IAppConfig, IAuditDataResult } from '@/api/types/uni-halo'
/** 个人令牌存储 key(与 src/store/token.ts 的 getPersonalToken 保持一致) */
const APP_TOKENS_KEY = 'APP_TOKENS'
+/** 合并后配置缓存 key(与 utils/url.ts / api/uni-halo.ts 的 APP_GLOBAL_CONFIGS 读取保持一致) */
+const APP_GLOBAL_CONFIGS_KEY = 'APP_GLOBAL_CONFIGS'
export const useAppConfigStore = defineStore(
'appConfig',
@@ -36,6 +38,10 @@ export const useAppConfigStore = defineStore(
if (body) {
configs.value = deepMerge(JSON.parse(JSON.stringify(DefaultAppConfigs)), body)
+ // 合并结果写入 APP_GLOBAL_CONFIGS 缓存,供 utils/url.ts 图片兜底与
+ // api/uni-halo.ts 第三方插件授权头等按 storage 路径读取
+ setCache(APP_GLOBAL_CONFIGS_KEY, configs.value)
+
// 存储个人令牌(供 getPersonalToken 使用,如非匿名投票)
if (body?.basicConfig?.tokenConfig) {
setCache(APP_TOKENS_KEY, body.basicConfig.tokenConfig)
diff --git a/src/store/setting.ts b/src/store/setting.ts
index 7d613ec..3b434c5 100644
--- a/src/store/setting.ts
+++ b/src/store/setting.ts
@@ -1,23 +1,68 @@
/**
- * 应用设置 store(源自旧项目 store/setting.js)
+ * 应用设置 store(两层偏好:站点默认 L0 + 本地差异 L1-L)
+ *
+ * - settings:合并结果缓存(= L0 站点默认 + 本地差异,本地优先),persist 持久化供离线兜底;
+ * - applySiteDefaults(site):启动 fetchConfigs 后把 getConfigs 收集的 L0 与本地差异合并(含旧数据迁移);
+ * - savePreference(patch):写本地差异(uh_pref_local_v1)并立即重合并;
+ * - resetPreferences:清本地差异,立即回退「站点默认」(无 L0 时回退内置默认)。
+ *
+ * 设计依据:插件仓库 .docs/config-system-v2-redesign.md §3-4(v2.2:远端=站点默认,无用户级远端层)。
*/
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { DefaultAppSettings } from '@/config/appSettings'
import type { IAppSettings } from '@/config/appSettings'
+import {
+ clearLocalPrefs,
+ mergeWithDefaults,
+ migrateLegacyLocalPrefs,
+ readLocalPrefs,
+ updateLocalPrefs,
+} from '@/utils/preference'
+import type { LocalPrefs } from '@/utils/preference'
export const useSettingStore = defineStore(
'setting',
() => {
+ /** 合并结果缓存(站点默认 + 本地差异;页面消费点不变) */
const settings = ref(JSON.parse(JSON.stringify(DefaultAppSettings)))
+ /** 最近一次站点默认(L0,collectSiteDefaults 结果),非持久化 */
+ const siteDefaults = ref(null)
- /** 重置为默认设置 */
- const updateDefaultAppSettings = () => {
- settings.value = JSON.parse(JSON.stringify(DefaultAppSettings))
+ /** 重算合并结果(统一出口:写 settings 缓存) */
+ function recompute(): void {
+ settings.value = mergeWithDefaults(siteDefaults.value, readLocalPrefs())
+ }
+
+ /**
+ * 应用站点默认并合并本地差异(启动 fetchConfigs 成功后调用;site 为 null/空时仅本地差异覆盖内置默认)
+ * 首次运行时顺带迁移旧版全量 persist(见 utils/preference.migrateLegacyLocalPrefs)
+ */
+ const applySiteDefaults = (site: LocalPrefs | null): void => {
+ siteDefaults.value = site && typeof site === 'object' ? site : null
+ migrateLegacyLocalPrefs()
+ recompute()
+ }
+
+ /** 保存偏好:写本地差异并立即重合并(改偏好即时生效) */
+ const savePreference = (patch: LocalPrefs): void => {
+ updateLocalPrefs(patch)
+ recompute()
+ }
+
+ /** 重置为站点默认:清本地差异(重置=删除本地,回退 getConfigs 下发值) */
+ const resetPreferences = (): void => {
+ clearLocalPrefs()
+ recompute()
+ }
+
+ /** 兼容旧调用点:恢复默认(新语义=重置回站点默认) */
+ const updateDefaultAppSettings = (): void => {
+ resetPreferences()
}
/** 检查并设置默认设置(启动时调用,persist 已保证有值,兜底处理) */
- const checkAndSetDefaultAppSettings = () => {
+ const checkAndSetDefaultAppSettings = (): void => {
if (!settings.value) {
settings.value = JSON.parse(JSON.stringify(DefaultAppSettings))
}
@@ -25,6 +70,10 @@ export const useSettingStore = defineStore(
return {
settings,
+ siteDefaults,
+ applySiteDefaults,
+ savePreference,
+ resetPreferences,
updateDefaultAppSettings,
checkAndSetDefaultAppSettings,
}
diff --git a/src/style/index.scss b/src/style/index.scss
index 1ee7de9..bf44221 100644
--- a/src/style/index.scss
+++ b/src/style/index.scss
@@ -1,21 +1,34 @@
// 测试用的 iconfont,可生效
-// @import './iconfont.css';
-
-.test {
- // 可以通过 @apply 多个样式封装整体样式
- @apply mt-4 ml-4;
-
- padding-top: 4px;
- color: red;
-}
+@import './iconfont.css';
:root,
page {
- // 修改按主题色
- // --wot-color-theme: #37c2bc;
+ // 修改按主题色
+ --wot-color-theme: #B9E424;
- // 修改按钮背景色
- // --wot-button-primary-bg-color: green;
+ // 修改按钮背景色
+ --wot-button-primary-bg-color: #B9E424;
+}
+
+.uh-global-page {
+}
+
+.uh-global-card-glass {
+ box-sizing: border-box;
+ background-color: rgb(255 255 255 / 55%);
+ border: 4rpx solid rgb(255 255 255 / 65%);
+ box-shadow: inset 0 1rpx 0 rgb(255 255 255 / 75%), 0 8rpx 32rpx rgb(90 105 200 / 14%);
+ backdrop-filter: blur(24rpx) saturate(160%);
+ -webkit-backdrop-filter: blur(24rpx) saturate(160%);
+
+ /* 低端安卓 WebView 不支持 backdrop-filter 的兜底:提高不透明度保证可读性 */
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
+ background-color: rgb(255 255 255 / 88%);
+ }
+}
+
+.uh-shadow-xs {
+ box-shadow: inset 0 1rpx 0 rgb(255 255 255 / 75%), 0 8rpx 32rpx rgb(90 105 200 / 7%);
}
/*
diff --git a/src/style/uni-components/audio.css b/src/style/uni-components/audio.css
deleted file mode 100644
index 0579b65..0000000
--- a/src/style/uni-components/audio.css
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * audio 组件默认样式补件
- * 说明:@dcloudio/uni-components 3.0.0-4070620250821001 的 style/ 目录未提供 audio.css,
- * vite 编译