1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-09-11 16:00:44 +08:00

style,refactor,feat: 统一卡片布局为图片在上并优化细节

1. 调整全局默认卡片样式为image_top,更新各页面默认布局配置
2. 给文章卡片添加variant属性适配双列/单列布局
3. 优化文章内容区域文字样式与评论列表空状态
4. 简化快捷导航组件代码,移除冗余样式与多余props
5. 优化markdown渲染配置与评论头像空格格式
This commit is contained in:
小莫唐尼
2026-09-09 17:47:54 +08:00
parent b41e01106a
commit d528d214b5
9 changed files with 32 additions and 62 deletions
+6 -5
View File
@@ -43,9 +43,9 @@ layout: {
| 页面 | listLayout | cardType |
|------|-----------|----------|
| home(首页) | `single` | `image_bottom` |
| articles(文章列表) | `double` | `image_bottom` |
| archives(文章归档) | `single` | `image_bottom` |
| home(首页) | `single` | `image_top` |
| articles(文章列表) | `double` | `image_top` |
| archives(文章归档) | `single` | `image_top` |
## 3. 后端插件字段映射(getConfigs.preferences)
@@ -73,7 +73,7 @@ layout: {
| `src/pages/tabbar/home/home.vue` | `layout.home.listLayout` 决定容器单/双列;卡片 `from="home"``layout.home.cardType` |
| `src/pages-blog/articles/articles.vue` | `layout.articles.listLayout` 决定容器与 `variant`(grid/list);卡片 `from="articles"` |
| `src/pages-blog/archives/archives.vue` | `layout.archives.listLayout` 决定归档时间线内单/双列;卡片 `from="archives"` |
| `src/components/uh-article-card/uh-article-card.vue` | 按 `from` 读取对应页面 `cardType` 作为 layout;grid/双列窄列自动回退 `image_top`;非法值兜底 `image_bottom` |
| `src/components/uh-article-card/uh-article-card.vue` | 按 `from` 读取对应页面 `cardType` 作为 layout;grid/双列窄列自动回退 `image_top`;非法值兜底 `image_top` |
## 5. 设置页枚举(「默认」= 跟随站点默认)
@@ -85,5 +85,6 @@ layout: {
| 版本 | 变更 |
|------|------|
| v2.4 | 卡片样式值体系由旧 `lr_*/tb_*` 改为组件 layout 值 `image_top/image_right/image_bottom/image_left`;内置默认 cardType 统一为 `image_bottom`;移除 `uh-article-card` 旧值映射(`CARD_TYPE_TO_LAYOUT`),非法值兜底 `image_bottom` |
| v2.5 | 内置默认 cardType 统一为 `image_top`;组件非法值兜底同步为 `image_top` |
| v2.4 | 卡片样式值体系由旧 `lr_*/tb_*` 改为组件 layout 值 `image_top/image_right/image_bottom/image_left`;移除 `uh-article-card` 旧值映射(`CARD_TYPE_TO_LAYOUT`) |
| v2.3 | 布局偏好由全局 `layout.home` / `layout.cardType`(字符串)重构为按页面分组 `layout.{home,articles,archives}.{listLayout,cardType}`;设置页增加「布局 / 功能」分段器与页面分组设置项;三个消费页面联动卡片 |
@@ -117,7 +117,7 @@
return raw
})
const cardLayout = computed(() => CARD_LAYOUTS[effectiveLayout.value] ?? CARD_LAYOUTS.image_bottom)
const cardLayout = computed(() => CARD_LAYOUTS[effectiveLayout.value] ?? CARD_LAYOUTS.image_top)
/** 社交卡片形态(封面在下):左上用户信息(头像 + 昵称/日期垂直)、右上浏览数 */
const isSocialCard = computed(() => effectiveLayout.value === 'image_bottom')
@@ -183,7 +183,7 @@
</template>
</view>
<view class="flex items-center text-xs text-gray-500" :class="cardLayout.footer">
<view v-if="!isGrid" class="flex items-center" :class="cardLayout.authorGroup">
<view class="flex items-center" :class="cardLayout.authorGroup">
<image :src="article.owner.avatar" class="uh-global-card-glass h-5 w-5 rounded-full"
:class="cardLayout.avatar" mode="aspectFill" />
<template v-if="isSocialCard">
@@ -199,11 +199,11 @@
</view>
</view>
</template>
<text v-else class="truncate">{{ article.owner.displayName }}</text>
<text v-else class="min-w-0 flex-1 truncate">{{ article.owner.displayName }}</text>
</view>
<text v-if="!isGrid && !isSocialCard" class="text-gray-400"
:class="cardLayout.time">{{ publishTimeText }}</text>
<view v-if="!isSocialCard" class="visits flex items-center gap-x-1" :class="cardLayout.visits">
<view v-if="!isGrid && !isSocialCard" class="visits flex items-center gap-x-1" :class="cardLayout.visits">
浏览
<text class="number">{{ visitCount }}</text>
@@ -39,7 +39,7 @@
result.value = res.data
dataList.value = res.data.items.map((item) => {
// todo:临时
item.spec.owner.avatar = checkAvatarUrl(item.spec.owner.avatar??'https://api.dicebear.com/10.x/adventurer-neutral/svg')
item.spec.owner.avatar = checkAvatarUrl(item.spec.owner.avatar ?? 'https://api.dicebear.com/10.x/adventurer-neutral/svg')
return item
})
loading.value = 'success'
@@ -101,8 +101,7 @@
<uh-section-title>
评论列表
<template #right>
<view class="flex items-center gap-1.5 text-xs text-gray-500 font-normal"
@click="handleGetData">
<view class="flex items-center gap-1.5 text-xs text-gray-500 font-normal" @click="handleGetData">
<wd-icon name="refresh" size="28rpx" />
<text class="">刷新</text>
</view>
@@ -135,20 +134,15 @@
<view v-if="dataList.length === 0" class="empty py-12">
<view class="empty-box flex flex-col items-center">
<wd-empty>
<template #image>
<wd-icon name="empty" size="100rpx" class="text-primary" />
</template>
<template #bottom>
<text class="mt-2 text-sm text-gray-500">{{disallowComment ? '暂无评论' : '暂无评论'}}</text>
<view v-if="disallowComment" class="mt-2 text-xs text-red-400">
文章已开启禁止评论
</view>
<view v-else class="mt-2 bg-primary text-black text-sm px-4 py-1.5 rounded-lg" @click="handleToComment()">
抢沙发
</view>
</template>
</wd-empty>
<wd-icon class-prefix="uhemoji-icon" name="-confused" size="100rpx" class="text-primary" />
<text class="mt-2 text-sm text-gray-500">{{disallowComment ? '暂无评论' : '暂无评论'}}</text>
<view v-if="disallowComment" class="mt-2 text-xs text-red-400">
文章已开启禁止评论
</view>
<view v-else class="mt-2 bg-primary text-black text-sm px-4 py-1.5 rounded-lg"
@click="handleToComment()">
抢沙发
</view>
</view>
</view>
@@ -96,7 +96,7 @@
:style="{
backgroundColor: item.bgGlass
}">
<wd-icon :class-prefix="item.iconPrefix" :name="item.icon" size="64rpx" :color="item.color" />
<wd-icon :class-prefix="item.iconPrefix" :name="item.icon" size="64rpx"/>
</view>
<view class="text-xs text-gray-900">
{{ item.title }}
@@ -104,17 +104,4 @@
</view>
</view>
</view>
</template>
<style scoped lang="scss">
/* 彩色玻璃图标:低透明度同色底 + 同色描边 + 柔和同色投影,图标用实体色保证通透感 */
.quick-nav-icon {
backdrop-filter: blur(16rpx) saturate(160%);
-webkit-backdrop-filter: blur(16rpx) saturate(160%);
/* 低端安卓 WebView 不支持 backdrop-filter 的兜底:提高底色不透明度保证可读性 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
background-color: rgb(255 255 255 / 60%) !important;
}
}
</style>
</template>
+3 -3
View File
@@ -63,9 +63,9 @@ export const DefaultAppSettings: IAppSettings = {
dotPosition: 'right',
},
layout: {
home: { listLayout: 'single', cardType: 'image_bottom' },
articles: { listLayout: 'double', cardType: 'image_bottom' },
archives: { listLayout: 'single', cardType: 'image_bottom' },
home: { listLayout: 'single', cardType: 'image_top' },
articles: { listLayout: 'double', cardType: 'image_top' },
archives: { listLayout: 'single', cardType: 'image_top' },
},
ad: {
timeout: 3,
+3 -16
View File
@@ -1,16 +1,9 @@
/**
* mp-html 富文本 / markdown 渲染业务配置
* 源自旧项目 common/markdown/markdown.config.js,TS 化复刻(业务封装新建,插件本体走 npm mp-html)
* 用法:<mp-html :content="html" :tag-style="markdownConfig.tagStyle" :container-style="markdownConfig.containStyle" />
*/
import { checkImageUrl } from '@/utils/url'
const primaryColor = '#B9E424'
export const markdownConfig = {
/** 图片域名前缀(mp-html 相对路径补全,源自旧配置 domain: BASE_API) */
domain: import.meta.env.VITE_SERVER_BASEURL || '',
/** 标签样式定制(表格/引用/标题/代码等) */
tagStyle: {
table: `
table-layout: fixed;
@@ -25,13 +18,9 @@ export const markdownConfig = {
`,
th: `
padding: 8px;
border-right: 1px solid var(--classE);
border-bottom: 1px solid var(--classE);
`,
td: `
padding: 8px;
border-right: 1px solid var(--classE);
border-bottom: 1px solid var(--classE);
`,
blockquote: `
padding: 8px 15px;
@@ -66,7 +55,7 @@ export const markdownConfig = {
color: ${primaryColor};
line-height: 24px;
position: relative;
margin: 26px 0 18px;
margin: 20px 0 14px;
font-size: 1.14em;
`,
h4: `
@@ -93,15 +82,13 @@ export const markdownConfig = {
p: `
line-height: 1.65;
margin-bottom: 14px;
font-size: 14px;
`,
code: ' ',
strong: 'font-weight: 700;color: rgb(248, 57, 41);',
img: 'border-radius: 10px',
video: 'width: 100%',
},
/** 容器样式 */
containStyle: 'font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;padding:0;font-size: 14px;color: #606266;word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 0px;background-color:transparent;',
/** 加载图 / 空图(来自应用配置 imagesConfig) */
containStyle: 'padding:0;background-color:transparent;',
loadingGif: checkImageUrl(undefined),
emptyGif: checkImageUrl(undefined),
}
+1
View File
@@ -282,6 +282,7 @@ onReachBottom(() => {
v-for="post in item.posts"
:key="post.metadata.name"
from="archives"
:variant="archivesListLayout === 'double' ? 'grid' : 'list'"
:article="post"
:audit-mode="calcAuditModeEnabled"
/>
@@ -539,7 +539,7 @@
</view>
<!-- 内容区域 -->
<view class="box-border flex flex-col gap-y-3 p-3">
<view class="box-border flex flex-col gap-y-3 p-3 text-gray-900 text-sm">
<!-- 受限阅读 -->
<template v-if="checkPostRestrictRead(result!)">
<view v-if="showContentArr.length === 0">
+1 -1
View File
@@ -249,7 +249,7 @@
<view class="box-border p-3 pt-0"
:class="homeListLayout === 'double' ? 'grid grid-cols-2 gap-3' : 'flex flex-col gap-y-3'">
<uh-article-card v-for="(article, index) in articleList" :key="index" from="home" :article="article"
:audit-mode="calcAuditModeEnabled" />
:variant="homeListLayout === 'double' ? 'grid' : 'list'" :audit-mode="calcAuditModeEnabled" />
</view>
<view class="mt-3 box-border pb-5 text-center text-xs text-gray-400">
{{ loadMoreText }}