wangfukang 2 weeks ago
parent
commit
bc60436d5b
  1. 58
      package1/ieBrowser/chat.vue
  2. 62
      package1/ieBrowser/profileSetup.vue
  3. 12
      package1/ieBrowser/universe.vue

58
package1/ieBrowser/chat.vue

@ -105,15 +105,17 @@
<text class="profile-info-label">性别</text>
<text>{{ genderText(targetProfile.gender) }}</text>
</view>
<view class="profile-info">
<text class="profile-info-label">想遇见</text>
<text>{{ targetText(targetProfile.targetModePreference, targetProfile.targetGenderPreference) }}</text>
</view>
</view>
<view class="profile-intro">{{ targetProfile.intro || companion.prompt || '这个人还没有写介绍。' }}</view>
<view class="profile-tags" v-if="targetProfile.interestTags && targetProfile.interestTags.length">
<text v-for="tag in targetProfile.interestTags" :key="tag">{{ tag }}</text>
</view>
<view class="profile-persona" v-if="targetProfile.personaImages && targetProfile.personaImages.length">
<view class="profile-section-title">人格卡片</view>
<scroll-view scroll-x class="profile-persona-scroll">
<image class="profile-persona-image" v-for="(img, index) in targetProfile.personaImages" :key="img" :src="img" mode="aspectFill" @tap="previewTargetPersona(index)"></image>
</scroll-view>
</view>
<view class="profile-close" @tap="showTargetProfile = false">继续聊天</view>
</view>
</view>
@ -637,18 +639,10 @@
if (gender === 'female') return '女生'
return '未设置'
},
modePreferenceText(mode) {
if (mode === 'i') return 'i 人'
if (mode === 'e') return 'e 人'
return '都可以'
},
genderPreferenceText(gender) {
if (gender === 'male') return '男生'
if (gender === 'female') return '女生'
return '不限性别'
},
targetText(mode, gender) {
return this.modePreferenceText(mode) + ' · ' + this.genderPreferenceText(gender)
previewTargetPersona(index) {
const images = this.targetProfile.personaImages || []
if (!images.length) return
uni.previewImage({ urls: images, current: images[index] })
},
async openTargetProfile() {
await this.loadTargetProfile()
@ -659,7 +653,8 @@
avatarUrl: this.companion.avatarUrl,
intro: this.companion.prompt,
currentMode: this.roomMode,
interestTags: []
interestTags: [],
personaImages: []
}
}
this.showTargetProfile = true
@ -1347,10 +1342,11 @@
display: flex;
gap: 18rpx;
margin-top: 26rpx;
justify-content: center;
}
.profile-info {
flex: 1;
min-width: 220rpx;
padding: 18rpx 14rpx;
border-radius: 24rpx;
color: rgba(22, 27, 46, 0.72);
@ -1393,6 +1389,32 @@
font-size: 21rpx;
}
.profile-persona {
margin-top: 24rpx;
text-align: left;
}
.profile-section-title {
margin-bottom: 16rpx;
color: rgba(22, 27, 46, 0.72);
font-size: 26rpx;
font-weight: 800;
}
.profile-persona-scroll {
white-space: nowrap;
}
.profile-persona-image {
display: inline-block;
width: 198rpx;
height: 242rpx;
margin-right: 16rpx;
border-radius: 28rpx;
background: rgba(22, 27, 46, 0.06);
box-shadow: 0 16rpx 42rpx rgba(96, 112, 160, 0.12);
}
.profile-close {
height: 82rpx;
line-height: 82rpx;

62
package1/ieBrowser/profileSetup.vue

@ -4,10 +4,10 @@
<view class="nav">
<view class="back" @tap="back"></view>
<view class="title">{{ isEdit ? '编辑 i/e 资料' : '先认识一下你' }}</view>
<view class="step">{{ step }}/4</view>
<view class="step">{{ step }}/5</view>
</view>
<view class="progress"><view :style="{ width: step * 25 + '%' }"></view></view>
<view class="progress"><view :style="{ width: step * 20 + '%' }"></view></view>
<view class="card" v-if="step === 1">
<view class="eyebrow">Your Energy</view>
@ -52,6 +52,22 @@
</view>
<view class="card" v-if="step === 4">
<view class="eyebrow">Persona Cards</view>
<view class="headline">上传你的人格卡片</view>
<view class="card-desc"> QQ 个人主页的形象展示最多 5 别人点头像时可以看到</view>
<view class="persona-grid">
<view class="persona-item" v-for="(img, index) in form.personaImages" :key="img">
<image :src="img" mode="aspectFill" @tap="previewPersona(index)"></image>
<view class="persona-delete" @tap.stop="removePersonaImage(index)">×</view>
</view>
<view class="persona-add" v-if="form.personaImages.length < 5" @tap="choosePersonaImages">
<view class="plus"></view>
<view>添加图片</view>
</view>
</view>
</view>
<view class="card" v-if="step === 5">
<view class="eyebrow">Match Target</view>
<view class="headline">你现在想遇见哪类人</view>
<view class="target-card" v-for="item in targetOptions" :key="item.key" :class="{ active: form.targetModePreference === item.key }" @tap="form.targetModePreference = item.key">
@ -68,7 +84,7 @@
<view class="actions">
<view class="ghost" @tap="prev" v-if="step > 1">上一步</view>
<view class="solid" @tap="next">{{ step === 4 ? '进入 i/e 此刻' : '继续' }}</view>
<view class="solid" @tap="next">{{ step === 5 ? '进入 i/e 此刻' : '继续' }}</view>
</view>
</view>
</template>
@ -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)
@ -172,6 +190,33 @@
}
})
},
choosePersonaImages() {
const remain = 5 - this.form.personaImages.length
if (remain <= 0) {
uni.showToast({ title: '最多上传 5 张', icon: 'none' })
return
}
uni.chooseImage({
count: remain,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: async (res) => {
const files = res.tempFilePaths || []
for (const filePath of files) {
if (this.form.personaImages.length >= 5) break
const result = await tui.uploadFile('/upload/file', filePath)
const url = typeof result === 'string' ? result : (result.url || result.fileUrl || result.path || result.fullPath || result)
if (url && typeof url === 'string') this.form.personaImages.push(url)
}
}
})
},
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' })
@ -187,7 +232,7 @@
async next() {
if (this.submitting) return
if (!this.validateStep()) return
if (this.step < 4) {
if (this.step < 5) {
this.step += 1
return
}
@ -228,6 +273,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; }
@ -252,6 +298,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); }

