125 lines
3.5 KiB
JavaScript
125 lines
3.5 KiB
JavaScript
/**
|
||||
|
|
* 黑名单管理页(重构:用 matchStore + ui-nav-bar + DangerActionDialog)
|
|||
|
|
*
|
|||
|
|
* 列表展示已拉黑用户(脱敏字段),支持解除拉黑。
|
|||
|
|
*
|
|||
|
|
* 不变量(AGENTS.md):
|
|||
|
|
* - 第 4 条:Block 优先级最高——解除拉黑后对方可重新与你互动;
|
|||
|
|
* 解除需 DangerActionDialog 二次确认。
|
|||
|
|
* - 第 8 条:敏感数据默认拒绝——列表仅展示后端返回的脱敏字段(昵称/拉黑时间/原因),
|
|||
|
|
* 不展示手机号/身份证等敏感信息。
|
|||
|
|
* - 第 9 条:PostgreSQL 是 Source of Truth——列表状态以 matchStore 同步服务端返回为准。
|
|||
|
|
*/
|
|||
|
|
const { matchStore, appStore } = require('../../stores');
|
|||
|
|
const { DANGER_ACTION } = require('../../constants');
|
|||
|
|
|
|||
|
|
const PAGE_SIZE = 20;
|
|||
|
|
|
|||
|
|
Page({
|
|||
|
|
data: {
|
|||
|
|
blockedList: [],
|
|||
|
|
blockedHasMore: true,
|
|||
|
|
loading: false,
|
|||
|
|
loadingMore: false,
|
|||
|
|
actionLoadingUserId: '',
|
|||
|
|
|
|||
|
|
// DangerActionDialog
|
|||
|
|
showDangerDialog: false,
|
|||
|
|
dangerAction: DANGER_ACTION.UNBLOCK,
|
|||
|
|
dangerTargetName: '',
|
|||
|
|
pendingUnblockUserId: '',
|
|||
|
|
|
|||
|
|
statusBarHeight: 20,
|
|||
|
|
navBarHeight: 44,
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onLoad() {
|
|||
|
|
try {
|
|||
|
|
const info = (wx.getWindowInfo && wx.getWindowInfo()) || wx.getSystemInfoSync();
|
|||
|
|
this.setData({
|
|||
|
|
statusBarHeight: info.statusBarHeight || 20,
|
|||
|
|
navBarHeight: info.platform === 'android' ? 48 : 44,
|
|||
|
|
});
|
|||
|
|
} catch (e) { /* 使用默认值 */ }
|
|||
|
|
|
|||
|
|
this._unsub = matchStore.bindToPage(this, {
|
|||
|
|
blockedList: 'blockedList',
|
|||
|
|
blockedHasMore: 'blockedHasMore',
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
this.fetchList(true);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onUnload() {
|
|||
|
|
if (this._unsub) this._unsub();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onShow() {
|
|||
|
|
this.fetchList(true);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
async fetchList(first) {
|
|||
|
|
if (this.data.loading) return;
|
|||
|
|
this.setData({ loading: true });
|
|||
|
|
try {
|
|||
|
|
await matchStore.fetchBlockedList({ pageSize: PAGE_SIZE });
|
|||
|
|
} catch (err) {
|
|||
|
|
appStore.toastError(err);
|
|||
|
|
} finally {
|
|||
|
|
this.setData({ loading: false });
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onPullDownRefresh() {
|
|||
|
|
this.fetchList(true).finally(() => wx.stopPullDownRefresh());
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onReachBottom() {
|
|||
|
|
if (this.data.loadingMore || !this.data.blockedHasMore) return;
|
|||
|
|
this.setData({ loadingMore: true });
|
|||
|
|
matchStore.loadMoreBlockedList()
|
|||
|
|
.catch((err) => appStore.toastError(err))
|
|||
|
|
.finally(() => this.setData({ loadingMore: false }));
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// ============ 解除拉黑 ============
|
|||
|
|
|
|||
|
|
onUnblock(e) {
|
|||
|
|
const userId = e.currentTarget.dataset.userId;
|
|||
|
|
const userName = e.currentTarget.dataset.userName || '对方';
|
|||
|
|
if (!userId || this.data.actionLoadingUserId) return;
|
|||
|
|
this.setData({
|
|||
|
|
showDangerDialog: true,
|
|||
|
|
dangerTargetName: userName,
|
|||
|
|
pendingUnblockUserId: userId,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
async onDangerConfirm() {
|
|||
|
|
const userId = this.data.pendingUnblockUserId;
|
|||
|
|
this.setData({ showDangerDialog: false, pendingUnblockUserId: '' });
|
|||
|
|
if (!userId) return;
|
|||
|
|
this.setData({ actionLoadingUserId: userId });
|
|||
|
|
try {
|
|||
|
|
await matchStore.unblock(userId);
|
|||
|
|
// 从本地列表移除(Store 的 unblock 不自动移除,需页面处理)
|
|||
|
|
matchStore.setState({
|
|||
|
|
blockedList: matchStore.state.blockedList.filter((u) => u.userId !== userId),
|
|||
|
|
});
|
|||
|
|
appStore.toastSuccess('已解除拉黑');
|
|||
|
|
} catch (err) {
|
|||
|
|
appStore.toastError(err);
|
|||
|
|
} finally {
|
|||
|
|
this.setData({ actionLoadingUserId: '' });
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onDangerCancel() {
|
|||
|
|
this.setData({ showDangerDialog: false, pendingUnblockUserId: '' });
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onBack() {
|
|||
|
|
wx.navigateBack();
|
|||
|
|
},
|
|||
|
|
});
|