You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
7.1 KiB
156 lines
7.1 KiB
<template>
|
|
<view class="settings-page">
|
|
<view class="top-safe" :style="{ height: menuButtonInfo.top + 'px' }"></view>
|
|
<view class="nav">
|
|
<view class="back" @tap="back">‹</view>
|
|
<view class="title">安全</view>
|
|
<view class="ghost"></view>
|
|
</view>
|
|
<view class="hero">
|
|
<view class="hero-title">安全中心</view>
|
|
<view class="hero-sub">这里只有黑名单和举报记录,方便你随时管理边界。</view>
|
|
</view>
|
|
<view class="tabs">
|
|
<view class="tab" :class="{ active: activeTab === 'blocks' }" @tap="switchTab('blocks')">黑名单</view>
|
|
<view class="tab" :class="{ active: activeTab === 'reports' }" @tap="switchTab('reports')">举报记录</view>
|
|
</view>
|
|
|
|
<view class="panel" v-if="activeTab === 'blocks'">
|
|
<view class="panel-title">已拉黑对象</view>
|
|
<view class="row" v-for="item in blocks" :key="item.id">
|
|
<view class="row-main">
|
|
<view class="name">用户 {{ item.blockedUserId }}</view>
|
|
<view class="desc">{{ item.reason || '已加入黑名单,不会再次出现在推荐中。' }}</view>
|
|
<view class="time">{{ item.createTime || '' }}</view>
|
|
</view>
|
|
<view class="action danger" @tap="confirmUnblock(item)">解除</view>
|
|
</view>
|
|
<view class="empty" v-if="!loading && !blocks.length">还没有拉黑任何人。</view>
|
|
<view class="empty" v-else>{{ loading ? '正在加载...' : (hasMore ? '上滑加载更多' : '没有更多了') }}</view>
|
|
</view>
|
|
|
|
<view class="panel" v-if="activeTab === 'reports'">
|
|
<view class="panel-title">我的举报记录</view>
|
|
<view class="row report-row" v-for="item in reports" :key="item.id">
|
|
<view class="row-main">
|
|
<view class="name">{{ reasonText(item.reasonType) }}</view>
|
|
<view class="desc">{{ item.reasonText || '已提交安全反馈。' }}</view>
|
|
<view class="time">对象 {{ item.reportedUserId || '-' }} · {{ statusText(item.status) }} · {{ item.createTime || '' }}</view>
|
|
<view class="handle" v-if="item.handleResult">{{ item.handleResult }}</view>
|
|
</view>
|
|
</view>
|
|
<view class="empty" v-if="!loading && !reports.length">还没有举报记录。</view>
|
|
<view class="empty" v-else>{{ loading ? '正在加载...' : (hasMore ? '上滑加载更多' : '没有更多了') }}</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { pageIeBlocks, pageIeReports, unblockIeUser } from '@/common/ieApi.js'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
menuButtonInfo: { top: 44 },
|
|
activeTab: 'blocks',
|
|
blocks: [],
|
|
reports: [],
|
|
pageNumber: 1,
|
|
pageSize: 10,
|
|
hasMore: true,
|
|
loading: false
|
|
}
|
|
},
|
|
onLoad() {
|
|
if (uni.getMenuButtonBoundingClientRect) this.menuButtonInfo = uni.getMenuButtonBoundingClientRect()
|
|
this.loadList()
|
|
},
|
|
onReachBottom() {
|
|
this.loadList()
|
|
},
|
|
methods: {
|
|
back() { uni.redirectTo({ url: '/package1/ieBrowser/index' }) },
|
|
switchTab(tab) {
|
|
if (this.activeTab === tab) return
|
|
this.activeTab = tab
|
|
this.pageNumber = 1
|
|
this.hasMore = true
|
|
this.loading = false
|
|
if (tab === 'blocks') this.blocks = []
|
|
if (tab === 'reports') this.reports = []
|
|
this.loadList()
|
|
},
|
|
async loadList() {
|
|
if (this.loading || !this.hasMore) return
|
|
this.loading = true
|
|
try {
|
|
const page = this.activeTab === 'blocks'
|
|
? await pageIeBlocks(this.pageNumber, this.pageSize)
|
|
: await pageIeReports(this.pageNumber, this.pageSize)
|
|
const list = page && page.records ? page.records : []
|
|
if (this.activeTab === 'blocks') {
|
|
const exists = new Set(this.blocks.map(item => item.id))
|
|
this.blocks = this.blocks.concat(list.filter(item => !exists.has(item.id)))
|
|
} else {
|
|
const exists = new Set(this.reports.map(item => item.id))
|
|
this.reports = this.reports.concat(list.filter(item => !exists.has(item.id)))
|
|
}
|
|
this.hasMore = page ? (page.current || this.pageNumber) < (page.pages || this.pageNumber) : false
|
|
this.pageNumber += 1
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
confirmUnblock(item) {
|
|
if (!item || !item.blockedUserId) return
|
|
uni.showModal({
|
|
title: '解除拉黑?',
|
|
content: '解除后,对方可能再次出现在随机陪伴中。',
|
|
confirmText: '解除',
|
|
confirmColor: '#6c69d8',
|
|
success: async (res) => {
|
|
if (!res.confirm) return
|
|
await unblockIeUser(item.blockedUserId)
|
|
this.blocks = this.blocks.filter(block => block.id !== item.id)
|
|
uni.showToast({ title: '已解除', icon: 'none' })
|
|
}
|
|
})
|
|
},
|
|
reasonText(type) {
|
|
const map = { other: '其他问题', harassment: '骚扰不适', fraud: '疑似欺诈', abuse: '攻击辱骂' }
|
|
return map[type] || '安全反馈'
|
|
},
|
|
statusText(status) {
|
|
if (status === 1) return '已处理'
|
|
if (status === 2) return '已驳回'
|
|
return '待处理'
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
page { background: #f7f9ff; }
|
|
.settings-page { min-height: 100vh; padding: 0 30rpx 60rpx; box-sizing: border-box; color: #151a2d; background: radial-gradient(circle at 82% 8%, rgba(169,255,231,.36), transparent 300rpx), linear-gradient(180deg, #fbfdff, #eef4ff); }
|
|
.nav { height: 90rpx; display: flex; align-items: center; }
|
|
.back, .ghost { width: 70rpx; font-size: 56rpx; color: rgba(21,26,45,.64); }
|
|
.title { flex: 1; text-align: center; font-size: 31rpx; font-weight: 800; }
|
|
.hero { margin-top: 20rpx; padding: 34rpx; border-radius: 40rpx; background: rgba(255,255,255,.62); border: 1rpx solid rgba(255,255,255,.86); box-shadow: 0 22rpx 60rpx rgba(96,112,160,.1); }
|
|
.hero-title { font-size: 44rpx; font-weight: 900; }
|
|
.hero-sub { margin-top: 12rpx; color: rgba(21,26,45,.5); font-size: 24rpx; line-height: 38rpx; }
|
|
.tabs { display: flex; gap: 16rpx; margin-top: 24rpx; padding: 10rpx; border-radius: 999rpx; background: rgba(255,255,255,.62); }
|
|
.tab { flex: 1; height: 70rpx; line-height: 70rpx; border-radius: 999rpx; text-align: center; color: rgba(21,26,45,.52); font-size: 25rpx; font-weight: 800; }
|
|
.tab.active { color: #11162a; background: #a9ffe7; box-shadow: 0 12rpx 30rpx rgba(169,255,231,.28); }
|
|
.panel { margin-top: 26rpx; padding: 30rpx; border-radius: 36rpx; background: rgba(255,255,255,.68); border: 1rpx solid rgba(255,255,255,.88); box-shadow: 0 22rpx 60rpx rgba(96,112,160,.1); }
|
|
.panel-title { margin-bottom: 12rpx; font-size: 30rpx; font-weight: 800; }
|
|
.row { display: flex; align-items: center; padding: 24rpx 0; border-top: 1rpx solid rgba(21,26,45,.06); }
|
|
.row:first-of-type { border-top: 0; }
|
|
.row-main { flex: 1; min-width: 0; }
|
|
.name { font-size: 27rpx; font-weight: 800; }
|
|
.desc { margin-top: 8rpx; color: rgba(21,26,45,.48); font-size: 22rpx; }
|
|
.time { margin-top: 8rpx; color: rgba(21,26,45,.34); font-size: 20rpx; line-height: 32rpx; }
|
|
.handle { margin-top: 12rpx; padding: 14rpx 18rpx; border-radius: 22rpx; color: #6c69d8; background: rgba(139,124,255,.1); font-size: 22rpx; line-height: 34rpx; }
|
|
.action { flex-shrink: 0; height: 58rpx; line-height: 58rpx; padding: 0 22rpx; border-radius: 999rpx; font-size: 22rpx; font-weight: 800; }
|
|
.action.danger { color: #e85d75; background: rgba(232,93,117,.1); }
|
|
.empty { margin-top: 26rpx; text-align: center; color: rgba(21,26,45,.36); font-size: 23rpx; }
|
|
</style>
|
|
|