feat(security): 完善超管平台订阅守卫拦截与移动端高意向访客提醒

这个提交包含在:
wikiboss
2026-09-21 11:15:59 +08:00
父节点 654f317c59
当前提交 c58a99d602
共有 7 个文件被更改,包括 93 次插入 和 4 次删除

查看文件

@@ -18,6 +18,13 @@
>
<text class="hall-tab-text">{{ t('tabTeam') }}</text>
</view>
<view
class="hall-tab"
:class="{ 'hall-tab-active': state.tab === 'event' }"
@click="handleTab('event')"
>
<text class="hall-tab-text">{{ t('tabEvent') }}</text>
</view>
</view>
<input
class="hall-search"
@@ -35,6 +42,15 @@
:placeholder="exchangePlaceholder"
:disabled="state.loading"
/>
<input
v-if="state.tab === 'event'"
class="hall-search"
type="text"
maxlength="6"
v-model="state.eventCode"
:placeholder="eventPlaceholder"
:disabled="state.loading"
/>
</view>
<view v-if="state.loading" class="hall-skeleton">
@@ -89,6 +105,7 @@ import {
openHallPortal,
refreshHall,
resolveHallText,
submitHallEventJoin,
submitHallExchange,
} from './useHall.uts';
@@ -113,11 +130,15 @@ const pageTitle = ref(resolveHallText('title'));
const pageSubtitle = ref(resolveHallText('subtitle'));
const searchPlaceholder = ref(resolveHallText('searchPlaceholder'));
const exchangePlaceholder = ref(resolveHallText('exchangePlaceholder'));
const eventPlaceholder = ref(resolveHallText('eventPlaceholder'));
const emptyDesc = computed((): string => {
if (state.tab === 'team') {
return resolveHallText('teamEmpty');
}
if (state.tab === 'event') {
return resolveHallText('eventEmpty');
}
return pageSubtitle.value;
});
@@ -125,6 +146,9 @@ const ctaLabel = computed((): string => {
if (state.loading) {
return resolveHallText('loading');
}
if (state.tab === 'event' && state.eventCode.trim() !== '') {
return resolveHallText('eventJoin');
}
if (state.exchangeCode.trim() !== '') {
return resolveHallText('exchange');
}
@@ -152,6 +176,10 @@ function handleOpenPortal(item: HallContactItem): void {
}
async function handlePrimary(): Promise<void> {
if (state.tab === 'event' && state.eventCode.trim() !== '') {
await submitHallEventJoin(state);
return;
}
if (state.exchangeCode.trim() !== '') {
await submitHallExchange(state);
return;

查看文件

@@ -3,6 +3,11 @@
<view class="leads-header">
<text class="leads-title">{{ pageTitle }}</text>
<text class="leads-subtitle">{{ followUpLabel }}</text>
<text
v-if="hotUnreadText !== ''"
class="radar-hot-badge"
@click="openRadar"
>{{ hotUnreadText }}</text>
<view v-if="radarLineOne !== ''" class="radar-preview">
<text class="radar-preview-text">{{ radarLineOne }}</text>
<text v-if="radarLineTwo !== ''" class="radar-preview-text">{{ radarLineTwo }}</text>
@@ -115,6 +120,7 @@ import {
applyLeadStatusFilter,
applyLeadsOptions,
createLeadsState,
formatHotUnread,
formatLeadCompany,
formatRadarLine,
openRadarPage,
@@ -149,6 +155,9 @@ const searchPlaceholder = ref(resolveLeadsText('searchPlaceholder'));
const scoreLabel = ref(resolveLeadsText('score'));
const briefingLabel = ref(resolveOverviewText('title'));
const radarMoreLabel = ref(resolveLeadsText('radarMore'));
const hotUnreadText = computed((): string => {
return formatHotUnread(state.hotUnread);
});
const radarLineOne = computed((): string => {
if (state.radarTracks.length < 1) {
return '';
@@ -250,6 +259,19 @@ onLoad((options: LeadsPageOptions) => {
margin-bottom: var(--oc-space-8, 8px);
}
.radar-hot-badge {
min-height: 44px;
min-width: 44px;
padding-inline: 12px;
margin-bottom: var(--oc-space-12, 12px);
background-color: var(--oc-primary-soft, #EAF1FF);
color: var(--oc-primary, #0B5CFF);
border-radius: 12px;
font-size: 13px;
font-weight: 600;
line-height: 44px;
}
.radar-preview {
margin-bottom: var(--oc-space-12, 12px);
padding: var(--oc-space-12, 12px);

查看文件

@@ -8,10 +8,13 @@ import {
OwnerPageData,
OwnerPageQuery,
RadarTrack,
TeamRankItem,
} from '../../../common/types.uts';
import {
fetchCurrentEvent,
fetchOwnerLeadPage,
fetchOwnerRadarPage,
fetchTeamLiveRank,
} from '../../../common/api.uts';
import { getCurrentLocale, getOmniText } from '../../../common/locale.uts';
@@ -27,7 +30,8 @@ export type OverviewCopyKey =
| 'empty'
| 'error'
| 'loading'
| 'unknownCountry';
| 'unknownCountry'
| 'rankTitle';
export type OverviewSummary = {
totalLeads: number;
@@ -49,6 +53,8 @@ export type LoadOverviewApi = {
fetchOwnerRadarPage?: (
query: OwnerPageQuery
) => Promise<OwnerPageData<RadarTrack>>;
fetchTeamLiveRank?: (eventId?: string) => Promise<TeamRankItem[]>;
fetchCurrentEvent?: () => Promise<{ code?: string } | null>;
};
export type LoadOverviewResult = {

查看文件

@@ -10,7 +10,11 @@ import {
OwnerPageQuery,
RadarTrack,
} from '../../common/types.uts';
import { fetchOwnerLeadPage, fetchOwnerRadarPage } from '../../common/api.uts';
import {
fetchOwnerLeadPage,
fetchOwnerRadarPage,
fetchRadarHotInbox,
} from '../../common/api.uts';
import { getCurrentLocale, getOmniText } from '../../common/locale.uts';
import { formatLocation, formatStay } from './useRadar.uts';
@@ -29,7 +33,8 @@ export type LeadsCopyKey =
| 'error'
| 'loading'
| 'score'
| 'radarMore';
| 'radarMore'
| 'hotBadge';
export type LoadLeadsQuery = {
page: number;
@@ -58,6 +63,7 @@ export type LoadLeadsResult = {
export type LeadsState = {
list: LeadEntity[];
radarTracks: RadarTrack[];
hotUnread: number;
page: number;
size: number;
total: number;
@@ -154,9 +160,19 @@ export function resolveLeadsText(key: LeadsCopyKey): string {
if (key === 'radarMore') {
return zh ? '查看全部雷达' : 'Full radar';
}
if (key === 'hotBadge') {
return zh ? '高意向访客' : 'Hot visitors';
}
return '';
}
export function formatHotUnread(unread: number): string {
if (unread < 1) {
return '';
}
return `${resolveLeadsText('hotBadge')} ${unread}`;
}
export function statusLabel(status: string): string {
if (status === 'new') {
return resolveLeadsText('statusNew');
@@ -244,6 +260,7 @@ export function createLeadsState(): LeadsState {
return {
list: [],
radarTracks: [],
hotUnread: 0,
page: 1,
size: 20,
total: 0,
@@ -318,6 +335,12 @@ export async function refreshLeads(
} catch (_err) {
state.radarTracks = [];
}
try {
const inbox = await fetchRadarHotInbox();
state.hotUnread = inbox != null && inbox.unread != null ? inbox.unread : 0;
} catch (_err) {
state.hotUnread = 0;
}
state.loading = false;
return result;
}