From cd0e8b7c5d4f87c0172319874e678c3434fd9118 Mon Sep 17 00:00:00 2001
From: wangfukang <15630117759@163.com>
Date: Wed, 27 May 2026 11:09:50 +0800
Subject: [PATCH] 1
---
package1/ieBrowser/chat.vue | 334 ++++++++++++++++++++++++++--
package1/ieBrowser/profileSetup.vue | 88 +++++++-
package1/ieBrowser/settings.vue | 140 +++++++++---
package1/ieBrowser/videoPreview.vue | 42 ++++
4 files changed, 561 insertions(+), 43 deletions(-)
create mode 100644 package1/ieBrowser/videoPreview.vue
diff --git a/package1/ieBrowser/chat.vue b/package1/ieBrowser/chat.vue
index 88fa165..736c667 100644
--- a/package1/ieBrowser/chat.vue
+++ b/package1/ieBrowser/chat.vue
@@ -22,6 +22,10 @@
电台陪伴中
你们已经安静陪伴了 {{ silentMinutes }} 分钟
+
+ 加入黑名单
+ 举报
+
@@ -51,6 +55,16 @@
+
+
+
+
+ ▶
+ 点击播放视频
+
+ {{ item.mediaDuration }}s
+
+
{{ item.content }}
@@ -74,26 +88,42 @@
☺
- {{ voiceMode ? '键' : '语' }}
- {{ voiceMode ? '键' : '语' }}
+
{{ voiceHoldText }}
- +
- 发送
+ +
+ 发送
安全与退出
- 举报不适内容
+ 举报不适内容
拉黑这个对象
提前结束陪伴
+
+
+ 举报这个对象
+
+ {{ item.label }}
+
+
+
+ 取消
+ 提交举报
+
+
+
+
@@ -141,6 +171,8 @@
pollTimer: null,
draft: '',
showSafety: false,
+ showReportPanel: false,
+ isBlocked: false,
showTargetProfile: false,
targetProfile: {},
showEmoji: false,
@@ -169,6 +201,16 @@
sendingMessage: false,
emojis: ['🙂', '😄', '🥲', '😭', '😴', '🙌', '🌙', '☁️', '🍃', '✨', '💛', '🫶'],
presenceActions: ['我在', '听着呢', '慢慢说', '抱一下空气'],
+ reportReasons: [
+ { key: 'harassment', label: '骚扰不适' },
+ { key: 'abuse', label: '攻击辱骂' },
+ { key: 'fraud', label: '疑似欺诈' },
+ { key: 'other', label: '其他问题' }
+ ],
+ reportForm: {
+ reasonType: 'other',
+ reasonText: ''
+ },
silentModes: ['一起听歌', '一起倒计时', '一起自习', '一起失眠'],
companions: {
i: {
@@ -314,6 +356,7 @@
mediaDuration: item.mediaDuration,
mediaSize: item.mediaSize,
mediaFormat: item.mediaFormat,
+ poster: item.poster || item.thumbTempFilePath || '',
mine,
pending: false,
blocked: item.isBlocked === 1
@@ -400,9 +443,20 @@
this.sendChatContent(text, 1)
},
toggleEmoji() {
+ if (this.isBlocked) {
+ uni.showToast({ title: '已加入黑名单,无法继续发送', icon: 'none' })
+ return
+ }
this.voiceMode = false
this.showEmoji = !this.showEmoji
},
+ toggleVoiceMode() {
+ if (this.isBlocked) {
+ uni.showToast({ title: '已加入黑名单,无法继续发送', icon: 'none' })
+ return
+ }
+ this.voiceMode = !this.voiceMode
+ },
sendEmoji(emoji) {
this.showEmoji = false
this.sendChatContent(emoji, 3)
@@ -425,6 +479,10 @@
uni.showToast({ title: '房间信息缺失', icon: 'none' })
return
}
+ if (this.isBlocked) {
+ uni.showToast({ title: '已加入黑名单,无法继续发送', icon: 'none' })
+ return
+ }
if (this.needWaitReply()) {
uni.showToast({ title: '先等等对方回复吧,首次破冰最多发送 3 条', icon: 'none' })
return
@@ -438,6 +496,7 @@
mediaDuration: media.mediaDuration,
mediaSize: media.mediaSize,
mediaFormat: media.mediaFormat,
+ poster: media.poster || '',
mine: true,
pending: true
})
@@ -471,11 +530,13 @@
msg.content = '发送失败,请稍后再试'
}
} catch (e) {
+ const message = (e && e.message) || ''
+ if (message.indexOf('黑名单') >= 0) this.isBlocked = true
const msg = this.messages.find(item => item.clientMsgId === payload.clientMsgId)
if (msg) {
msg.pending = false
msg.blocked = true
- msg.content = (e && e.message) || '发送失败,请稍后再试'
+ msg.content = message || '发送失败,请稍后再试'
}
}
},
@@ -491,8 +552,33 @@
msg.blocked = ack.isBlocked === 1
msg.content = msg.blocked ? '这句话没有送出,请换一种更温柔的说法。' : (ack.content || msg.content)
},
- chooseImage() {
+ chooseMedia() {
+ if (this.isBlocked) {
+ uni.showToast({ title: '已加入黑名单,无法继续发送', icon: 'none' })
+ return
+ }
if (this.uploadingImage) return
+ if (!uni.chooseMedia) {
+ this.chooseImageCompat()
+ return
+ }
+ uni.chooseMedia({
+ count: 1,
+ mediaType: ['image', 'video'],
+ sourceType: ['album', 'camera'],
+ camera: 'back',
+ success: async (res) => {
+ const file = res.tempFiles && res.tempFiles[0]
+ if (!file || !file.tempFilePath) return
+ if (res.type === 'video' || file.fileType === 'video') {
+ await this.uploadAndSendVideo(file)
+ return
+ }
+ await this.uploadAndSendImage(file.tempFilePath, file.size)
+ }
+ })
+ },
+ chooseImageCompat() {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
@@ -504,7 +590,7 @@
}
})
},
- async uploadAndSendImage(filePath) {
+ async uploadAndSendImage(filePath, fileSize) {
this.uploadingImage = true
try {
const result = await tui.uploadFile('/upload/file', filePath)
@@ -514,7 +600,30 @@
return
}
this.showEmoji = false
- this.sendChatContent(imageUrl, 2)
+ this.sendChatContent(imageUrl, 2, {
+ mediaSize: fileSize,
+ mediaFormat: 'image'
+ })
+ } finally {
+ this.uploadingImage = false
+ }
+ },
+ async uploadAndSendVideo(file) {
+ this.uploadingImage = true
+ try {
+ const result = await tui.uploadFile('/upload/file', file.tempFilePath)
+ const videoUrl = typeof result === 'string' ? result : (result.url || result.fileUrl || result.path || result.fullPath || result)
+ if (!videoUrl || typeof videoUrl !== 'string') {
+ uni.showToast({ title: '视频上传失败', icon: 'none' })
+ return
+ }
+ this.showEmoji = false
+ this.sendChatContent(videoUrl, 5, {
+ mediaDuration: file.duration ? Math.round(file.duration) : undefined,
+ mediaSize: file.size,
+ mediaFormat: 'video',
+ poster: file.thumbTempFilePath || ''
+ })
} finally {
this.uploadingImage = false
}
@@ -523,6 +632,12 @@
if (!url) return
uni.previewImage({ urls: [url], current: url })
},
+ previewVideo(url) {
+ if (!url) return
+ uni.navigateTo({
+ url: '/package1/ieBrowser/videoPreview?url=' + encodeURIComponent(url)
+ })
+ },
initRecorder() {
if (!uni.getRecorderManager) return
this.recorderManager = uni.getRecorderManager()
@@ -564,6 +679,10 @@
return touch ? touch.clientY || touch.pageY || 0 : 0
},
startRecord(event) {
+ if (this.isBlocked) {
+ uni.showToast({ title: '已加入黑名单,无法继续发送', icon: 'none' })
+ return
+ }
if (!this.recorderManager || this.uploadingVoice) return
this.showEmoji = false
this.recording = true
@@ -681,15 +800,45 @@
prompt: profile.intro || this.companion.prompt
}
},
- async report() {
+ openReportPanel() {
this.showSafety = false
- await reportIeRoom(this.roomId, { reportedUserId: this.targetUserId, reasonType: 'other', reasonText: '聊天内容不适' })
+ this.reportForm.reasonType = 'other'
+ this.reportForm.reasonText = ''
+ this.showReportPanel = true
+ },
+ async submitReport() {
+ if (!this.roomId || !this.targetUserId) {
+ uni.showToast({ title: '举报对象缺失', icon: 'none' })
+ return
+ }
+ await reportIeRoom(this.roomId, {
+ reportedUserId: this.targetUserId,
+ reasonType: this.reportForm.reasonType,
+ reasonText: this.reportForm.reasonText || '聊天内容不适'
+ })
+ this.showReportPanel = false
uni.showToast({ title: '已收到举报', icon: 'none' })
},
async block() {
this.showSafety = false
- if (this.targetUserId) await blockIeUser(this.targetUserId, '聊天中拉黑')
- uni.showToast({ title: '已拉黑', icon: 'none' })
+ if (!this.targetUserId) {
+ uni.showToast({ title: '拉黑对象缺失', icon: 'none' })
+ return
+ }
+ uni.showModal({
+ title: '加入黑名单?',
+ content: '加入后你们不能继续互相发送消息,也不会再次随机匹配到对方。',
+ confirmText: '加入',
+ confirmColor: '#e85d75',
+ success: async (res) => {
+ if (!res.confirm) return
+ await blockIeUser(this.targetUserId, '聊天中拉黑')
+ this.isBlocked = true
+ this.showEmoji = false
+ this.voiceMode = false
+ uni.showToast({ title: '已加入黑名单', icon: 'none' })
+ }
+ })
},
async finishRoom() {
if (this.finishing) return
@@ -925,6 +1074,8 @@
.radio-copy {
position: relative;
z-index: 1;
+ flex: 1;
+ min-width: 0;
}
.radio-title {
@@ -938,6 +1089,31 @@
font-size: 22rpx;
}
+ .safe-actions {
+ position: relative;
+ z-index: 1;
+ display: flex;
+ gap: 12rpx;
+ margin-left: 18rpx;
+ }
+
+ .safe-btn {
+ height: 52rpx;
+ line-height: 52rpx;
+ padding: 0 18rpx;
+ border-radius: 999rpx;
+ color: #6c69d8;
+ background: rgba(139,124,255,.1);
+ font-size: 21rpx;
+ font-weight: 800;
+ white-space: nowrap;
+ }
+
+ .safe-btn.warn {
+ color: #e85d75;
+ background: rgba(232,93,117,.1);
+ }
+
.silent-modes {
position: relative;
z-index: 1;
@@ -1098,6 +1274,13 @@
background: rgba(255, 255, 255, 0.72);
}
+ .video-bubble {
+ padding: 0;
+ border: none;
+ background: transparent;
+ overflow: hidden;
+ }
+
.chat-image {
display: block;
width: 260rpx;
@@ -1106,6 +1289,71 @@
background: rgba(22, 27, 46, 0.06);
}
+ .video-card {
+ position: relative;
+ width: 300rpx;
+ height: 390rpx;
+ border-radius: 28rpx;
+ overflow: hidden;
+ background:
+ radial-gradient(circle at 22% 16%, rgba(169,255,231,.36), transparent 130rpx),
+ radial-gradient(circle at 78% 80%, rgba(139,124,255,.32), transparent 150rpx),
+ linear-gradient(145deg, #151a2d, #2c3350);
+ box-shadow: 0 18rpx 44rpx rgba(96,112,160,.18);
+ }
+
+ .mine .video-card {
+ box-shadow: 0 18rpx 44rpx rgba(169,255,231,.24);
+ }
+
+ .video-poster,
+ .video-placeholder {
+ width: 100%;
+ height: 100%;
+ }
+
+ .video-placeholder {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ color: rgba(255,255,255,.92);
+ }
+
+ .video-play {
+ width: 86rpx;
+ height: 86rpx;
+ border-radius: 50%;
+ text-align: center;
+ line-height: 86rpx;
+ color: #151a2d;
+ background: rgba(255,255,255,.9);
+ box-shadow: 0 12rpx 32rpx rgba(0,0,0,.18);
+ font-size: 34rpx;
+ font-weight: 900;
+ }
+
+ .video-text {
+ margin-top: 18rpx;
+ color: rgba(255,255,255,.78);
+ font-size: 24rpx;
+ font-weight: 700;
+ }
+
+ .video-meta {
+ position: absolute;
+ right: 16rpx;
+ bottom: 16rpx;
+ height: 42rpx;
+ line-height: 42rpx;
+ padding: 0 16rpx;
+ border-radius: 999rpx;
+ color: #fff;
+ background: rgba(0,0,0,.38);
+ font-size: 21rpx;
+ font-weight: 800;
+ }
+
.emoji-bubble {
min-width: 72rpx;
text-align: center;
@@ -1254,6 +1502,10 @@
font-weight: 800;
}
+ .send.disabled {
+ opacity: .46;
+ }
+
.safety-mask {
position: fixed;
left: 0;
@@ -1295,6 +1547,62 @@
color: #6c69d8;
}
+ .report-reason {
+ height: 76rpx;
+ line-height: 76rpx;
+ margin-top: 12rpx;
+ padding: 0 24rpx;
+ border-radius: 24rpx;
+ color: rgba(22,27,46,.66);
+ background: rgba(238,244,255,.72);
+ font-size: 25rpx;
+ font-weight: 800;
+ }
+
+ .report-reason.active {
+ color: #151a2d;
+ background: #a9ffe7;
+ }
+
+ .report-textarea {
+ width: 100%;
+ height: 150rpx;
+ margin-top: 18rpx;
+ padding: 22rpx;
+ border-radius: 24rpx;
+ box-sizing: border-box;
+ color: #151a2d;
+ background: rgba(238,244,255,.72);
+ font-size: 24rpx;
+ }
+
+ .report-actions {
+ display: flex;
+ gap: 16rpx;
+ margin-top: 20rpx;
+ }
+
+ .report-cancel,
+ .report-submit {
+ flex: 1;
+ height: 78rpx;
+ line-height: 78rpx;
+ border-radius: 999rpx;
+ text-align: center;
+ font-size: 25rpx;
+ font-weight: 800;
+ }
+
+ .report-cancel {
+ color: rgba(22,27,46,.62);
+ background: rgba(22,27,46,.06);
+ }
+
+ .report-submit {
+ color: #11162a;
+ background: #a9ffe7;
+ }
+
.profile-mask {
position: fixed;
left: 0;
diff --git a/package1/ieBrowser/profileSetup.vue b/package1/ieBrowser/profileSetup.vue
index cb95152..10eee39 100644
--- a/package1/ieBrowser/profileSetup.vue
+++ b/package1/ieBrowser/profileSetup.vue
@@ -4,10 +4,10 @@
‹
{{ isEdit ? '编辑 i/e 资料' : '先认识一下你' }}
- {{ step }}/4
+ {{ step }}/5
-
+
Your Energy
@@ -52,6 +52,22 @@
+ Persona Cards
+ 上传你的人格卡片
+ 最多 5 张,像个人主页的形象展示。别人点击头像时可以看到。
+
+
+
+ ×
+
+
+ +
+ 添加图片
+
+
+
+
+
Match Target
你现在想遇见哪类人?
@@ -68,7 +84,7 @@
上一步
- {{ step === 4 ? '进入 i/e 此刻' : '继续' }}
+ {{ step === 5 ? '进入 i/e 此刻' : '继续' }}
@@ -94,7 +110,8 @@
avatarUrl: '',
gender: 'unknown',
intro: '',
- interestTags: []
+ interestTags: [],
+ personaImages: []
},
tagOptions: ['慢热', '爱听歌', '夜跑', '自习', '想聊天', '想安静', '情绪低电量', '散步', '电影', '游戏', '摄影', '干饭'],
targetOptions: [
@@ -142,6 +159,7 @@
this.form.gender = profile.gender || 'unknown'
this.form.intro = profile.intro || ''
this.form.interestTags = profile.interestTags || []
+ this.form.personaImages = profile.personaImages || []
},
toggleTag(tag) {
const index = this.form.interestTags.indexOf(tag)
@@ -208,6 +226,59 @@
// uni.hideLoading();
}, 1000)
},
+ choosePersonaImages() {
+ const remain = 5 - this.form.personaImages.length
+ if (remain <= 0) {
+ uni.showToast({ title: '最多上传 5 张', icon: 'none' })
+ return
+ }
+ uni.chooseMedia({
+ count: remain,
+ mediaType: ['image'],
+ sourceType: ['camera', 'album'],
+ camera: 'back',
+ success: async (res) => {
+ const files = res.tempFiles || []
+ for (const file of files) {
+ if (this.form.personaImages.length >= 5) break
+ const url = await this.uploadPersonaFile(file.tempFilePath)
+ if (url) this.form.personaImages.push(url)
+ }
+ }
+ })
+ },
+ uploadPersonaFile(path) {
+ if (!path) return Promise.resolve('')
+ const hiverToken = uni.getStorageSync('hiver_token')
+ uni.showLoading({ title: '上传中...', mask: true })
+ return new Promise((resolve) => {
+ uni.uploadFile({
+ url: this.tui.interfaceUrl() + '/upload/file',
+ filePath: path,
+ name: 'file',
+ header: {
+ 'content-type': 'multipart/form-data',
+ 'accessToken': hiverToken
+ },
+ success: (uploadFileRes) => {
+ try {
+ const data = JSON.parse(uploadFileRes.data)
+ resolve(data.result || '')
+ } catch (e) {
+ resolve('')
+ }
+ },
+ fail: () => resolve(''),
+ complete: () => uni.hideLoading()
+ })
+ })
+ },
+ removePersonaImage(index) {
+ this.form.personaImages.splice(index, 1)
+ },
+ previewPersona(index) {
+ uni.previewImage({ urls: this.form.personaImages, current: this.form.personaImages[index] })
+ },
validateStep() {
if (this.step === 2 && !this.form.anonymousName.trim()) {
uni.showToast({ title: '先起一个昵称吧', icon: 'none' })
@@ -223,7 +294,7 @@
async next() {
if (this.submitting) return
if (!this.validateStep()) return
- if (this.step < 4) {
+ if (this.step < 5) {
this.step += 1
return
}
@@ -264,6 +335,7 @@
.card { margin-top: 36rpx; padding: 38rpx 32rpx; border-radius: 46rpx; border: 1rpx solid rgba(255,255,255,.82); background: rgba(255,255,255,.64); box-shadow: 0 26rpx 80rpx rgba(96,112,160,.14); backdrop-filter: blur(26rpx); }
.eyebrow { color: rgba(21,26,45,.42); font-size: 22rpx; letter-spacing: 5rpx; text-transform: uppercase; }
.headline { margin-top: 16rpx; margin-bottom: 28rpx; font-size: 46rpx; line-height: 60rpx; font-weight: 800; }
+ .card-desc { margin: -10rpx 0 24rpx; color: rgba(21,26,45,.52); font-size: 24rpx; line-height: 38rpx; }
.mode-card, .target-card { display: flex; align-items: center; margin-top: 22rpx; padding: 28rpx; border-radius: 34rpx; background: rgba(238,244,255,.68); border: 2rpx solid transparent; }
.mode-card.active, .target-card.active { border-color: #a9ffe7; background: rgba(223,254,244,.7); transform: scale(1.01); }
.mark { width: 82rpx; height: 82rpx; margin-right: 22rpx; border-radius: 28rpx; text-align: center; line-height: 82rpx; font-size: 46rpx; font-weight: 800; }
@@ -288,6 +360,12 @@
.tag-grid { display: flex; flex-wrap: wrap; }
.tag { margin: 0 14rpx 18rpx 0; padding: 16rpx 24rpx; border-radius: 999rpx; color: rgba(21,26,45,.62); background: rgba(238,244,255,.82); font-size: 24rpx; }
.tag.active { color: #11162a; background: #a9ffe7; font-weight: 800; }
+ .persona-grid { display: flex; flex-wrap: wrap; gap: 18rpx; }
+ .persona-item, .persona-add { position: relative; width: 184rpx; height: 224rpx; border-radius: 30rpx; overflow: hidden; background: rgba(238,244,255,.82); }
+ .persona-item image { width: 100%; height: 100%; display: block; }
+ .persona-delete { position: absolute; right: 12rpx; top: 12rpx; width: 42rpx; height: 42rpx; border-radius: 50%; text-align: center; line-height: 38rpx; color: #fff; background: rgba(21,26,45,.56); font-size: 34rpx; }
+ .persona-add { display: flex; flex-direction: column; align-items: center; justify-content: center; color: rgba(21,26,45,.46); border: 2rpx dashed rgba(108,105,216,.22); box-sizing: border-box; font-size: 23rpx; }
+ .persona-add .plus { margin-bottom: 10rpx; color: #6c69d8; font-size: 44rpx; font-weight: 800; }
.actions { position: fixed; left: 32rpx; right: 32rpx; bottom: 42rpx; display: flex; gap: 18rpx; }
.ghost, .solid { flex: 1; height: 96rpx; border-radius: 999rpx; text-align: center; line-height: 96rpx; font-size: 28rpx; font-weight: 800; }
.ghost { color: rgba(21,26,45,.58); background: rgba(255,255,255,.68); }
diff --git a/package1/ieBrowser/settings.vue b/package1/ieBrowser/settings.vue
index c337ac2..6c1e6a3 100644
--- a/package1/ieBrowser/settings.vue
+++ b/package1/ieBrowser/settings.vue
@@ -3,64 +3,154 @@
‹
- 设置
+ 安全
-
- {{ group.title }}
-
-
- {{ item.name }}
- {{ item.desc }}
+
+ 安全中心
+ 这里只有黑名单和举报记录,方便你随时管理边界。
+
+
+ 黑名单
+ 举报记录
+
+
+
+ 已拉黑对象
+
+
+ 用户 {{ item.blockedUserId }}
+ {{ item.reason || '已加入黑名单,不会再次出现在推荐中。' }}
+ {{ item.createTime || '' }}
+
+ 解除
+
+ 还没有拉黑任何人。
+ {{ loading ? '正在加载...' : (hasMore ? '上滑加载更多' : '没有更多了') }}
+
+
+
+ 我的举报记录
+
+
+ {{ reasonText(item.reasonType) }}
+ {{ item.reasonText || '已提交安全反馈。' }}
+ 对象 {{ item.reportedUserId || '-' }} · {{ statusText(item.status) }} · {{ item.createTime || '' }}
+ {{ item.handleResult }}
- ›
+ 还没有举报记录。
+ {{ loading ? '正在加载...' : (hasMore ? '上滑加载更多' : '没有更多了') }}
diff --git a/package1/ieBrowser/videoPreview.vue b/package1/ieBrowser/videoPreview.vue
new file mode 100644
index 0000000..0659149
--- /dev/null
+++ b/package1/ieBrowser/videoPreview.vue
@@ -0,0 +1,42 @@
+
+
+
+
+ ‹
+ 视频
+
+
+
+ 视频地址为空
+
+
+
+
+
+