12
package1/ieBrowser/universe.vue

@ -21,6 +21,12 @@
<view class="tag-panel" v-if="profile.interestTags && profile.interestTags.length">
<view class="tag" v-for="item in profile.interestTags" :key="item">{{ item }}</view>
</view>
<view class="persona-panel" v-if="profile.personaImages && profile.personaImages.length">
<view class="panel-title">人格卡片</view>
<scroll-view scroll-x class="persona-scroll">
<image class="persona-image" v-for="(img, index) in profile.personaImages" :key="img" :src="img" mode="aspectFill" @tap="previewPersona(index)"></image>
</scroll-view>
</view>
<view class="panel">
<view class="panel-title">情绪轨道</view>
<view class="orbit-row" v-for="item in orbit" :key="item.day">
@ -67,6 +73,9 @@
},
back() { uni.redirectTo({ url: '/package1/ieBrowser/index' }) },
editProfile() { uni.navigateTo({ url: '/package1/ieBrowser/profileSetup?edit=1' }) },
previewPersona(index) {
uni.previewImage({ urls: this.profile.personaImages || [], current: this.profile.personaImages[index] })
},
goSettings() { uni.navigateTo({ url: '/package1/ieBrowser/settings' }) }
}
}
@ -92,6 +101,9 @@
.stats text:last-child { margin-top: 8rpx; color: rgba(22,27,46,.42); font-size: 21rpx; }
.tag-panel { display: flex; flex-wrap: wrap; margin-top: 24rpx; padding: 24rpx; border-radius: 32rpx; background: rgba(255,255,255,.58); border: 1rpx solid rgba(255,255,255,.78); }
.tag { margin: 0 12rpx 12rpx 0; padding: 10rpx 18rpx; border-radius: 999rpx; color: #6c69d8; background: rgba(139,124,255,.1); font-size: 22rpx; }
.persona-panel { margin-top: 26rpx; padding: 30rpx; border-radius: 36rpx; background: rgba(255,255,255,.62); border: 1rpx solid rgba(255,255,255,.78); backdrop-filter: blur(24rpx); box-shadow: 0 20rpx 64rpx rgba(96,112,160,.12); }
.persona-scroll { white-space: nowrap; }
.persona-image { display: inline-block; width: 214rpx; height: 260rpx; margin-right: 18rpx; border-radius: 28rpx; background: rgba(22,27,46,.06); box-shadow: 0 16rpx 42rpx rgba(96,112,160,.12); }
.panel { margin-top: 26rpx; padding: 30rpx; border-radius: 36rpx; background: rgba(255,255,255,.62); border: 1rpx solid rgba(255,255,255,.78); backdrop-filter: blur(24rpx); box-shadow: 0 20rpx 64rpx rgba(96,112,160,.12); }
.panel-title { margin-bottom: 24rpx; font-size: 30rpx; font-weight: 800; }
.orbit-row { display: flex; align-items: center; margin-top: 22rpx; }

Loading…
Cancel
Save