| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- <template>
- <view class="detail-page">
- <!-- 顶部蓝色背景 + 顶栏 -->
- <view class="top-bg">
- <view class="detail-header">
- <view class="back" @click="goBack">
- <image class="header-icon-img" src="/static/icons/back.svg" mode="aspectFit" />
- </view>
- <!-- 右上角不显示三个点,但保留占位,避免标题中心抖动 -->
- <view class="header-actions" />
- </view>
- <view class="hero">
- <view class="hero-avatar">
- <UserAvatar
- :name="contactName"
- :id="contactId"
- :src="''"
- :size="140"
- unit="rpx"
- />
- </view>
- <view class="hero-names">
- <text class="hero-main-name">{{ contactName || '联系人' }}</text>
- <text class="hero-sub-name">{{ contactEnglishName || '' }}</text>
- </view>
- </view>
- </view>
- <!-- 三个按钮:消息 / 语言 / 视频 -->
- <view class="action-row">
- <view class="action-item" @click="goChat">
- <image class="action-icon" src="/static/icons/message.svg" mode="aspectFit" />
- <text class="action-label">消息</text>
- </view>
- <view class="action-item" :class="{ 'is-hidden': !showVoiceVideo }" @click="onVoice">
- <image class="action-icon" src="/static/icons/file.svg" mode="aspectFit" />
- <text class="action-label">语音</text>
- </view>
- <view class="action-item" :class="{ 'is-hidden': !showVoiceVideo }" @click="onVideo">
- <image class="action-icon" src="/static/icons/video.svg" mode="aspectFit" />
- <text class="action-label">视频</text>
- </view>
- </view>
- <!-- 备注名行 -->
- <view class="remark-row">
- <text class="remark-label">备注名</text>
- <view class="remark-right">
- <text class="remark-value">{{ contactName || '' }}</text>
- </view>
- </view>
- </view>
- </template>
- <script>
- import UserAvatar from '../../components/UserAvatar.vue'
- export default {
- components: { UserAvatar },
- data() {
- return {
- contactId: '',
- contactName: '',
- contactEnglishName: '',
- contactStatus: '',
- // 需求:先隐藏“语音/视频”,但要保持“消息”位置和样式不变
- showVoiceVideo: false,
- loading: false
- }
- },
- computed: {},
- onLoad(options) {
- const rawContactId = options?.contactId ?? options?.otherUserId ?? ''
- const rawContactName = options?.contactName ?? ''
- const rawContactEnglishName = options?.contactEnglishName ?? ''
- const rawContactStatus = options?.contactStatus ?? ''
- // uni-app 在某些端上不会自动对 query 参数解码,避免直接显示 %E5... URL 编码结果
- const maybeDecode = (v) => {
- const s = String(v ?? '')
- // 仅当包含 %xx 形式时才尝试解码,避免重复解码造成破坏
- if (!/%[0-9A-Fa-f]{2}/.test(s)) return s
- try {
- return decodeURIComponent(s)
- } catch (e) {
- return s
- }
- }
- this.contactId = String(rawContactId)
- this.contactName = maybeDecode(rawContactName)
- this.contactEnglishName = maybeDecode(rawContactEnglishName)
- this.contactStatus = maybeDecode(rawContactStatus)
- this.loading = false
- },
- methods: {
- goBack() {
- uni.navigateBack()
- },
- onMore() {
- uni.showToast({ title: '更多', icon: 'none' })
- },
- goChat() {
- const id = String(this.contactId || '').trim()
- if (!id) {
- uni.showToast({ title: '无法进入聊天', icon: 'none' })
- return
- }
- uni.navigateTo({
- url:
- '/pages/chat/index?otherUserId=' +
- encodeURIComponent(id) +
- '&contactName=' +
- encodeURIComponent(this.contactName || '')
- })
- }
- ,
- onVoice() {
- uni.showToast({ title: '语音', icon: 'none' })
- },
- onVideo() {
- uni.showToast({ title: '视频', icon: 'none' })
- }
- }
- }
- </script>
- <style scoped>
- .detail-page {
- height: 100vh;
- display: flex;
- flex-direction: column;
- background: #f5f5f7;
- }
- .top-bg {
- position: relative;
- background: linear-gradient(180deg, #2b7de9 0%, #5aa9ff 100%);
- padding-bottom: 48rpx;
- }
- .top-bg::after {
- content: '';
- position: absolute;
- left: 0;
- right: 0;
- /* 让蓝->白分界线与按钮卡片顶部重叠,同时避免中间空白露出蓝色 */
- bottom: -20rpx;
- /* 拉长白色覆盖层:向下延长但保持顶部边界不变 */
- height: 300rpx;
- background: #f5f5f7;
- border-top-left-radius: 40rpx;
- border-top-right-radius: 40rpx;
- transform: skewY(0deg);
- }
- .detail-header {
- position: relative;
- z-index: 2;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 24rpx 24rpx 24rpx 24rpx;
- padding-top: max(88rpx, calc(24rpx + constant(safe-area-inset-top)));
- padding-top: max(88rpx, calc(24rpx + env(safe-area-inset-top)));
- }
- .back {
- width: 64rpx;
- height: 64rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .header-icon-img {
- width: 44rpx;
- height: 44rpx;
- opacity: 0.95;
- }
- .header-actions {
- width: 64rpx;
- height: 64rpx;
- display: flex;
- align-items: center;
- justify-content: flex-end;
- }
- .header-icon {
- width: 56rpx;
- height: 56rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .hero {
- position: relative;
- z-index: 2;
- padding-top: 16rpx;
- padding-bottom: 28rpx;
- }
- .hero-avatar {
- margin-left: 46rpx;
- margin-bottom: 18rpx;
- }
- .hero-avatar :deep(.user-avatar) {
- box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.18);
- }
- .hero-names {
- margin-left: 40rpx;
- text-align: left;
- }
- .hero-main-name {
- display: block;
- font-size: 44rpx;
- font-weight: 700;
- color: #111827;
- }
- .hero-sub-name {
- display: block;
- margin-top: 10rpx;
- font-size: 28rpx;
- font-weight: 600;
- color: #111827;
- }
- .action-row {
- position: relative;
- z-index: 1;
- margin-top: -40rpx;
- padding: 0 40rpx;
- display: flex;
- gap: 28rpx;
- justify-content: space-between;
- }
- .action-item {
- flex: 1;
- background: #ffffff;
- border-radius: 18rpx;
- padding: 26rpx 0;
- display: flex;
- flex-direction: column;
- /* 图标和文字居中 */
- align-items: center;
- justify-content: center;
- box-shadow: 0 2rpx 10rpx rgba(17, 24, 39, 0.06);
- }
- /* 隐藏语音/视频但不改变布局:只隐藏内容,保留三个格子的宽度 */
- .action-item.is-hidden {
- visibility: hidden;
- pointer-events: none;
- }
- .action-icon {
- width: 54rpx;
- height: 54rpx;
- opacity: 0.95;
- }
- .action-label {
- margin-top: 12rpx;
- font-size: 28rpx;
- color: #111827;
- text-align: center;
- }
- .remark-row {
- position: relative;
- z-index: 1;
- margin: 28rpx 28rpx 0;
- background: #ffffff;
- border-radius: 18rpx;
- padding: 26rpx 28rpx;
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
- .remark-label {
- font-size: 28rpx;
- color: #111827;
- }
- .remark-right {
- display: flex;
- align-items: center;
- gap: 16rpx;
- }
- .remark-value {
- font-size: 28rpx;
- color: #6b7280;
- }
- </style>
|