first commit
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"navigation-bar": "/components/navigation-bar/navigation-bar",
|
||||
"empty-state": "/components/empty-state/empty-state"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { request } from '../../utils/request'
|
||||
import { PagedResult, NotificationItem } from '../../types/models'
|
||||
import { formatRelativeTime } from '../../utils/format'
|
||||
|
||||
const FILTERS = [
|
||||
{ name: '全部', value: 0 },
|
||||
{ name: '点赞', value: 1 },
|
||||
{ name: '订单', value: 2 },
|
||||
{ name: '系统', value: 3 },
|
||||
]
|
||||
|
||||
Page({
|
||||
data: {
|
||||
filters: FILTERS,
|
||||
activeFilter: 0,
|
||||
list: [] as NotificationItem[],
|
||||
loading: true,
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
hasMore: true,
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.refresh()
|
||||
this.fetchUnread()
|
||||
},
|
||||
|
||||
fetchUnread() {
|
||||
request<{ unread_count: number }>({ url: '/notification/unread', showError: false })
|
||||
.then((res) => {
|
||||
wx.setStorageSync('zt_closet_unread', res.unread_count)
|
||||
const tabBar = (this as any).getTabBar && (this as any).getTabBar()
|
||||
if (tabBar && tabBar.refreshUnread) tabBar.refreshUnread()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.setData({ page: 1, hasMore: true, loading: this.data.list.length === 0 })
|
||||
this.fetchList(1)
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (!this.data.hasMore || this.data.loading) return
|
||||
this.fetchList(this.data.page + 1)
|
||||
},
|
||||
|
||||
fetchList(page: number) {
|
||||
const params: Record<string, any> = { page, page_size: this.data.pageSize }
|
||||
const filter = this.data.activeFilter
|
||||
if (filter > 0) params.msg_type = filter
|
||||
|
||||
request<PagedResult<NotificationItem>>({ url: '/notification', data: params })
|
||||
.then((res) => {
|
||||
const list = res.list.map((it) => ({ ...it, _time: formatRelativeTime(it.created_at) }))
|
||||
const merged = page === 1 ? list : this.data.list.concat(list)
|
||||
this.setData({
|
||||
list: merged,
|
||||
hasMore: merged.length < res.total,
|
||||
loading: false,
|
||||
page,
|
||||
})
|
||||
})
|
||||
.catch(() => this.setData({ loading: false }))
|
||||
},
|
||||
|
||||
onFilterTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const index = Number(e.currentTarget.dataset.index)
|
||||
if (index === this.data.activeFilter) return
|
||||
this.setData({ activeFilter: index, list: [], loading: true })
|
||||
this.refresh()
|
||||
},
|
||||
|
||||
onItemTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const uuid = e.currentTarget.dataset.uuid as string
|
||||
wx.navigateTo({ url: `/pages/notification-detail/notification-detail?uuid=${uuid}` })
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,53 @@
|
||||
<view class="page page-flex">
|
||||
<navigation-bar title="通知" />
|
||||
|
||||
<scroll-view
|
||||
scroll-y
|
||||
class="scroll-body"
|
||||
bindscrolltolower="onReachBottom"
|
||||
>
|
||||
<!-- 筛选 -->
|
||||
<scroll-view scroll-x class="filter-scroll" show-scrollbar="{{false}}">
|
||||
<view class="filter-row">
|
||||
<view
|
||||
wx:for="{{filters}}"
|
||||
wx:key="name"
|
||||
class="filter-item {{activeFilter === index ? 'active' : ''}}"
|
||||
data-index="{{index}}"
|
||||
bindtap="onFilterTap"
|
||||
>{{item.name}}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 空态 -->
|
||||
<empty-state
|
||||
wx:if="{{!loading && !list.length}}"
|
||||
icon="icon-bell"
|
||||
title="还没有消息"
|
||||
desc="穿搭被点赞、订单动态都会出现在这里"
|
||||
/>
|
||||
|
||||
<!-- 列表 -->
|
||||
<view class="list">
|
||||
<view
|
||||
class="n-card card {{item.is_read === 1 ? '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="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>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -0,0 +1,126 @@
|
||||
.page-flex {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scroll-body {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.filter-scroll {
|
||||
background: #fff;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: inline-flex;
|
||||
padding: 20rpx 24rpx;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.filter-item.active {
|
||||
background: #007AFF;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.n-card {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.n-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.n-icon.like {
|
||||
background: #FFE8EC;
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.n-icon.order {
|
||||
background: #E8F2FF;
|
||||
color: #007AFF;
|
||||
}
|
||||
|
||||
.n-icon.sys {
|
||||
background: #F2F2F7;
|
||||
color: #8E8E93;
|
||||
}
|
||||
|
||||
.n-icon .icon {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
|
||||
.n-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 {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.n-title.read {
|
||||
color: #8E8E93;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.n-content {
|
||||
font-size: 26rpx;
|
||||
color: #3C3C43;
|
||||
margin-top: 8rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.n-time {
|
||||
font-size: 22rpx;
|
||||
color: #C7C7CC;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
Reference in New Issue
Block a user