fix(theme): 修复门票页导航栏主题脱节与个人中心双身份卡片流光动画,加固活动参与人画像与大神隐私
这个提交包含在:
@@ -38,7 +38,8 @@ export function formatActivityData(raw) {
|
||||
startTime: raw.startTime || '',
|
||||
location: raw.location || '',
|
||||
creatorId: raw.creatorId != null ? Number(raw.creatorId) : (raw.creator_id != null ? Number(raw.creator_id) : 0),
|
||||
creatorNickname: raw.creatorNickname || '',
|
||||
// 创建人已被删除时给出真实状态,避免列表显示空白局长
|
||||
creatorNickname: raw.creatorNickname || '局长已注销',
|
||||
creatorAvatar: raw.creatorAvatar || '',
|
||||
status: raw.status || (joinedCount >= (raw.maxParticipants || 4) ? 'FULL' : 'RECRUITING'),
|
||||
allowDynamicPrice: Boolean(raw.allowDynamicPrice),
|
||||
@@ -236,7 +237,7 @@ export async function getCompanions(keyword) {
|
||||
price: Number(c.hourlyRate) || 0,
|
||||
rating: Number(c.rating) || 0,
|
||||
orderCount: Number(c.orderCount) || 0,
|
||||
isOnline: c.status === '接单中',
|
||||
isOnline: c.isOnline !== undefined ? Boolean(c.isOnline) : c.status === '接单中',
|
||||
voiceDuration: Number(c.voiceDuration) || 0,
|
||||
voiceType: 'voice',
|
||||
voiceTitle: c.voiceTitle || '',
|
||||
@@ -267,7 +268,6 @@ export async function matchCompanions(options = {}) {
|
||||
const list = Array.isArray(res) ? res : (res && Array.isArray(res.list) ? res.list : []);
|
||||
return list.map((c) => ({
|
||||
id: String(c.id),
|
||||
userId: Number(c.userId) || 0,
|
||||
nickname: c.nickname || '',
|
||||
avatar: c.avatar || '',
|
||||
gender: c.gender === '男' ? 'male' : (c.gender === '女' ? 'female' : ''),
|
||||
|
||||
@@ -72,7 +72,10 @@
|
||||
<text class="sec-title">组局阵地与发起人</text>
|
||||
</view>
|
||||
<view class="creator-box">
|
||||
<image class="creator-avatar btn-active" :src="activity.creatorAvatar" mode="aspectFill" @click="openHostProfile" />
|
||||
<image v-if="activity.creatorAvatar" class="creator-avatar btn-active" :src="activity.creatorAvatar" mode="aspectFill" @click="openHostProfile" />
|
||||
<view v-else class="creator-avatar creator-avatar-empty btn-active" @click="openHostProfile">
|
||||
<text class="creator-avatar-placeholder">?</text>
|
||||
</view>
|
||||
<view class="creator-info btn-active" @click="openHostProfile">
|
||||
<view class="creator-name-row">
|
||||
<text class="creator-name">{{ activity.creatorNickname }}</text>
|
||||
@@ -1147,6 +1150,21 @@ const handleJoin = () => {
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.creator-avatar-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(148, 163, 184, 0.18);
|
||||
border: 1px solid rgba(148, 163, 184, 0.3);
|
||||
|
||||
.creator-avatar-placeholder {
|
||||
font-size: 30rpx;
|
||||
color: #94A3B8;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.creator-info {
|
||||
|
||||
@@ -140,7 +140,10 @@
|
||||
<!-- 底部房主与价格 -->
|
||||
<view class="card-footer">
|
||||
<view class="creator-info">
|
||||
<image class="creator-avatar" :src="act.creatorAvatar" mode="aspectFill" />
|
||||
<image v-if="act.creatorAvatar" class="creator-avatar" :src="act.creatorAvatar" mode="aspectFill" />
|
||||
<view v-else class="creator-avatar creator-avatar-empty">
|
||||
<text class="creator-avatar-placeholder">?</text>
|
||||
</view>
|
||||
<text class="creator-name">局长:{{ act.creatorNickname }}</text>
|
||||
</view>
|
||||
|
||||
@@ -346,9 +349,9 @@ onUnmounted(() => {
|
||||
});
|
||||
|
||||
const getCategoryTagClass = (game) => {
|
||||
if (game === '美食陪吃') return 'tag-meal';
|
||||
if (game === '同城陪唱') return 'tag-sing';
|
||||
if (game === '下午茶陪喝' || game === '同城微醺') return 'tag-drink';
|
||||
if (game === '美食陪吃' || game === '美食探店') return 'tag-meal';
|
||||
if (game === '同城陪唱' || game === 'KTV嗨唱') return 'tag-sing';
|
||||
if (game === '下午茶陪喝' || game === '下午茶歇' || game === '同城微醺') return 'tag-drink';
|
||||
return '';
|
||||
};
|
||||
|
||||
@@ -802,6 +805,20 @@ const createActivity = () => {
|
||||
height: 48rpx;
|
||||
border-radius: 24rpx;
|
||||
margin-right: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.creator-avatar-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(148, 163, 184, 0.18);
|
||||
border: 1px solid rgba(148, 163, 184, 0.3);
|
||||
|
||||
.creator-avatar-placeholder {
|
||||
font-size: 22rpx;
|
||||
color: #94A3B8;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
.creator-name {
|
||||
font-size: 22rpx;
|
||||
|
||||
@@ -251,7 +251,7 @@ import AppTabBar from '@/components/CustomTabBar.vue';
|
||||
import { ICONS } from '@/common/icons.js';
|
||||
import { getCurrentThemeKey, applyThemeToNativeUI } from '@/common/theme.js';
|
||||
import { isExpertCertified } from '@/common/role.js';
|
||||
import { claimOrder, getOrdersPool, getExpertStats, updateCompanionProfile, getUserProfile, getActivities, normalizeUserId } from '@/common/api.js';
|
||||
import { claimOrder, getOrdersPool, getExpertStats, updateCompanionProfile, getUserProfile, getActivities, getMyExpertProfile, normalizeUserId } from '@/common/api.js';
|
||||
import { getUserLocation } from '@/common/location.js';
|
||||
import { startHeartbeat, stopHeartbeat } from '@/common/expert-heartbeat.js';
|
||||
import { getNavBarInfo } from '@/common/nav.js';
|
||||
@@ -363,6 +363,15 @@ const loadHallData = async () => {
|
||||
}
|
||||
}).catch(() => {}),
|
||||
|
||||
getMyExpertProfile().then((profile) => {
|
||||
if (profile && profile.status) {
|
||||
isOnline.value = profile.status === '接单中';
|
||||
uni.setStorageSync('EXPERT_RECEIVING_STATUS', isOnline.value ? '1' : '0');
|
||||
if (isOnline.value) startHeartbeat();
|
||||
else stopHeartbeat();
|
||||
}
|
||||
}).catch(() => {}),
|
||||
|
||||
getOrdersPool(myCoords).then((pool) => {
|
||||
if (Array.isArray(pool)) {
|
||||
orders.value = pool.map(p => {
|
||||
@@ -475,26 +484,37 @@ const filteredOrders = computed(() => {
|
||||
});
|
||||
|
||||
const toggleOnlineStatus = async () => {
|
||||
isOnline.value = !isOnline.value;
|
||||
uni.setStorageSync('EXPERT_RECEIVING_STATUS', isOnline.value ? '1' : '0');
|
||||
const eid = Number(expert.value.id) || normalizeUserId();
|
||||
if (!eid) {
|
||||
uni.showToast({ title: '请先登录后再操作', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const next = !isOnline.value;
|
||||
isOnline.value = next;
|
||||
uni.setStorageSync('EXPERT_RECEIVING_STATUS', next ? '1' : '0');
|
||||
try {
|
||||
await updateCompanionProfile(eid, {
|
||||
status: isOnline.value ? '接单中' : '休息中'
|
||||
status: next ? '接单中' : '休息中'
|
||||
});
|
||||
} catch (_) {}
|
||||
if (isOnline.value) {
|
||||
} catch (err) {
|
||||
// 服务端失败必须回滚本地状态,避免界面显示在线但实际不接单
|
||||
isOnline.value = !next;
|
||||
uni.setStorageSync('EXPERT_RECEIVING_STATUS', !next ? '1' : '0');
|
||||
stopHeartbeat();
|
||||
uni.showToast({
|
||||
title: (err && err.message) || '接单状态切换失败,请稍后重试',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (next) {
|
||||
startHeartbeat();
|
||||
} else {
|
||||
stopHeartbeat();
|
||||
}
|
||||
uni.showToast({
|
||||
title: isOnline.value ? '已开启在线接单' : '已设置为打烊休息',
|
||||
icon: isOnline.value ? 'success' : 'none',
|
||||
title: next ? '已开启在线接单' : '已设置为打烊休息',
|
||||
icon: next ? 'success' : 'none',
|
||||
duration: 1500
|
||||
});
|
||||
};
|
||||
|
||||
@@ -562,6 +562,13 @@ const loadExpertProfile = async () => {
|
||||
voiceIntroUrl: profile.voiceIntroUrl || '',
|
||||
voiceDuration: Number(profile.voiceDuration) || 0
|
||||
};
|
||||
// 以服务端接单状态为准,避免本地缓存显示在线但实际已休息
|
||||
if (profile.status) {
|
||||
isReceivingOrders.value = profile.status === '接单中';
|
||||
uni.setStorageSync('EXPERT_RECEIVING_STATUS', isReceivingOrders.value ? '1' : '0');
|
||||
if (isReceivingOrders.value) startHeartbeat();
|
||||
else stopHeartbeat();
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
};
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<view class="section-title-wrap">
|
||||
<view class="section-title">
|
||||
<view class="title-line"></view>
|
||||
<text>精选在线大神</text>
|
||||
<text>精选大神</text>
|
||||
</view>
|
||||
<view class="section-more btn-active" @click="startInstantMatch">
|
||||
<view class="pulse-point"></view>
|
||||
|
||||
在新工单中引用
屏蔽一个用户