提交 c7d02181 作者: 姚志忠

1

父级 f280f663
......@@ -14,6 +14,8 @@ import { CollectionApi, PhotoApi, ItineraryApi, CardApi, PoiApi } from "./api";
const plugin = requirePlugin("indoormap");
const mapKey = "QUIBZ-OTL6U-T2MVM-GMPIT-EON66-LGBCU";
const SUPPORTED_CHINESE_LANGUAGES = ["zh_CN", "zh_TW", "zh_HK"];
const TRANSLATE_GUIDE_SHOWN_KEY = "TRANSLATE_GUIDE_SHOWN";
const buildings = [
{
name: "六区",
......@@ -412,6 +414,15 @@ App({
events: new EventEmitter(),
isIOS: wx.getDeviceInfo().platform === "ios",
onLaunch() {
const appBaseInfo = wx.getAppBaseInfo();
const language = appBaseInfo.language;
const hasShownTranslateGuide = wx.getStorageSync(TRANSLATE_GUIDE_SHOWN_KEY);
const needTranslateGuide =
!SUPPORTED_CHINESE_LANGUAGES.includes(language) && !hasShownTranslateGuide;
this.globalData.needTranslateGuide = needTranslateGuide;
this.globalData.userLang = this.getLangName(language);
this.collectionApi = new CollectionApi(this);
this.photoApi = new PhotoApi(this);
this.itineraryApi = new ItineraryApi(this);
......@@ -431,6 +442,26 @@ App({
const callback = (res) => console.log("userTriggerTranslation", res);
wx.onUserTriggerTranslation(callback);
},
getLangName(wechatLang) {
// 核心语言映射表(中文)
const langMap = {
'zh_CN': '简体中文',
'zh_TW': '繁体中文(台湾)',
'zh_HK': '繁体中文(香港)',
'en': '英语',
'ja': '日语',
'ko': '韩语',
'fr': '法语',
'de': '德语',
'es': '西班牙语',
'ru': '俄语',
'pt': '葡萄牙语',
'it': '意大利语',
'ar': '阿拉伯语'
};
// 找不到时默认返回简体中文
return langMap[wechatLang] || '简体中文';
},
/**
* 首次启动时,根据 GPS 定位自动切换到用户所在的区
*/
......@@ -832,6 +863,18 @@ App({
}
this.userLocation = el;
this.events.emit("userLocation", this.userLocation);
if (el && el.buildingId) {
const targetBuilding = this.buildings.find(
(b) => b.buildingId === el.buildingId
);
// 如果找到了对应的楼栋配置,且与当前楼栋不同,则执行切换
if (targetBuilding && this.currentBuilding.buildingId !== el.buildingId) {
console.log('室内定位触发楼栋切换:', targetBuilding.name);
this.setBuilding(targetBuilding);
}
}
},
});
}
......@@ -904,5 +947,12 @@ App({
? wx.getStorageSync("user")
: null,
isPluginInited: false,
needTranslateGuide: false,
userLang: "zh_CN",
boothNo:null,
},
markTranslateGuideShown() {
this.globalData.needTranslateGuide = false;
wx.setStorageSync(TRANSLATE_GUIDE_SHOWN_KEY, true);
},
});
\ No newline at end of file
<view class="empty">
<image src="./empty.png" class="icon" mode="" />
{{isEn?'No information available yet':'还没有任何信息'}}
<text>{{isEn ? 'No shops found. Check out these featured merchants:' : '没有搜索到商铺,可查看以下实力商家'}}</text>
</view>
\ No newline at end of file
......@@ -24,6 +24,7 @@ Component({
behaviors: [langBehavior, buildingBehavior],
properties: {
type: String,
},
/**
......@@ -42,7 +43,8 @@ Component({
*/
methods: {
handleLang() {
this.setData({ showOptions: true });
// this.setData({ showOptions: true });
this.setData({ showTip: true });
},
closeOptions() {
this.setData({ showOptions: false });
......@@ -83,4 +85,5 @@ Component({
});
},
},
});
......@@ -37,7 +37,6 @@
</view>
</view>
<scroll-view wx:else scroll-x enhanced show-scrollbar="{{false}}" class="langs">
<view class="grid">
<view class="item" wx:for="{{langs}}" wx:key="*this" bind:tap="chooseLang" id="{{item}}">{{item}}
<image wx:if="{{item==='简体中文'&&!isEn||item==='English'&&isEn}}" src="./tick.png" class="tick" mode="" />
......
......@@ -49,6 +49,8 @@ Page({
getLocationSuccess: false,
hasAuth: false,
cardId: null,
needTranslateGuide:false,
userLang:''
},
handleTab({ detail: tab }) {
if (tab.text === "我的" || tab.text === "探索")
......@@ -194,32 +196,58 @@ Page({
this.setData({ banners, showBanner: banners.length > 0 });
getApp().bannerShowed = true;
},
async closeBanner() {
this.setData({ showBanner: false });
},
handleBanner() {
const ad = this.data.banners[0];
if (
(ad.link_type === "app_web" || ad.link_type === "link") &&
ad.link_content
) {
if (!ad) return;
// 埋点
getApp().sensors?.track("MLVajraAreaClick", {
menu_name: ad.name || "首页广告",
});
// 需要登录
if (ad.need_login == 1) {
if (!getApp().checkUser()) {
wx.setStorageSync('AFTER_LOGIN_REDIRECT_URL', ad.link_content);
wx.setStorageSync('AFTER_LOGIN_REDIRECT_TYPE', ad.link_type);
// 跳去登录页(你自己的登录路径)
wx.navigateTo({ url: "/pages/login/login" });
return;
}
}
// 已登录,直接跳转
this.doBannerJump(ad);
},
// 抽出来跳转方法
doBannerJump(ad) {
if (["app_web", "link"].includes(ad.link_type) && ad.link_content) {
wx.navigateTo({
url: `/pages/wap/index?url=${encodeURIComponent(ad.link_content)}`,
});
} else if (
ad.link_type === "mini_program" &&
ad.link_content &&
ad.link_path
) {
wx.navigateToMiniProgram({ appId: ad.link_content, path: ad.link_path });
} else if (ad.link_type === "mini_program" && ad.link_content && ad.link_path) {
wx.navigateToMiniProgram({
appId: ad.link_content,
path: ad.link_path,
});
}
},
async closeBanner() {
this.setData({ showBanner: false });
},
handleBannerIndex({ detail: { current } }) {
this.setData({ bannerIndex: current });
},
async onLoad(options) {
const app = getApp();
this.setData({ needTranslateGuide: getApp().globalData.needTranslateGuide,userLang:getApp().globalData.userLang });
console.log(this.data.needTranslateGuide,'globalData');
// ================= 1. 参数预处理 =================
let { shopId, facilityId, actId, q, fromshare, mode, scene } = options;
......@@ -286,6 +314,7 @@ Page({
this.getFloor();
}
},
onUnload() {
app.events.off("userLocation", this._onLocationChange);
app.events.off("building", this._onBuildingChange);
......
......@@ -47,14 +47,79 @@
}
}
}
.go {
.translate-guide {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 200px;
z-index: 2;
background: #fff;
top: 12px;
right: 14px;
z-index: 3;
display: flex;
flex-direction: column;
align-items: flex-end;
animation: translateGuideEnter 260ms ease-out;
.translate-guide__bubble {
width: 240px;
padding: 14px 14px 12px;
border-radius: 18px;
background: linear-gradient(180deg, rgba(31, 41, 55, 0.96) 0%, rgba(17, 24, 39, 0.96) 100%);
box-shadow: 0 14px 36px rgba(15, 23, 42, 0.28);
color: #fff;
}
.translate-guide__eyebrow {
font-size: 11px;
line-height: 16px;
letter-spacing: 0.8px;
text-transform: uppercase;
color: #93c5fd;
}
.translate-guide__title {
margin-top: 4px;
font-size: 15px;
line-height: 21px;
font-weight: 600;
}
.translate-guide__desc {
margin-top: 6px;
font-size: 12px;
line-height: 18px;
color: rgba(255, 255, 255, 0.82);
}
.translate-guide__lang {
margin-top: 10px;
font-size: 11px;
line-height: 16px;
color: rgba(191, 219, 254, 0.95);
}
.translate-guide__action {
margin-top: 12px;
margin-left: auto;
padding: 6px 12px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.14);
font-size: 12px;
line-height: 16px;
font-weight: 600;
color: #fff;
}
.translate-guide__tail {
width: 0;
height: 0;
margin-top: -2px;
margin-right: 18px;
border-left: 10px solid transparent;
border-right: 4px solid transparent;
border-top: 14px solid rgba(17, 24, 39, 0.96);
transform: rotate(-10deg);
}
}
@keyframes translateGuideEnter {
from {
opacity: 0;
transform: translateY(-8px) scale(0.96);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.banner {
position: fixed;
......@@ -221,4 +286,11 @@
height: 56px;
z-index: 2;
}
.translate-guide {
color: #333;
padding: 8px 16px;
text-align: center;
font-size: 14px;
border-bottom: 1px solid #eee;
}
}
<view class="index">
<map-wrapper type="{{isIndex?'index':'surroundings'}}" viewstate="{{viewstate}}" user-location="{{userLocation}}" acts="{{acts}}" reset-count="{{resetCount}}" floor-name="{{floorName}}" facilities="{{currentFloorFacilities}}" bind:poi="handlePoi" bind:act="handleAct" bind:buildchange="handleMapBuildChange"></map-wrapper>
<lang-btn wx:if="{{!(isIndex&&viewstate==='fullscreen')}}" type="index"></lang-btn>
<lang-btn wx:if="{{!(isIndex&&viewstate==='fullscreen')}}" type="index"></lang-btn>
<bottom-hud-index wx:if="{{isIndex}}" bind:viewstate="handleBottomHudViewstate" bind:search="handleSearch" bind:ai="handleAi" bind:poi="handlePoi">
<floors never-authed="{{neverAuthed}}" show-success="{{getLocationSuccess}}" refreshing="{{gettingLocation}}" wx:if="{{viewstate!=='fullscreen'&&!focusedPoi}}" floors="{{currentBuilding.floors}}" floor-name="{{floorName}}" bind:floorname="handleFloor" bind:resetmap="handleReset"></floors>
</bottom-hud-index>
......
......@@ -11,7 +11,7 @@ Page({
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {},
onLoad(options) { },
checkPrivacy() {
this.setData({ checked: !this.data.checked });
},
......@@ -57,27 +57,23 @@ Page({
async getRedPocketOpenid() {
try {
const { marketurl, post, globalData } = getApp();
const {
data: { code, message },
} = await post(
const { data: { code, message } } = await post(
`${marketurl}/rpt/user/openId`,
{
returnUrl: `https://h5.chinagoods.com/verify-openid/?targetPath=${encodeURIComponent(
"/pages/verify-openId/index"
)}`,
returnUrl: `https://h5.chinqgoods.com/verify-openid/...`,
},
{
Authorization: `Bearer ${globalData.user.access_token}`,
}
);
if (code === 20000) {
wx.redirectTo({
url: `/pages/wap/index?url=${encodeURIComponent(message)}`,
});
return false;
} else return true;
} else {
return true;
}
} catch (error) {
console.log(error);
return true;
}
},
......@@ -87,29 +83,40 @@ Page({
closeModal() {
this.setData({ showModal: false });
},
async handleGetPhone({ detail: { code } }) {
this.setData({ phoneLock: true });
try {
if (code) {
const response = await getApp().login(code);
if (!response)
return wx.showToast({
title: "登录失败",
icon: "none",
});
if (!response) {
wx.showToast({ title: "登录失败", icon: "none" });
return;
}
if (response.code === 20000) {
const redirectUrl = wx.getStorageSync('AFTER_LOGIN_REDIRECT_URL');
const redirectType = wx.getStorageSync('AFTER_LOGIN_REDIRECT_TYPE');
if (redirectUrl) {
// 有广告跳转 → 执行广告跳转
this.afterLoginGoBanner();
return;
}
// 无广告跳转 → 按原有逻辑处理
const hasOpenid = await this.checkRedPocketOpenid();
if (hasOpenid) this.back();
else {
if (hasOpenid) {
this.back();
} else {
await this.getRedPocketOpenid();
this.afterLoginGoBanner();
}
} else if (response.code === 88051) {
return this.setData({ bindingModalData: response.data });
this.setData({ bindingModalData: response.data });
} else {
return wx.showToast({
title: response.message,
icon: "none",
});
wx.showToast({ title: response.message, icon: "none" });
}
}
} catch (error) {
......@@ -118,41 +125,61 @@ Page({
this.setData({ phoneLock: false });
}
},
afterLoginGoBanner() {
// 取出广告跳转信息
const url = wx.getStorageSync('AFTER_LOGIN_REDIRECT_URL');
const type = wx.getStorageSync('AFTER_LOGIN_REDIRECT_TYPE');
if (!url) {
// 没有记录 → 返回上一页
wx.navigateBack();
return;
}
// 清除缓存(避免重复跳转)
wx.removeStorageSync('AFTER_LOGIN_REDIRECT_URL');
wx.removeStorageSync('AFTER_LOGIN_REDIRECT_TYPE');
// 直接跳转到广告链接
wx.redirectTo({
url: `/pages/wap/index?url=${encodeURIComponent(url)}`,
});
},
closeBindingModal() {
this.setData({ bindingModalData: null });
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
onReady() { },
/**
* 生命周期函数--监听页面显示
*/
onShow() {},
onShow() { },
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
onHide() { },
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {},
onUnload() { },
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {},
onPullDownRefresh() { },
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
onReachBottom() { },
/**
* 用户点击右上角分享
*/
onShareAppMessage() {},
onShareAppMessage() { },
});
......@@ -16,12 +16,16 @@ Page({
poi: null,
lastNav: null,
kcal: null,
boothNo: '',
},
/**
* 生命周期函数--监听页面加载
*/
async onLoad(options) {
// 从 options 中获取商位号
this.setData({ boothNo: options.boothNo || '' });
console.log(this.data.boothNo, "boothNo");
const { lastNav } = getApp().globalData;
if (!lastNav) return this.toIndex();
this.setData({ lastNav });
......
......@@ -43,6 +43,11 @@
display: flex;
align-items: center;
justify-content: space-between;
&.booth-row {
.left {
padding-left: 12px;
}
}
.left {
display: inline-flex;
flex-shrink: 0;
......
......@@ -25,6 +25,13 @@
<view>{{lastNav.endPoint.floorName}}</view>
</view>
</view>
<view class="border" wx:if="{{boothNo}}"></view>
<view class="row booth-row" wx:if="{{boothNo}}">
<view class="left">商位号</view>
<view class="right end">
<view>{{boothNo}}</view>
</view>
</view>
</view>
<view class="r3">
<view class="col">
......
......@@ -43,6 +43,7 @@ Page({
url: "/pages/aisearch/index",
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
......
<view class="search">
<search-bar q="{{q}}" bind:q="handleQ" bind:ai="handleAi"></search-bar>
<search-default wx:if="{{!q}}" fac-types="{{facTypes}}" bind:q="handleQ" bind:showbluetoothmodal="openBluetoothModal" bind:showlocationmodal="openLocationModal" bind:showauthmodal="openAuthModal"></search-default>
<search-result wx:if="{{q}}" q="{{q}}" user-location="{{userLocation}}" bind:showbluetoothmodal="openBluetoothModal" bind:showlocationmodal="openLocationModal" bind:showauthmodal="openAuthModal"></search-result>
<search-result wx:if="{{q}}" q="{{q}}" user-location="{{userLocation}}" bind:showbluetoothmodal="openBluetoothModal" bind:showlocationmodal="openLocationModal" bind:showauthmodal="openAuthModal" ></search-result>
<bluetooth-modal wx:if="{{showBluetoothModal}}" bind:close="closeBluetoothModal"></bluetooth-modal>
<location-modal wx:if="{{showLocationModal}}" bind:close="closeLocationModal"></location-modal>
<auth-modal wx:if="{{showAuthModal}}" bind:close="closeAuthModal"></auth-modal>
......
import langBehavior from "../../../behaviors/langBehavior";
import { toRoutePlan, getDistance } from "../../../util";
Component({
behaviors: [langBehavior],
/**
......@@ -19,6 +18,8 @@ Component({
pageNo: 1,
hasMore: true,
allList: [], // 添加存储所有数据的数组
featuredShops: [],//实力商家列表
isLoadingFeatured: false, // 防止重复请求
},
/**
......@@ -56,12 +57,13 @@ Component({
});
try {
// 1. 获取全量 ID 列表 (仅包含 shopId, shopType 等基础字段)
const {
data: { data },
} = await app.post(
`${app.qmurl}/api/v1/applet/searchShopFacilityList`,
{ keyword: q, zone: app.currentBuilding.zone },
{ keyword: q, zone: searchZone },
{ lang: isEn ? "en" : "zh" },
);
......@@ -104,7 +106,7 @@ Component({
userLocation.longitude,
),
);
} catch (e) {}
} catch (e) { }
}
return { ...item, distance };
......@@ -126,28 +128,40 @@ Component({
},
/**
* 内部方法:按需获取详情并渲染
*/
* 内部方法:按需获取详情并渲染
*/
async _processPageData(targetPage) {
const app = getApp();
const { pageSize } = this.data;
this.setData({ isLoading: true });
// 只有在第一页且列表为空时才显示 loading 全屏遮罩,加载更多时通常显示局部 loading
if (targetPage === 1) {
this.setData({ isLoading: true });
}
try {
// 1. 截取当前页需要的 ID (这些 ID 已经是排好序的了)
// 1. 截取当前页需要的 ID
const start = (targetPage - 1) * pageSize;
const end = start + pageSize;
const rawSlice = this.sortedRawList.slice(start, end);
// 如果没有数据可加载
if (rawSlice.length === 0) {
return this.setData({ isLoading: false, hasMore: false });
this.setData({
isLoading: false,
hasMore: false
});
if (targetPage === 1) {
this._handleEmptyResult(); // 这里触发加载实力商家
}
return;
}
// 2. 批量请求详情
const populatedSlice = await app.poiApi.populate(rawSlice, {
targetField: "poi",
// 这里的配置可以省略,如果字段名标准的话
getType: (item) => item.shopType,
getId: (item) => item.shopId,
getBooth: (item) => item.boothNo,
......@@ -158,24 +172,42 @@ Component({
.filter((item) => item.poi)
.map((item) => ({
poi: item.poi,
distance: item.distance, // 直接使用第一步计算好的距离,无需再次计算
distance: item.distance,
}));
// 4. 更新视图
const newList = targetPage === 1
? displaySlice
: [...this.data.list, ...displaySlice];
console.log('newList', newList)
this.setData({
list:
targetPage === 1
? displaySlice
: [...this.data.list, ...displaySlice],
list: newList,
pageNo: targetPage,
hasMore: this.sortedRawList.length > end,
isLoading: false,
});
// 【核心修改】只在第一页且最终结果为空时触发一次
console.log(targetPage, newList.length);
if (targetPage === 1 && newList.length === 0) {
this._handleEmptyResult();
}
} catch (error) {
console.error("分页加载失败", error);
this.setData({ isLoading: false });
}
},
// 【修改】处理搜索结果为空的辅助方法
_handleEmptyResult() {
console.log("搜索结果为空,开始加载实力商家");
// 获取实力商家数据
this.loadFeaturedShops();
},
async addSearchHistory(shopId, isShop) {
const { post, qmurl, globalData } = getApp();
if (!globalData.user) return;
......@@ -209,23 +241,23 @@ Component({
key_word: this.data.q,
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
: {}),
...(poi.facilityId
? {
nav_target_type: poi.facility.name,
}
nav_target_type: poi.facility.name,
}
: {
store_name: poi.ywZh.name,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_cover_img: poi.ywZh.cover,
booth_no: poi.ywZh.boothNo,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
}),
store_name: poi.ywZh.name,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_cover_img: poi.ywZh.cover,
booth_no: poi.ywZh.boothNo,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
}),
});
} catch (error) {
console.error("埋点失败", error);
......@@ -248,24 +280,24 @@ Component({
key_word: this.data.q,
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
: {}),
...(poi.facilityId
? {
nav_target_type: poi.facility.name,
booth_floor: poi.tx.poi_fl_seq,
}
nav_target_type: poi.facility.name,
booth_floor: poi.tx.poi_fl_seq,
}
: {
store_name: poi.ywZh.name,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_cover_img: poi.ywZh.cover,
booth_no: poi.ywZh.boothNo,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
}),
store_name: poi.ywZh.name,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_cover_img: poi.ywZh.cover,
booth_no: poi.ywZh.boothNo,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
}),
});
} catch (error) {
console.error("埋点失败", error);
......@@ -288,24 +320,24 @@ Component({
key_word: this.data.q,
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
: {}),
...(poi.facilityId
? {
nav_target_type: poi.facility.name,
booth_floor: poi.tx.poi_fl_seq,
}
nav_target_type: poi.facility.name,
booth_floor: poi.tx.poi_fl_seq,
}
: {
store_name: poi.ywZh?.name,
booth_addr_street: poi.ywZh?.boothAddrStreet,
booth_cover_img: poi.ywZh?.cover,
booth_no: poi.ywZh?.boothNo,
industry: poi.ywZh?.frontIndustryCategory,
booth_floor: poi.ywZh?.addrFloor,
}),
store_name: poi.ywZh?.name,
booth_addr_street: poi.ywZh?.boothAddrStreet,
booth_cover_img: poi.ywZh?.cover,
booth_no: poi.ywZh?.boothNo,
industry: poi.ywZh?.frontIndustryCategory,
booth_floor: poi.ywZh?.addrFloor,
}),
});
} catch (error) {
console.error("埋点失败", error);
......@@ -337,24 +369,24 @@ Component({
key_word: this.data.q,
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
: {}),
...(poi.facilityId
? {
nav_target_type: poi.facility.name,
booth_floor: poi.tx.poi_fl_seq,
}
nav_target_type: poi.facility.name,
booth_floor: poi.tx.poi_fl_seq,
}
: {
store_name: poi.ywZh.name,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_cover_img: poi.ywZh.cover,
booth_no: poi.ywZh.boothNo,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
}),
store_name: poi.ywZh.name,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_cover_img: poi.ywZh.cover,
booth_no: poi.ywZh.boothNo,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
}),
});
} catch (error) {
console.error("埋点失败", error);
......@@ -378,6 +410,105 @@ Component({
this.getList(true);
}
},
/**
* 【新增】获取当前楼栋的实力商家(前20条)
*/
async loadFeaturedShops() {
// 如果正在加载或已经有数据,则不重复请求
if (this.data.isLoadingFeatured) {
return;
}
const app = getApp();
const { currentBuilding, isEn, marketurl, md5, salt, poiApi } = app;
if (!currentBuilding || !currentBuilding.zone) {
console.warn('当前未选择楼栋,无法获取实力商家');
return;
}
// 【关键修改】即使 data.featuredShops.length > 0,也要允许重新加载
// 因为每次搜索都可能对应不同的楼栋,需要清空旧数据
this.setData({ isLoadingFeatured: true });
try {
// 1. 构造请求参数
const page = 1;
const page_size = 20;
const industryKeyList = currentBuilding.formats ? currentBuilding.formats.map(f => f.key) : [];
const { data: { data: res } } = await app.post(
`${marketurl}/osc/v1/shops/open/toBaiDu/search`,
{
page: page,
page_size: page_size,
industryKeyList: industryKeyList,
lang: isEn ? "en" : "zh",
keySecret: md5(md5(salt + page)),
zone: currentBuilding.zone,
}
);
// 2. 填充 POI 详情
if (res && res.data && res.data.length > 0) {
const filledItems = await poiApi.populate(res.data, {
getType: () => "1",
getId: (i) => i.shopId,
getBooth: (i) => i.boothNo,
targetField: "detail",
});
// 注意:WXML 里使用 item.shopId / item.ywZh 等字段
// 所以这里必须保留 shopId,并且把 poi 详情平铺到 item 上
const shops = filledItems
.map((item) => ({ ...item, ...(item.detail || {}) }))
.filter((item) => item && item.shopId);
this.setData({
featuredShops: shops,
});
} else {
this.setData({ featuredShops: [] });
}
} catch (error) {
console.error("获取实力商家失败", error);
} finally {
this.setData({ isLoadingFeatured: false });
}
},
/**
* 【修改】处理搜索结果为空的回调
* 由父页面或内部逻辑触发
*/
onSearchResultEmpty() {
// 当搜索结果为空时,尝试加载实力商家
this.loadFeaturedShops();
},
/**
* 【新增】点击实力商家跳转
*/
handleFeaturedShopTap(e) {
const { shopid } = e.currentTarget.dataset;
if (!shopid) return;
// 埋点 (可选)
const app = getApp();
app.sensors?.track("FeaturedMerchantClick", {
shop_id: shopid,
source_page: "search_empty_result"
});
// 跳转详情页
wx.navigateTo({
url: `/pages/shop/index?shopId=${shopid}`
});
},
},
lifetimes: {
......@@ -387,6 +518,8 @@ Component({
},
observers: {
q() {
// 每次新搜索时,清空之前的实力商家,以便重新加载当前楼栋的
this.setData({ featuredShops: [] });
this.getList();
},
},
......
.search-result {
width: 100vw;
flex: 1;
height: calc(100vh - 68px);
.list {
......@@ -88,7 +89,7 @@
}
}
.empty {
padding-top: calc(50vh - 88px - 68px);
padding-top: calc(13vh - 88px - 8px);
}
.size-16 {
width: 16px;
......@@ -98,4 +99,93 @@
width: 32px;
height: 32px;
}
.empty-container {
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.empty-tip {
font-size: 14px;
color: #666;
margin-bottom: 20px;
text-align: center;
line-height: 1.5;
}
.featured-list {
width: 100%;
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); // 添加轻微阴影,增加立体感
margin-top: 12px; // 增加与提示语的距离
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
}
.featured-item {
display: flex;
align-items: center;
padding: 12px;
border-bottom: 1px solid #f5f5f5;
}
.featured-item {
display: flex;
align-items: center;
padding: 12px;
border-bottom: 1px solid #f5f5f5;
&:first-child {
margin-top: 16rpx;
}
&:last-child {
border-bottom: none;
}
}
.featured-avatar {
width: 50px;
height: 50px;
border-radius: 4px;
margin-right: 12px;
background-color: #eee;
// 可选:添加圆角边框
border: 1px solid #eee;
}
.featured-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.featured-name {
font-size: 15px;
color: #333;
font-weight: 500;
margin-bottom: 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.featured-addr {
font-size: 12px;
color: #999;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.arrow-icon {
width: 16px;
height: 16px;
margin-left: 8px;
opacity: 0.5;
}
}
<scroll-view scroll-y class="search-result" bindscrolltolower="handleScrollToLower" lower-threshold="200">
<loading wx:if="{{isLoading}}"></loading>
<!-- 有搜索结果:展示结果列表 -->
<view class="list" wx:if="{{list.length}}">
<block wx:for="{{list}}" wx:key="index">
<view class="border" wx:if="{{index>0}}"></view>
......@@ -51,7 +53,27 @@
</block>
<end wx:if="{{!isLoading&&list.length}}"></end>
</view>
<!-- 无搜索结果:展示实力商家(有则展示,无则展示 empty) -->
<view class="empty" wx:if="{{!isLoading&&list.length===0}}">
<empty></empty>
<!-- 实力商家列表 -->
<view class="featured-list" wx:if="{{featuredShops.length > 0}}">
<block wx:for="{{featuredShops}}" wx:key="shopId">
<view class="featured-item" bind:tap="handleFeaturedShopTap" data-shopid="{{item.shopId}}">
<image class="featured-avatar" src="{{item.ywZh.cover}}" mode="aspectFill" />
<view class="featured-info">
<view class="featured-name">
<text>{{isEn && item.ywEn ? item.ywEn.name : item.ywZh.name}}</text>
</view>
<view class="featured-addr">
<text>{{item.ywZh.marketNameDtl}} {{item.ywZh.addrFloor}}F {{item.ywZh.boothNo}}</text>
</view>
</view>
<image class="arrow-icon" src="./arrowright.png" mode="aspectFit" />
</view>
</block>
</view>
</view>
</scroll-view>
\ No newline at end of file
......@@ -40,6 +40,23 @@ Page({
const { isEn } = this.data;
const shop = await app.poiApi.getOne({ shopType: "1", shopId });
if (!shop) return this.back();
const fixCoverUrl = (url) => {
if (!url) return '';
// 将 200x 替换为 空
return url.replace('/200x', '');
};
// 处理中文信息中的 cover
if (shop.ywZh && shop.ywZh.cover) {
shop.ywZh.cover = fixCoverUrl(shop.ywZh.cover);
}
// 处理英文信息中的 cover
if (shop.ywEn && shop.ywEn.cover) {
shop.ywEn.cover = fixCoverUrl(shop.ywEn.cover);
}
const boothNo = shop.ywZh?.boothNo;
try {
let {
......
......@@ -242,6 +242,9 @@ export const toRoutePlan = async (poi, isEn) => {
poi_fl_name: floorName,
bld_id,
} = poi.tx;
console.log(poi,"poi");
// 1. 【新增】获取商位号
const boothNo = poi.ywZh?.boothNo || poi.ywEn?.boothNo || '';
const destPoint = encodeURIComponent(
JSON.stringify({
......@@ -253,8 +256,11 @@ export const toRoutePlan = async (poi, isEn) => {
buildingName: "义乌国际商贸城",
}),
);
// 2. 【关键修改】构建带参数的 navEndPageUrl
const navEndPageUrl = `/pages/nav-end/index?boothNo=${encodeURIComponent(boothNo)}`;
wx.navigateTo({
url: `plugin://indoormap/routeplan?banNav=false&transitDisable=true&buildingId=${bld_id}&buildingName=义乌国际商贸城&destPoint=${destPoint}`,
url: `plugin://indoormap/routeplan?banNav=false&transitDisable=true&buildingId=${bld_id}&buildingName=义乌国际商贸城&destPoint=${destPoint}&navEndPageUrl=${encodeURIComponent(navEndPageUrl)}`,
});
} catch (error) {
console.error(error);
......@@ -290,6 +296,19 @@ export const actToRoutePlan = async (act) => {
return "showLocationModal";
if (!getApp().checkUser()) return "login needed";
getApp().ensurePluginInit();
// 1. 【新增】从 act 对象中获取 shopId 并查询完整 POI 以获取商位号
let boothNo = '';
if (act.shopId) {
try {
const poi = await getApp().poiApi.getOne({ shopType: "1", shopId: act.shopId });
boothNo = poi?.ywZh?.boothNo || poi?.ywEn?.boothNo || '';
} catch (error) {
console.warn('获取活动商铺详情失败,无法传递商位号', error);
}
}
const { name, latitude, longitude, floor_name, building_id } = act;
const destPoint = encodeURIComponent(
......@@ -302,8 +321,11 @@ export const actToRoutePlan = async (act) => {
buildingName: "义乌国际商贸城",
}),
);
// 2. 【关键修改】构建带参数的 navEndPageUrl
const navEndPageUrl = `/pages/nav-end/index?boothNo=${encodeURIComponent(boothNo)}`;
wx.navigateTo({
url: `plugin://indoormap/routeplan?banNav=false&transitDisable=true&buildingId=${building_id}&buildingName=义乌国际商贸城&destPoint=${destPoint}`,
url: `plugin://indoormap/routeplan?banNav=false&transitDisable=true&buildingId=${building_id}&buildingName=义乌国际商贸城&destPoint=${destPoint}&navEndPageUrl=${encodeURIComponent(navEndPageUrl)}`,
});
} catch (error) {
console.error(error);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论