feat: ui update
This commit is contained in:
@@ -5,6 +5,7 @@ import { STORAGE_KEYS } from '../../utils/config'
|
||||
import { formatRelativeTime } from '../../utils/format'
|
||||
import { normalizePaged, mergePaged, hasMorePaged } from '../../utils/paged'
|
||||
import { getTabBarInstance } from '../../utils/tabbar'
|
||||
import { navScroll } from '../../utils/nav'
|
||||
import { logger } from '../../utils/logger'
|
||||
|
||||
// 日志模块名
|
||||
@@ -27,8 +28,13 @@ Page({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
hasMore: true,
|
||||
// 滚动收缩:由 utils/nav.ts 的共享 handler 驱动
|
||||
navScrolled: false,
|
||||
},
|
||||
|
||||
// scroll-view 滚动 → 导航收缩为玻璃小标题
|
||||
onNavScroll: navScroll,
|
||||
|
||||
onShow() {
|
||||
// 未登录直接回登录页(幂等跳转),不再发出必然 401 的请求
|
||||
if (!auth.isLoggedIn()) {
|
||||
|
||||
@@ -1,53 +1,64 @@
|
||||
<view class="page page-flex">
|
||||
<navigation-bar title="通知" />
|
||||
<navigation-bar title="通知" scrolled="{{navScrolled}}" />
|
||||
|
||||
<scroll-view
|
||||
scroll-y
|
||||
class="scroll-body"
|
||||
bindscrolltolower="onReachBottom"
|
||||
>
|
||||
<!-- 筛选 -->
|
||||
<scroll-view scroll-x class="filter-scroll" show-scrollbar="{{false}}">
|
||||
<view class="filter-row">
|
||||
<scroll-view scroll-y class="scroll-body" bindscrolltolower="onReachBottom" bindscroll="onNavScroll">
|
||||
<!-- 大标题页头 -->
|
||||
<view class="head">
|
||||
<view class="eyebrow">Notifications</view>
|
||||
<view class="display">通知</view>
|
||||
</view>
|
||||
|
||||
<!-- 下划线式筛选 -->
|
||||
<view class="segbar">
|
||||
<view class="seg">
|
||||
<view
|
||||
wx:for="{{filters}}"
|
||||
wx:key="name"
|
||||
class="filter-item {{activeFilter === index ? 'active' : ''}}"
|
||||
class="seg-item {{activeFilter === index ? 'is-on' : ''}}"
|
||||
data-index="{{index}}"
|
||||
bindtap="onFilterTap"
|
||||
>{{item.name}}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<view wx:if="{{loading}}" class="nt-skel">
|
||||
<view class="nt-skel-item" wx:for="{{[1, 2, 3]}}" wx:key="*this">
|
||||
<view class="sk sk-ln" style="width: 52%;"></view>
|
||||
<view class="sk sk-ln" style="width: 86%;"></view>
|
||||
<view class="sk sk-ln" style="width: 30%;"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空态 -->
|
||||
<empty-state
|
||||
wx:if="{{!loading && !list.length}}"
|
||||
wx:elif="{{!list.length}}"
|
||||
icon="icon-bell"
|
||||
title="还没有消息"
|
||||
desc="穿搭被点赞、订单动态都会出现在这里"
|
||||
/>
|
||||
|
||||
<!-- 列表 -->
|
||||
<view class="list">
|
||||
<!-- 列表:未读左侧黑竖条 + 黑字标题,已读降为 ink-3 -->
|
||||
<view wx:else class="nt-list">
|
||||
<view
|
||||
class="n-card card {{item.is_read === 1 ? 'unread' : ''}}"
|
||||
class="nt-item {{item.is_read === 1 ? 'is-unread' : ''}}"
|
||||
wx:for="{{list}}"
|
||||
wx:key="notification_uuid"
|
||||
data-uuid="{{item.notification_uuid}}"
|
||||
bindtap="onItemTap"
|
||||
>
|
||||
<view class="n-icon {{item.msg_type === 1 ? 'like' : item.msg_type === 2 ? 'order' : 'sys'}}">
|
||||
<view class="nt-ic">
|
||||
<view class="icon {{item.msg_type === 1 ? 'icon-heart' : item.msg_type === 2 ? 'icon-doc' : 'icon-bell'}}"></view>
|
||||
</view>
|
||||
<view class="n-body">
|
||||
<view class="n-title-row">
|
||||
<view wx:if="{{item.is_read === 1}}" class="n-dot"></view>
|
||||
<text class="n-title {{item.is_read === 2 ? 'read' : ''}}">{{item.title}}</text>
|
||||
</view>
|
||||
<view class="n-content">{{item.content}}</view>
|
||||
<view class="n-time">{{item._time}}</view>
|
||||
<view class="nt-body">
|
||||
<view class="nt-t">{{item.title}}</view>
|
||||
<view class="nt-c">{{item.content}}</view>
|
||||
<view class="nt-time num">{{item._time}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{list.length && !hasMore}}" class="foot-note">没有更多了</view>
|
||||
<view class="gap-32"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** 通知列表:下划线筛选 + 未读黑竖条 + 发丝线分行 **/
|
||||
.page-flex {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
@@ -10,117 +11,104 @@
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.filter-scroll {
|
||||
background: #fff;
|
||||
white-space: nowrap;
|
||||
.segbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
margin-top: 36rpx;
|
||||
background: var(--glass);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
border-bottom: 1rpx solid var(--hairline);
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: inline-flex;
|
||||
padding: 20rpx 24rpx;
|
||||
.nt-skel {
|
||||
padding: 40rpx var(--pad) 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 52rpx;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex-shrink: 0;
|
||||
padding: 0 32rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
color: #3C3C43;
|
||||
background: #F2F2F7;
|
||||
margin-right: 16rpx;
|
||||
.nt-skel-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18rpx;
|
||||
}
|
||||
|
||||
.filter-item.active {
|
||||
background: #007AFF;
|
||||
color: #fff;
|
||||
.nt-list {
|
||||
padding: 8rpx var(--pad) 0;
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.n-card {
|
||||
.nt-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
gap: 26rpx;
|
||||
padding: 36rpx 0;
|
||||
border-bottom: 1rpx solid var(--hairline);
|
||||
}
|
||||
|
||||
.n-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
/* 未读:左侧 4rpx 黑竖条 */
|
||||
.nt-item.is-unread::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -20rpx;
|
||||
top: 44rpx;
|
||||
width: 4rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 2rpx;
|
||||
background: var(--ink);
|
||||
}
|
||||
|
||||
.nt-ic {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
background: var(--fill);
|
||||
color: var(--ink-2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.n-icon.like {
|
||||
background: #FFE8EC;
|
||||
color: #FF3B30;
|
||||
.nt-ic .icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.n-icon.order {
|
||||
background: #E8F2FF;
|
||||
color: #007AFF;
|
||||
}
|
||||
|
||||
.n-icon.sys {
|
||||
background: #F2F2F7;
|
||||
color: #8E8E93;
|
||||
}
|
||||
|
||||
.n-icon .icon {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
|
||||
.n-body {
|
||||
.nt-body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.n-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.n-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background: #007AFF;
|
||||
margin-right: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.n-title {
|
||||
.nt-t {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.n-title.read {
|
||||
color: #8E8E93;
|
||||
font-weight: 500;
|
||||
color: var(--ink-3);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.n-content {
|
||||
.nt-item.is-unread .nt-t {
|
||||
color: var(--ink);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nt-c {
|
||||
margin-top: 10rpx;
|
||||
font-size: 26rpx;
|
||||
color: #3C3C43;
|
||||
margin-top: 8rpx;
|
||||
line-height: 1.6;
|
||||
color: var(--ink-2);
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.n-time {
|
||||
.nt-time {
|
||||
margin-top: 12rpx;
|
||||
font-size: 22rpx;
|
||||
color: #C7C7CC;
|
||||
margin-top: 8rpx;
|
||||
color: var(--ink-4);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user