提交 4847926a 作者: anergin00

update init

父级 a39267af
import CollectionApi from "./apis/CollectionApi";
import PhotoApi from "./apis/PhotoApi";
import ItineraryApi from "./apis/ItineraryApi";
export { CollectionApi, PhotoApi, ItineraryApi };
import CardApi from "./apis/CardApi";
import PoiApi from "./apis/PoiApi";
export { CollectionApi, PhotoApi, ItineraryApi, CardApi, PoiApi };
export default class CardApi {
constructor(app) {
this.app = app;
}
async getByZone(zoneCode) {
const { qmurl, post } = this.app;
try {
const {
data: { code, data },
} = await post(`${qmurl}/api/v1/applet/getActivityByZone`, {
zoneCode,
});
if (code === 200) {
return data?.activityId;
}
return null;
} catch (error) {
console.error(error);
return null;
}
}
async get(activityId) {
const { qmurl, post, globalData } = this.app;
if (!globalData.user) return null;
try {
const {
data: { code, data },
} = await post(`${qmurl}/api/v1/applet/getActivityInfo`, {
userId: globalData.user.user.userId,
activityId,
});
if (code === 200) {
return data;
}
return null;
} catch (error) {
console.error(error);
return null;
}
}
async check(poi) {
const { qmurl, post, globalData } = this.app;
if (!globalData.user) return false;
if (!poi) return false;
try {
const {
data: { code, data },
} = await post(`${qmurl}/api/v1/applet/checkInActivity`, {
userId: globalData.user.user.userId,
token: globalData.user.access_token,
shopType: poi.facility ? 2 : 1,
shopId: poi.shopId ? poi.shopId : poi.facilityId,
boothNo: poi.shopId ? poi.ywZh?.boothNo : undefined,
});
if (code === 200) return data;
return false;
} catch (error) {
console.error(error);
return false;
}
}
}
......@@ -75,15 +75,16 @@ export default class PhotoApi {
}
}
async search(imageUrl, rect) {
const { marketurl, post, globalData } = this.app;
if (!globalData.user) return false;
if (!imageUrl) return false;
const { marketurl, post, globalData, currentBuilding } = this.app;
if (!globalData.user) throw new Error("用户未登录");
if (!imageUrl) throw new Error("没有图片url");
if (!rect) {
try {
const { width, height } = await wx.getImageInfo({ src: imageUrl });
rect = { width, height, x: 0, y: 0 };
} catch (error) {
console.error(error);
throw new Error("获取图片宽高失败");
}
}
try {
......@@ -92,12 +93,13 @@ export default class PhotoApi {
} = await post(`${marketurl}/detector/baidu/image/search`, {
imageRectDto: rect,
imageUrl,
marketCode: currentBuilding.marketCode,
});
if (code === 20000) return data;
return null;
throw new Error("接口返回code不是20000");
} catch (error) {
console.error(error);
return null;
throw new Error("接口异常");
}
}
}
import { getShopMainGoods, getStarredPhone } from "../util";
export default class PoiApi {
constructor(app) {
this.app = app;
this.MAX_CACHE_SIZE = 1000;
this.poiCache = new Map();
// 内存不足时自动清理
if (wx.onMemoryWarning) {
wx.onMemoryWarning((res) => {
console.warn("Memory warning, clearing POI cache:", res.level);
this.poiCache.clear();
});
}
}
// LRU 缓存设置
_setCache(key, value) {
if (this.poiCache.has(key)) this.poiCache.delete(key);
this.poiCache.set(key, value);
if (this.poiCache.size > this.MAX_CACHE_SIZE) {
this.poiCache.delete(this.poiCache.keys().next().value);
}
}
_getCacheKey({ shopType, shopId, boothNo }) {
return `${shopType}_${shopId}_${boothNo || ""}`;
}
// 数据预处理
_processShopData(item) {
if (!item) return item;
// 简单判断是否为店铺逻辑:type=1 或 有ID且无facilityId
const isShop = item.shopType === "1" || (item.shopId && !item.facilityId);
if (isShop) {
try {
item.maingoods = getShopMainGoods(item, false);
item.maingoodsEn = getShopMainGoods(item, true);
if (item.ywZh?.contactPhone)
item.contactPhone = getStarredPhone(item.ywZh.contactPhone);
if (item.ywEn?.contactPhone)
item.contactPhoneEn = getStarredPhone(item.ywEn.contactPhone);
} catch (e) {
console.error("Format shop data error:", e);
}
}
return item;
}
// --- 核心底层方法:批量获取 (含缓存) ---
async getListByIds(params) {
if (!Array.isArray(params) || params.length === 0) return [];
const uncachedParams = [];
const resultMap = {};
// 1. 缓存分流
params.forEach((param) => {
if (!param) return; // 跳过 populate 产生的无效占位
const key = this._getCacheKey(param);
if (this.poiCache.has(key)) {
const val = this.poiCache.get(key);
this._setCache(key, val); // 刷新 LRU
resultMap[key] = val;
} else {
uncachedParams.push(param);
}
});
// 2. 网络请求 (仅请求未命中的)
if (uncachedParams.length > 0) {
try {
const { qmurl, post } = this.app;
const {
data: { data },
} = await post(
`${qmurl}/api/v1/applet/getShopFacilityPoiListBatch`,
uncachedParams.map(({ shopType, shopId, boothNo }) => ({
shopType,
shopId,
boothNo,
})),
);
if (Array.isArray(data)) {
data.forEach((item, index) => {
const param = uncachedParams[index];
if (param && item) {
this._processShopData(item);
const key = this._getCacheKey(param);
this._setCache(key, item);
resultMap[key] = item;
}
});
}
} catch (e) {
console.error("Batch fetch error:", e);
}
}
// 3. 按原顺序返回
return params.map((param) => {
if (!param) return null;
return resultMap[this._getCacheKey(param)] || null;
});
}
// --- 业务层方法 ---
/**
* 智能填充列表 (Page层主要调用此方法)
*/
async populate(list, options = {}) {
if (!Array.isArray(list) || list.length === 0) return [];
const {
getType = (item) => item.shopType,
getId = (item) => item.shopId,
getBooth = (item) => item.boothNo,
targetField = "poi",
} = options;
// 1. 构造请求参数 (保持索引对应)
const params = list.map((item) => {
const type = getType(item);
const id = getId(item);
// 仅处理合法的店铺(1)或设施(2)
if ((type == 1 || type == 2) && id) {
return {
shopType: String(type),
shopId: id,
boothNo: getBooth(item) || "",
};
}
return null;
});
// 2. 批量获取
const details = await this.getListByIds(params);
// 3. 回填数据
return list
.map((item, index) => {
const detail = details[index];
return detail ? { ...item, [targetField]: detail } : null;
})
.filter(Boolean);
}
/**
* 获取单条详情 (复用 populate)
*/
async getOne({ shopType, shopId, boothNo }) {
const res = await this.populate([{ shopType, shopId, boothNo }], {
targetField: "detail",
});
return res[0]?.detail || null;
}
async getTx() {
try {
const {
data: { data },
} = await this.app.get(
`${this.app.qmurl}/api/v1/applet/getShopFacilityPoiSummary`,
);
return data;
} catch (e) {
console.error(e);
return null;
}
}
}
......@@ -11,7 +11,11 @@
"pages/aisearchresult/index",
"pages/itinerary/index",
"pages/nav-end/index",
"pages/poi-map/index"
"pages/poi-map/index",
"pages/verify-openId/index",
"pages/card-detail/index",
"pages/feedback/index",
"pages/explore/index"
],
"permission": {
"scope.userLocation": {
......@@ -34,7 +38,7 @@
"provider": "wx069ba97219f66d99"
},
"indoormap": {
"version": "1.3.27",
"version": "1.3.32",
"provider": "wxfe8f0709a4de371b",
"export": "pluginReport.js"
}
......
module.exports = Behavior({
behaviors: [],
properties: {},
data: {
currentBuilding: getApp().currentBuilding,
},
lifetimes: {
attached() {
this.setData({ currentBuilding: getApp().currentBuilding });
this.setBuilding = (currentBuilding) => {
this.setData({ currentBuilding });
if (this.onCurrentBuildingChange)
this.onCurrentBuildingChange(currentBuilding);
};
getApp().events.on("building", this.setBuilding);
},
detached() {
getApp().events.off("building", this.setBuilding);
},
},
});
......@@ -28,14 +28,13 @@ module.exports = Behavior({
},
methods: {
async toggleCollection(poi) {
const { collectionApi } = getApp();
const { collectionApi, buildingIdNameMap } = getApp();
try {
let success;
const collected = this.isCollected(poi);
try {
getApp().sensors?.track("CollectNavPosition", {
action_type: collected ? "取消收藏" : "收藏",
short_market_name: "二区东",
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
......@@ -46,8 +45,10 @@ module.exports = Behavior({
? {
nav_target_type: poi.facility.name,
booth_floor: poi.tx.poi_fl_seq,
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
: {
short_market_name: poi.ywZh.marketNameDtl,
store_name: poi.ywZh.name,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_cover_img: poi.ywZh.cover,
......
......@@ -6,8 +6,15 @@ Component({
/**
* 组件的初始数据
*/
data: { isIOS: getApp().isIOS },
data: { isIOS: getApp().isIOS, isSystem: true },
lifetimes: {
attached() {
const appAuthorizeSetting = wx.getAppAuthorizeSetting();
this.setData({
isSystem: appAuthorizeSetting.bluetoothAuthorized === "authorized",
});
},
},
/**
* 组件的方法列表
*/
......@@ -15,6 +22,13 @@ Component({
close() {
this.triggerEvent("close");
},
openAppAuthorizeSetting() {
wx.openAppAuthorizeSetting({
success(res) {
console.log(res);
},
});
},
doNothing() {},
},
});
......@@ -16,20 +16,47 @@
height: 100vh;
.image {
position: absolute;
top: 32px;
top: 120px;
left: 0;
right: 0;
margin: auto;
width: 304px;
height: 572px;
width: 302px;
height: 396px;
z-index: 1;
}
.close {
position: absolute;
top: 130px;
right: calc(50vw - 151px + 10px);
width: 32px;
height: 32px;
z-index: 2;
}
.btn {
position: absolute;
top: 542px;
top: 452px;
left: 0;
right: 0;
margin: auto;
width: 260px;
height: 38px;
z-index: 2;
}
.btn1 {
position: absolute;
top: 452px;
left: calc(50vw - 126px - 4px);
width: 126px;
height: 38px;
z-index: 2;
}
.btn2 {
position: absolute;
top: 452px;
right: calc(50vw - 126px - 4px);
margin: auto;
width: 126px;
height: 38px;
z-index: 2;
}
}
<textarea disabled class="bluetooth-bg"></textarea>
<view class="bluetooth-modal" bind:tap="close">
<image wx:if="{{isIOS}}" class="image" catch:tap="donothing" src="https://cdnimg.chinagoods.com/png/2025/09/01/dacfdaux2wtvloq0mfvhd48otw8gplir.png" mode="" />
<image wx:else catch:tap="donothing" class="image" src="https://cdnimg.chinagoods.com/png/2025/09/01/mbx4nn2dwya3xovr7lp1yfhzrn6qgxsq.png" catch:tap="doNothing" mode="" />
<block wx:if="{{isSystem}}">
<image wx:if="{{isIOS}}" class="image" catch:tap="doNothing" src="https://cdnimg.chinagoods.com/png/2025/10/30/iowxo8oegleiwnzm1lci81ngipjqxrkm.png" mode="" />
<image wx:else catch:tap="doNothing" class="image" src="https://cdnimg.chinagoods.com/png/2025/10/30/65vtmu6ebrcalmekbb9bimrykmcpnsqi.png" catch:tap="doNothing" mode="" />
<view class="btn" catch:tap="close"></view>
</block>
<block wx:else>
<image wx:if="{{isIOS}}" class="image" catch:tap="doNothing" src="https://cdnimg.chinagoods.com/png/2025/10/30/fu5mur0sheld26mgetp8hjddzh7fh64i.png" mode="" />
<image wx:else catch:tap="doNothing" class="image" src="https://cdnimg.chinagoods.com/png/2025/10/30/br1lik6ag7902e2kjmz3iy0ep5ctvkj6.png" catch:tap="doNothing" mode="" />
<view class="btn1" catch:tap="close"></view>
<view class="btn2" catch:tap="openAppAuthorizeSetting"></view>
</block>
<view class="close" catch:tap="close"></view>
</view>
\ No newline at end of file
......@@ -21,6 +21,13 @@ Component({
activeIcon: "./selectedSurroundings.png",
},
{
url: "/pages/explore/index",
text: "探索",
textEn: "Explore",
icon: "./explore.png",
activeIcon: "./selectedExplore.png",
},
{
url: "/pages/mine/index",
text: "我的",
textEn: "My",
......@@ -36,7 +43,7 @@ Component({
methods: {
handleTap({ currentTarget: { id } }) {
if (
["0", "1", "2"].includes(id) &&
["0", "1", "2", "3"].includes(id) &&
this.data.currentIndex !== Number(id)
) {
const { currentIndex } = this.data;
......
import langBehavior from "../../behaviors/langBehavior";
import buildingBehavior from "../../behaviors/buildingBehavior";
Component({
behaviors: [langBehavior],
behaviors: [langBehavior, buildingBehavior],
properties: {
floors: Array,
floorName: String,
......@@ -16,7 +17,18 @@ Component({
/**
* 组件的初始数据
*/
data: {},
data: {
reversedFloors: [],
scrollTop: 0,
},
observers: {
floors() {
this.setData({ reversedFloors: [...this.data.floors].reverse() });
},
"floorName,reversedFloors"() {
this.scrollToCurrent();
},
},
/**
* 组件的方法列表
......@@ -28,5 +40,28 @@ Component({
handleFloor({ currentTarget: { id: floorName } }) {
this.triggerEvent("floorname", floorName);
},
scrollToCurrent() {
if (this.scollContext) {
const index = this.data.reversedFloors.findIndex(
(item) => item === this.data.floorName
);
if (index > -1) {
const scrollTop = Math.max(0, (index - 2) * 36);
this.setData({ scrollTop });
}
}
},
},
lifetimes: {
attached() {
this.setData({ reversedFloors: [...this.data.floors].reverse() });
this.createSelectorQuery()
.select("#floors")
.node((res) => {
this.scollContext = res.node;
this.scrollToCurrent();
})
.exec();
},
},
});
......@@ -115,11 +115,9 @@
display: flex;
flex-direction: column;
top: -152px;
&.has-reset {
top: -202px;
}
right: 10px;
padding: 7px 4px;
left: 10px;
padding: 7px 0;
width: 40px;
z-index: 2;
gap: 2px;
align-items: center;
......@@ -131,10 +129,17 @@
width: 8px;
height: 3px;
}
.scroller {
width: 40px;
height: 104px;
.list {
display: flex;
width: 40px;
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 0 4px;
box-sizing: border-box;
.floor {
display: flex;
width: 32px;
......@@ -154,14 +159,12 @@
}
}
}
}
}
.floors-mask {
position: absolute;
top: -152px;
&.has-reset {
top: -202px;
}
right: 10px;
left: 10px;
width: 40px;
height: 128px;
z-index: 1;
......
......@@ -15,9 +15,10 @@
<textarea disabled class="floors-mask {{showReset?'has-reset':''}}"></textarea>
<view class="floors {{showReset?'has-reset':''}}">
<image class="arrow" src="./floorUp.png" mode="" />
<scroll-view id="floors" scroll-y scroll-top="{{scrollTop}}" class="scroller" enhanced>
<view class="list">
<view wx:for="{{floors}}" class="floor {{floorName===item.floorName?'active':''}}" id="{{item.floorName}}" wx:key="floorName" bind:tap="handleFloor">{{item.displayName}}</view>
<view wx:for="{{reversedFloors}}" class="floor {{floorName===item?'active':''}}" id="{{item}}" wx:key="*this" bind:tap="handleFloor">{{item}}</view>
</view>
</scroll-view>
<image class="arrow" src="./floorDown.png" mode="" />
</view>
\ No newline at end of file
import langBehavior from "../../behaviors/langBehavior";
import buildingBehavior from "../../behaviors/buildingBehavior";
const langs = [
"简体中文",
"English",
"العربية",
// "العربية",
// "日本語",
"한국어",
"Deutsch",
"Français",
"Português",
"Español",
"Italiano",
"Bahasa Melayu",
"русский",
"Bahasa Indonesia",
"ภาษาไทย",
"Türkçe",
"繁體中文 香港/澳門",
"繁體中文 中國臺灣",
"Tiếng Việt",
// "한국어",
// "Deutsch",
// "Français",
// "Português",
// "Español",
// "Italiano",
// "Bahasa Melayu",
// "русский",
// "Bahasa Indonesia",
// "ภาษาไทย",
// "Türkçe",
// "繁體中文 香港/澳門",
// "繁體中文 中國臺灣",
// "Tiếng Việt",
];
Component({
behaviors: [langBehavior],
behaviors: [langBehavior, buildingBehavior],
properties: {
type: String,
},
......@@ -32,6 +33,8 @@ Component({
showOptions: false,
langs,
showTip: false,
buildings: getApp().buildings,
showBuildings: false,
},
/**
......@@ -44,6 +47,12 @@ Component({
closeOptions() {
this.setData({ showOptions: false });
},
openBuildings() {
this.setData({ showBuildings: true });
},
closeBuildings() {
this.setData({ showBuildings: false });
},
chooseLang({ currentTarget: { id: lang } }) {
if (
(lang === "简体中文" && this.data.isEn) ||
......@@ -60,5 +69,17 @@ Component({
this.setData({ showTip: false });
},
donothing() {},
changeBuilding({ currentTarget: { id } }) {
const building = this.data.buildings[id];
getApp().setBuilding(building);
getApp().blurPoi();
this.setData({ showBuildings: false });
},
handleFeedback() {
if (!getApp().checkUser()) return;
wx.navigateTo({
url: `/pages/feedback/index`,
});
},
},
});
.logo {
width: 24px;
height: 24px;
}
.langBtn {
position: absolute;
z-index: 2;
......@@ -6,13 +10,16 @@
display: flex;
flex-direction: column;
width: 40px;
height: 64px;
height: 50px;
gap: 2px;
justify-content: center;
align-items: center;
border-radius: 8px;
background: #fff;
box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
&.index {
height: 150px;
}
&.white {
background: none;
box-shadow: none;
......@@ -25,13 +32,9 @@
color: #f3f3f3;
}
}
.logo {
width: 24px;
height: 24px;
}
.texts {
display: flex;
height: 24px;
flex-direction: column;
color: #333;
text-align: center;
......@@ -42,6 +45,49 @@
line-height: 12px; /* 120% */
}
}
.marketLang {
position: absolute;
z-index: 2;
top: 10px;
right: 10px;
display: flex;
flex-direction: column;
width: 40px;
height: 102px;
gap: 10px;
justify-content: center;
align-items: center;
border-radius: 8px;
background: #fff;
box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
&.index {
height: 150px;
}
.btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
color: #333;
text-align: center;
font-family: "PingFang SC";
font-size: 10px;
font-style: normal;
font-weight: 400;
line-height: 12px;
}
}
.lang-bg {
position: absolute;
z-index: 1;
top: 10px;
right: 10px;
width: 40px;
height: 64px;
&.index {
height: 102px;
}
}
.options-bg {
position: absolute;
z-index: 3000;
......@@ -52,6 +98,9 @@
border-radius: 0 0 8px 8px;
border-top: #f3f3f3;
background: #fff;
&.tmp {
height: 108px;
}
}
.options {
position: absolute;
......@@ -60,6 +109,9 @@
right: 0;
width: 100vw;
height: 196px;
&.tmp {
height: 108px;
}
.close {
position: absolute;
top: 16px;
......@@ -79,12 +131,49 @@
font-weight: 600;
line-height: 18px;
}
.row {
position: absolute;
top: 56px;
left: 0;
display: flex;
height: 40px;
width: 100vw;
padding: 0 12px;
gap: 4px;
.item {
position: relative;
display: flex;
align-items: center;
padding-left: 10px;
flex: 1;
height: 40px;
border-radius: 4px;
border-bottom: 0.5px solid rgba(255, 255, 255, 0.1);
background: #f7f7f7;
color: #333;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 18px;
.tick {
position: absolute;
width: 12px;
height: 12px;
top: 0;
bottom: 0;
right: 18px;
margin: auto;
}
}
}
.langs {
position: absolute;
top: 56px;
left: 0;
width: 100vw;
height: 128px;
.grid {
width: 1064px;
height: 128px;
......@@ -165,3 +254,52 @@
height: 38px;
}
}
.buildings-bg {
position: absolute;
z-index: 3000;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
}
.buildings {
position: absolute;
z-index: 3001;
top: 10px;
right: 55px;
display: inline-flex;
padding: 2px;
flex-direction: column;
align-items: flex-start;
border-radius: 8px;
background: #4a4a4a;
.tri {
position: absolute;
top: 14px;
right: -3px;
width: 3px;
height: 10px;
}
.building {
display: flex;
padding-left: 10px;
padding-right: 10px;
align-items: center;
min-width: 140px;
height: 40px;
gap: 6px;
color: #fff;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 600;
line-height: 16px;
}
.building + .building {
border-top: 1px solid rgba(255, 255, 255, 0.06);
}
}
.size-12 {
width: 12px;
height: 12px;
}
<view class="langBtn {{type}}" catch:tap="handleLang">
<view wx:if="{{type==='index'}}" class="marketLang {{type}}">
<view class="btn" catch:tap="openBuildings">
<image class="logo" src="./market.png" mode="" />
<view>{{isEn?'Market':'市场'}}</view>
</view>
<view class="btn" catch:tap="handleLang">
<image class="logo" src="./switch.png" mode="" />
<view>{{isEn?'Lang':'语言'}}</view>
</view>
<view class="btn" catch:tap="handleFeedback">
<image class="logo" src="./feedback.png" mode="" />
<view>{{isEn?'Report':'反馈'}}</view>
</view>
</view>
<view wx:else class="langBtn {{type}}" catch:tap="handleLang">
<block wx:if="{{type==='white'}}">
<image class="logo" src="./switchWhite.png" mode="" />
</block>
......@@ -9,16 +23,21 @@
<image class="logo" src="./switch.png" mode="" />
</block>
<view class="texts" wx:if="{{type!== 'white'}}">
<view>{{isEn?'Change':'更换'}}</view>
<view>{{isEn?'Lang':'语言'}}</view>
</view>
</view>
<textarea disabled class="options-bg" wx:if="{{showOptions}}"></textarea>
<view wx:if="{{showOptions}}" class="options">
<textarea disabled class="lang-bg {{type}}"></textarea>
<textarea disabled class="options-bg {{langs.length===2?'tmp':''}}" wx:if="{{showOptions}}"></textarea>
<view wx:if="{{showOptions}}" class="options {{langs.length===2?'tmp':''}}">
<view class="t1">{{isEn?'Change language':'更换语言'}}</view>
<image src="./close.png" class="close" mode="" bind:tap="closeOptions" />
<scroll-view scroll-x enhanced show-scrollbar="{{false}}" class="langs">
<view wx:if="{{langs.length===2}}" class="row">
<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="" />
</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="" />
......@@ -32,3 +51,12 @@
<image catch:tap="donothing" class="image" src="https://cdnimg.chinagoods.com/png/2025/09/03/e3evgoktoetqebfymujhse0kmoxzjkt8.png" mode="" />
<view class="btn" catch:tap="closeTip"></view>
</view>
<textarea disabled class="buildings-bg" wx:if="{{showBuildings}}" bind:tap="closeBuildings"></textarea>
<view class="buildings" wx:if="{{showBuildings}}">
<image src="./tri.png" class="tri" mode="" />
<view wx:for="{{buildings}}" class="building" id="{{index}}" wx:key="name" catch:tap="changeBuilding">
<image wx:if="{{currentBuilding.name===item.name}}" class="size-12" src="./checked.png" mode="" />
<image wx:else class="size-12" src="./unchecked.png" mode="" />
{{isEn ? item.displayNameEn: item.displayName}}
</view>
</view>
\ No newline at end of file
......@@ -6,8 +6,15 @@ Component({
/**
* 组件的初始数据
*/
data: { isIOS: getApp().isIOS },
data: { isIOS: getApp().isIOS, isSystem: true },
lifetimes: {
attached() {
const appAuthorizeSetting = wx.getAppAuthorizeSetting();
this.setData({
isSystem: appAuthorizeSetting.locationAuthorized === "authorized",
});
},
},
/**
* 组件的方法列表
*/
......@@ -15,6 +22,13 @@ Component({
close() {
this.triggerEvent("close");
},
openAppAuthorizeSetting() {
wx.openAppAuthorizeSetting({
success(res) {
console.log(res);
},
});
},
doNothing() {},
},
});
......@@ -16,20 +16,47 @@
height: 100vh;
.image {
position: absolute;
top: 32px;
top: 120px;
left: 0;
right: 0;
margin: auto;
width: 304px;
height: 572px;
width: 302px;
height: 396px;
z-index: 1;
}
.close {
position: absolute;
top: 130px;
right: calc(50vw - 151px + 10px);
width: 32px;
height: 32px;
z-index: 2;
}
.btn {
position: absolute;
top: 542px;
top: 452px;
left: 0;
right: 0;
margin: auto;
width: 260px;
height: 38px;
z-index: 2;
}
.btn1 {
position: absolute;
top: 452px;
left: calc(50vw - 126px - 4px);
width: 126px;
height: 38px;
z-index: 2;
}
.btn2 {
position: absolute;
top: 452px;
right: calc(50vw - 126px - 4px);
margin: auto;
width: 126px;
height: 38px;
z-index: 2;
}
}
<textarea disabled class="bluetooth-bg"></textarea>
<view class="bluetooth-modal" bind:tap="close">
<image wx:if="{{isIOS}}" class="image" catch:tap="donothing" src="https://cdnimg.chinagoods.com/png/2025/09/01/l5z7pr16cdmgrjxqzwtkps1fl5m4yaiy.png" mode="" />
<image wx:else catch:tap="donothing" class="image" src="https://cdnimg.chinagoods.com/png/2025/09/01/6rkar7dc5ot10homibl4ohrnrun8vwtq.png" catch:tap="doNothing" mode="" />
<block wx:if="{{isSystem}}">
<image wx:if="{{isIOS}}" class="image" catch:tap="doNothing" src="https://cdnimg.chinagoods.com/png/2025/10/30/d9bcjoms6szz980q0ngpmaddd59v0jwh.png" mode="" />
<image wx:else catch:tap="doNothing" class="image" src="https://cdnimg.chinagoods.com/png/2025/10/30/srefp3tal0ys1ztdqnkdao8lhrg0pvul.png" catch:tap="doNothing" mode="" />
<view class="btn" catch:tap="close"></view>
</block>
<block wx:else>
<image wx:if="{{isIOS}}" class="image" catch:tap="doNothing" src="https://cdnimg.chinagoods.com/png/2025/10/30/o8oxwdtxr651n3ocmvanea8arvzsz95y.png" mode="" />
<image wx:else catch:tap="doNothing" class="image" src="https://cdnimg.chinagoods.com/png/2025/10/30/gk0taraemutjyhsrbfpzrupz3aqvttj2.png" catch:tap="doNothing" mode="" />
<view class="btn1" catch:tap="close"></view>
<view class="btn2" catch:tap="openAppAuthorizeSetting"></view>
</block>
<view class="close" catch:tap="close"></view>
</view>
\ No newline at end of file
<map class="map" id="indexMap" show-compass show-location="{{userLocation&&!(userLocation&&userLocation.floorName&&userLocation.floorName!==floorName)}}" enable-rotate enable-3D enable-overlooking enable-auto-max-overlooking enable-indoor subkey="QUIBZ-OTL6U-T2MVM-GMPIT-EON66-LGBCU" latitude="{{latitude}}" longitude="{{longitude}}" markers="{{markers}}" max-scale="22" setting="{{setting}}" bind:tap="{{type === 'index' ? 'handleTap' : ''}}" bind:poitap="{{type === 'index' ? 'handleTap' : ''}}" bind:markertap="{{type === 'surroundings' ? 'handleMarkerTap' : ''}}" bind:callouttap="{{type === 'index' ? 'handleCalloutTap' : ''}}" bind:indoorchange="handleIndoorChange"></map>
\ No newline at end of file
<map wx:if="{{latitude&&longitude}}" class="map" id="indexMap" show-compass show-location="{{userLocation&&!(userLocation&&userLocation.floorName&&userLocation.floorName!==floorName)}}" enable-rotate enable-3D enable-overlooking enable-auto-max-overlooking enable-indoor subkey="QUIBZ-OTL6U-T2MVM-GMPIT-EON66-LGBCU" latitude="{{latitude}}" longitude="{{longitude}}" max-scale="22" setting="{{setting}}" bind:tap="{{type === 'index' ? 'handleTap' : ''}}" bind:poitap="{{type === 'index' ? 'handleTap' : ''}}" bind:markertap="{{type === 'surroundings' ? 'handleMarkerTap' : ''}}" bind:callouttap="{{type === 'index' ? 'handleCalloutTap' : ''}}" bind:indoorchange="handleIndoorChange"></map>
\ No newline at end of file
......@@ -36,13 +36,14 @@ Component({
async handleGo() {
const { isEn, focusedPoi: poi, isIndex } = this.data;
try {
const { buildingIdNameMap } = getApp();
getApp().sensors?.track("NavEntryBtnClick", {
page_name: isIndex ? "导航弹出框" : "周边弹出框",
short_market_name: "二区东",
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
: {}),
...(poi.facilityId
......
<view class="popup" wx:if="{{focusedPoi}}">
<slot></slot>
<view class="shop" wx:if="{{focusedPoi.facility&&focusedPoi.facility.name==='yandoocafe'}}">
<view class="shop" wx:if="{{focusedPoi.facility&&focusedPoi.facility.type===2}}">
<image wx:if="{{focusedPoi.facility.logo}}" src="{{focusedPoi.facility.logo}}" class="avatar" mode="" />
<view class="right">
<view class="c-gap-6">
......
import md5 from "./md5";
const app = "indoor";
const secret = "ysGsjd08sUxPsxz2";
/**
* 使用md5加密方式发起请求
* @param {*} url
* @param {*} queryData path为加密参数,必传
* @param {*} options
*/
function MD5Request(url, queryData = {}, options = {}) {
// 是否loading
if (options && options.loading) {
wx.showLoading({
title: "加载中",
mask: true,
});
}
const secretParams = getCommonReqParams(queryData);
url = url + queryData.path || "";
delete queryData.path;
const method = (options && options.method) || "GET";
return new Promise((resolve, reject) => {
wx.request({
url,
data: queryData,
method,
header: {
"Content-Type": "application/json; charset=UTF-8",
...secretParams,
},
success(res) {
resolve(res.data);
},
fail(e) {
console.log(e);
reject(e);
},
complete() {
if (options && options.delay) {
setTimeout(() => {
wx.hideLoading();
}, options.delay);
} else {
wx.hideLoading();
}
},
...options,
});
});
}
// 加密参数
function getCommonReqParams(params) {
const ts = Date.parse(new Date()) / 1000;
const path = params.path;
const sign = md5(path + secret + ts);
return {
app,
ts,
sign,
};
}
export default MD5Request;
......@@ -67,9 +67,9 @@ Page({
}
},
async takePhoto() {
const { state, states } = this.data;
try {
wx.showLoading();
const { state, states } = this.data;
if (state !== states.init) return;
this.setData({ state: states.takingPhoto, isAlbum: false });
const ctx = wx.createCameraContext();
......@@ -235,10 +235,6 @@ Page({
});
const shopId = params.shopId;
if (shopId) {
const { shopIdMap } = getApp();
if (!shopIdMap) return;
const shop = shopIdMap[shopId];
if (!shop) return;
wx.navigateTo({
url: `/pages/poi-map/index?shopId=${shopId}`,
});
......

1.0 KB | W: | H:

637 Bytes | W: | H:

pages/aisearchresult/add.png
pages/aisearchresult/add.png
pages/aisearchresult/add.png
pages/aisearchresult/add.png
  • 2-up
  • Swipe
  • Onion skin

951 Bytes | W: | H:

774 Bytes | W: | H:

pages/aisearchresult/added.png
pages/aisearchresult/added.png
pages/aisearchresult/added.png
pages/aisearchresult/added.png
  • 2-up
  • Swipe
  • Onion skin
import langBehavior from "../../behaviors/langBehavior";
import modalBehavior from "../../behaviors/modalBehavior";
import { toRoutePlan, getDistance } from "../../util";
import { toRoutePlan, getDistance, nearDistrict2East } from "../../util";
import mockData from "./mock.js";
const sortByStates = {
nosort: "nosort",
distanceDesc: "distanceDesc",
distanceAsc: "distanceAsc",
priceDesc: "priceDesc",
priceAsc: "priceAsc",
};
Page({
behaviors: [langBehavior, modalBehavior],
data: {
photoUrl: "",
rectVoList: [],
originalList: [],
voList: [],
currentIndex: 0,
itineraryMap: {},
userLocation: null,
sortByStates,
sortBy: sortByStates.nosort,
},
/**
......@@ -17,12 +29,16 @@ Page({
*/
async onLoad({ photoUrl }) {
this.setUserLocation = () => {
this.setData({ userLocation: getApp().userLocation });
const { userLocation } = getApp();
if (
userLocation &&
(userLocation.buildingId || nearDistrict2East(userLocation))
)
this.setData({ userLocation });
};
getApp().events.on("userLocation", this.setUserLocation);
this.setUserLocation();
photoUrl = decodeURIComponent(photoUrl);
await this.init(photoUrl);
if (!this.data.rectVoList.length) {
......@@ -50,67 +66,137 @@ Page({
app.events.off("itineraryRefresh", this.setItineraryMap);
}
},
handleDistanceSort() {
if (
this.data.sortBy !== sortByStates.distanceDesc &&
this.data.sortBy !== sortByStates.distanceAsc
) {
this.setData({ sortBy: sortByStates.distanceAsc });
} else if (this.data.sortBy === sortByStates.distanceAsc) {
this.setData({ sortBy: sortByStates.distanceDesc });
} else {
this.setData({ sortBy: sortByStates.nosort });
}
this.setSortedList();
},
handlePriceSort() {
if (
this.data.sortBy !== sortByStates.priceDesc &&
this.data.sortBy !== sortByStates.priceAsc
) {
this.setData({ sortBy: sortByStates.priceAsc });
} else if (this.data.sortBy === sortByStates.priceAsc) {
this.setData({ sortBy: sortByStates.priceDesc });
} else {
this.setData({ sortBy: sortByStates.nosort });
}
this.setSortedList();
},
handleNoSort() {
this.setData({ sortBy: sortByStates.nosort });
this.setSortedList();
},
setSortedList() {
if (!this.data.originalList || !Array.isArray(this.data.originalList))
return;
let list = [...this.data.originalList];
if (this.data.sortBy === sortByStates.nosort)
return this.setData({ voList: list });
list.sort((a, b) => {
switch (this.data.sortBy) {
case sortByStates.distanceAsc:
case sortByStates.distanceDesc:
// 无论升序还是降序,distance为null的元素都排在最后
if (a.distance === null && b.distance === null) return 0;
if (a.distance === null) return 1;
if (b.distance === null) return -1;
// 正常的距离比较
return this.data.sortBy === sortByStates.distanceAsc
? a.distance - b.distance
: b.distance - a.distance;
case sortByStates.priceAsc:
return a.price - b.price;
case sortByStates.priceDesc:
return b.price - a.price;
default:
return 0;
}
});
this.setData({ voList: list });
},
async init(photoUrl) {
try {
wx.showLoading();
console.log(photoUrl);
const { photoApi } = getApp();
const { rectVoList = [], voList } = await photoApi.search(photoUrl);
const originalList = await this.processVoList(voList);
this.setData({
photoUrl,
rectVoList: [{ cutImageURL: photoUrl }, ...rectVoList],
voList: this.processVoList(voList),
originalList,
});
this.setSortedList();
} catch (error) {
console.error(error);
const originalList = await this.processVoList(mockData.voList);
this.setData({
photoUrl,
rectVoList: [{ cutImageURL: photoUrl }],
originalList,
});
this.setSortedList();
} finally {
wx.hideLoading();
}
},
processVoList(voList) {
const { shopIdMap } = getApp();
const result = voList
.map((good) => ({
...good,
shop: shopIdMap && shopIdMap[good.shopId],
}))
.filter(({ shop }) => shop);
result.forEach((good) => {
try {
good.yuan = Math.floor(good.price);
good.fen =
"." + String(Math.round(good.price * 100) % 100).padStart(2, "0");
} catch (error) {
good.yuan = good.price;
console.error(error);
}
const poi = good.shop;
if (!poi.tx) good.distance = null;
if (!this.data.userLocation) good.distance = null;
async processVoList(voList) {
if (!Array.isArray(voList)) return [];
// 1. 批量填充
const list = await getApp().poiApi.populate(voList, {
getType: () => "1",
getId: (item) => item.shopId,
targetField: "shop",
});
const { userLocation } = this.data;
// 2. 过滤 + 格式化 (价格 & 距离)
return list
.filter((item) => item?.shop)
.map((item) => {
// 价格格式化
const price = Number(item.price) || 0;
item.yuan = Math.floor(price);
item.fen = `.${String(Math.round(price * 100) % 100).padStart(2, "0")}`;
// 距离计算
const tx = item.shop.tx;
if (tx && userLocation) {
try {
const lat = Number(poi.tx.poi_location.latitude);
const lng = Number(poi.tx.poi_location.longitude);
good.distance = Math.ceil(
getDistance(
lat,
lng,
this.data.userLocation.latitude,
this.data.userLocation.longitude
)
const dist = getDistance(
Number(tx.poi_location.latitude),
Number(tx.poi_location.longitude),
userLocation.latitude,
userLocation.longitude,
);
} catch (error) {
good.distance = null;
}
try {
// 楼层不同增加 60m 距离
const floorDiff = Math.abs(
Number(poi.tx.poi_fl_name[0]) -
Number(this.data.userLocation.floorName[0])
parseInt(tx.poi_fl_name) - parseInt(userLocation.floorName),
);
if (floorDiff && good.distance) good.distance += floorDiff;
} catch (error) {}
if (good.distance > 3000) good.distance = null;
item.distance = Math.ceil(dist) + (floorDiff > 0 ? 60 : 0);
} catch (e) {
console.error(e);
}
}
return item;
});
return result;
},
async handleRectImg(e) {
const {
......@@ -127,10 +213,12 @@ Page({
const res = await photoApi.search(this.data.photoUrl, rectVo.rect);
if (res.voList) {
const originalList = await this.processVoList(res.voList);
this.setData({
voList: this.processVoList(res.voList),
originalList,
currentIndex: Number(index),
});
this.setSortedList();
}
} catch (error) {
console.error(error);
......@@ -159,7 +247,13 @@ Page({
app.refreshItinerary();
}
wx.showToast({
title: success ? (isEn ? "success" : "成功") : isEn ? "fail" : "失败",
title: success
? isEn
? "success"
: "取消收藏"
: isEn
? "fail"
: "失败",
icon: "none",
});
} else {
......@@ -173,7 +267,7 @@ Page({
app.refreshItinerary();
}
wx.showToast({
title: id ? (isEn ? "success" : "成功") : isEn ? "fail" : "失败",
title: id ? (isEn ? "success" : "收藏成功") : isEn ? "fail" : "失败",
icon: "none",
});
}
......@@ -185,13 +279,14 @@ Page({
const { isEn, voList } = this.data;
const { shop: poi } = voList[index];
try {
const { buildingIdNameMap } = getApp();
getApp().sensors?.track("NavEntryBtnClick", {
page_name: "AI识物结果",
short_market_name: "二区东",
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
short_market_name: buildingIdNameMap[poi.tx.bld_id],
}
: {}),
...(poi.facilityId
......
......@@ -83,10 +83,35 @@
bottom: 0;
border-radius: 16px 16px 0;
background: #f7f7f7;
padding: 8px 10px 0 10px;
padding: 4px 10px 0 10px;
display: flex;
flex-direction: column;
gap: 10px;
gap: 4px;
.tabs {
display: flex;
padding: 0 21px;
align-items: center;
justify-content: space-between;
&.dual {
padding: 0 77px;
}
.tab {
display: inline-flex;
align-items: center;
height: 38px;
color: #333;
text-align: center;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 400;
gap: 4px;
.icon {
width: 10px;
height: 16px;
}
}
}
.title {
display: flex;
align-items: baseline;
......@@ -109,7 +134,7 @@
.scroll-y {
width: 100%;
flex: 1;
height: calc(100vh - 117px);
height: calc(100vh - 145px);
.goods {
display: inline-flex;
flex-direction: column;
......@@ -149,6 +174,7 @@
font-style: normal;
font-weight: 600;
line-height: 22px;
padding-right: 20px;
}
.t2 {
display: flex;
......@@ -203,20 +229,25 @@
position: absolute;
bottom: 0;
right: 0;
top: 0;
display: flex;
flex-direction: column;
gap: 24px;
.row {
align-items: flex-end;
justify-content: space-between;
.collect {
display: flex;
gap: 6px;
flex-direction: column;
gap: 2px;
align-items: center;
.t5 {
color: #333;
text-align: center;
font-family: "PingFang SC";
font-size: 10px;
font-size: 8px;
font-style: normal;
font-weight: 600;
line-height: 12px;
font-weight: 400;
line-height: 12px; /* 150% */
}
.t51 {
display: flex;
......@@ -239,6 +270,25 @@
}
}
}
.red-btn {
display: flex;
width: 64px;
height: 48px;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 8px;
background: linear-gradient(90deg, #fa643c 0%, #e92927 100%);
font-family: "PingFang SC";
font-size: 10px;
font-style: normal;
font-weight: 600;
line-height: 12px;
color: white;
.meta {
color: var(--W-80, rgba(255, 255, 255, 0.8));
}
}
}
}
}
......@@ -308,4 +358,8 @@
width: 20px;
height: 20px;
}
.size-16 {
width: 16px;
height: 16px;
}
}
......@@ -13,6 +13,19 @@
<image class="tri" src="./tri.png" mode="" />
</view>
<view class="bottom">
<view class="tabs {{!userLocation?'dual':''}}">
<view class="tab" bind:tap="handleNoSort">{{isEn?'Comprehensive':'综合'}}</view>
<view class="tab" wx:if="{{!!userLocation}}" bind:tap="handleDistanceSort">{{isEn?'Distance':'距离'}}
<image wx:if="{{sortBy===sortByStates.distanceDesc}}" class="icon" src="./desc.png" mode="" />
<image wx:elif="{{sortBy===sortByStates.distanceAsc}}" class="icon" src="./asc.png" mode="" />
<image wx:else class="icon" src="./sort.png" mode="" />
</view>
<view class="tab" bind:tap="handlePriceSort">{{isEn?'Price':'价格'}}
<image wx:if="{{sortBy===sortByStates.priceDesc}}" class="icon" src="./desc.png" mode="" />
<image wx:elif="{{sortBy===sortByStates.priceAsc}}" class="icon" src="./asc.png" mode="" />
<image wx:else class="icon" src="./sort.png" mode="" />
</view>
</view>
<view class="title" wx:if="{{isEn}}">
Find similar stores for you
<text class="red">{{voList.length}}</text>
......@@ -44,21 +57,20 @@
</view>
</view>
<view class="right-corner">
<view class="row" catch:tap="handleItinerary" id="{{index}}">
<view class="collect" catch:tap="handleItinerary" id="{{index}}">
<image wx:if="{{itineraryMap[item.shopId]}}" class="size-20" src="./added.png" mode="" />
<image wx:else class="size-20" src="./add.png" mode="" />
<view wx:if="{{itineraryMap[item.shopId]}}" class="t5 red">
{{isEn?'Added itinerary':'已加行程'}}
<view class="t5" wx:if="{{itineraryMap[item.shopId]}}">
{{isEn?'Collected':'已收藏'}}
</view>
<view wx:else class="t5">{{isEn?'Add itinerary':'加入行程'}}</view>
<view class="t5" wx:else>
{{isEn?'Collect':'收藏'}}
</view>
<view class="row" wx:if="{{item.shop&&item.shop.tx}}" id="{{index}}" bind:tap="handleGo">
<image class="size-20" src="./nav.png" mode="" />
<view class="t5" wx:if="{{!item.distance}}">{{isEn?'Go Here':'到这去'}}</view>
<view wx:else class="t51">
<view class="t511">{{item.distance}}m</view>
<view class="t512">{{isEn?'Go Here':'到这去'}}</view>
</view>
<view class="red-btn" wx:if="{{item.shop&&item.shop.tx}}" id="{{index}}" bind:tap="handleGo">
<image class="size-16" src="./wnav.png" mode="" />
<view>{{isEn?'Go Here':'立即导航'}}</view>
<view class="meta" wx:if="{{item.distance}}">{{item.distance}}m</view>
</view>
</view>
</view>
......
import langBehavior from "../../behaviors/langBehavior";
import { getPoiName } from "../../util";
Page({
behaviors: [langBehavior],
/**
* 页面的初始数据
*/
data: {
card: null,
collapsed: true,
isOverflow: false,
pois: [],
scrollTop: 0,
showToast: false,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad({ cardId }) {
this.getCard(cardId);
},
back() {
wx.navigateBack();
},
async getCard(cardId) {
const app = getApp();
try {
const card = await app.cardApi.get(cardId);
if (!card) return wx.navigateBack();
this.setData({ card });
// 1. 自动填充 (默认配置即可匹配 shopType/shopId 字段,且会自动过滤无效项)
const list = await app.poiApi.populate(card.activityShopList || []);
// 2. 格式化并更新视图
this.setData({
pois: list.map((item) => ({
...item,
poiName: getPoiName(item.poi, this.data.isEn),
})),
});
wx.nextTick(() => this.checkTextOverflow());
} catch (error) {
console.error(error);
wx.navigateBack();
}
},
async toPoi({ currentTarget: { id } }) {
const poi = this.data.pois.find((el) => el.shopId === id);
if (poi.checkInStatus === 1) return;
if (this.data.card.isFinish) {
this.setData({ showToast: true });
await new Promise((resolve) => {
setTimeout(() => {
this.setData({ showToast: false });
resolve();
}, 1000);
});
}
if (poi.shopType === 1)
wx.navigateTo({
url: `/pages/poi-map/index?shopId=${poi.shopId}&isCardNav=true`,
});
else {
wx.navigateTo({
url: `/pages/poi-map/index?facilityId=${poi.shopId}&isCardNav=true`,
});
}
},
showDetail() {
wx.previewImage({
urls: [this.data.card?.pointMapImage],
});
},
handleScroll({ detail: { scrollTop } }) {
this.setData({ scrollTop });
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
const menuButtonInfo = wx.getMenuButtonBoundingClientRect();
const windowInfo = wx.getWindowInfo();
const rightPadding = windowInfo.screenWidth - menuButtonInfo.right;
const contentTop = menuButtonInfo.top;
this.setData({
menuButtonInfo,
rightPadding,
contentTop,
});
},
// 添加toggle点击事件
toggleCollapse() {
this.setData({
collapsed: !this.data.collapsed,
});
},
// 添加判断文本是否超过3行的逻辑
checkTextOverflow() {
// 先临时设置为展开状态,获取完整高度
this.setData({ collapsed: false }, () => {
const query = wx.createSelectorQuery();
query
.select(".text")
.boundingClientRect((rect) => {
const lineHeight = 23; // 与样式中定义的line-height一致
const maxLines = 3;
const maxHeight = lineHeight * maxLines;
const isOverflow = rect.height > maxHeight;
// 根据是否溢出设置初始状态
this.setData({
isOverflow,
collapsed: isOverflow, // 如果溢出,默认折叠;否则,默认展开
});
})
.exec();
});
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
getApp().blurPoi();
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {},
});
{
"usingComponents": {},
"navigationStyle": "custom"
}
.card {
position: relative;
width: 100vw;
height: 100vh;
.bg {
position: absolute;
width: 100vw;
height: 100vh;
z-index: 1;
}
.bgTop {
position: absolute;
width: 100vw;
z-index: 2;
}
.header {
position: absolute;
top: 0;
left: 0;
z-index: 5;
display: flex;
width: 100vw;
padding-bottom: 6px;
box-sizing: border-box;
align-items: center;
padding-left: 10px;
.back {
width: 22px;
height: 22px;
}
.placeholder {
width: 22px;
}
.title {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
color: #333;
font-family: "PingFang SC";
font-size: 17px;
font-style: normal;
font-weight: 500;
line-height: normal;
}
}
.toast {
position: absolute;
z-index: 6;
top: 99px;
left: 0;
right: 0;
margin: auto;
width: 312px;
padding: 16px 24px;
display: flex;
flex-direction: column;
gap: 8px;
border-radius: 8px;
background: rgba(0, 0, 0, 0.7);
align-items: center;
.t1 {
color: #fff;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 22px;
}
.t2 {
color: #fff;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
}
}
.scroller {
position: absolute;
box-sizing: border-box;
top: 0;
left: 0;
z-index: 4;
width: 100vw;
height: 100vh;
.scroll-content {
position: relative;
width: 100vw;
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 16px;
padding: 0 12px;
.top {
width: 100%;
height: 216px;
}
.desc {
width: calc(100vw - 24px);
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding: 16px 14px;
border-radius: 16px;
border: 1px solid var(--W-100, #fff);
background: linear-gradient(
180deg,
#fff 0%,
rgba(255, 255, 255, 0.2) 100%
);
backdrop-filter: blur(4px);
.text {
width: 100%;
color: #333;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 23px;
/* 默认展示全部 */
overflow: visible;
text-overflow: unset;
display: block;
}
/* 折叠状态 */
.text:not(.expanded) {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.toggle {
display: flex;
align-items: center;
gap: 4px;
color: #666;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;
.arrow {
width: 14px;
height: 14px;
}
}
}
.pois {
position: relative;
width: calc(100vw - 24px);
border-radius: 16px;
padding: 12px;
overflow: hidden;
display: inline-flex;
flex-direction: column;
gap: 14px;
.title {
position: relative;
z-index: 2;
width: 100%;
color: #fff;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: normal;
vertical-align: baseline;
.meta {
display: inline;
margin-left: 8px;
color: rgba(255, 255, 255, 0.75);
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: normal;
}
}
.poisBg {
position: absolute;
z-index: 1;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
.grid {
width: 100%;
padding: 12px;
background: #ffecec;
border-radius: 16px;
position: relative;
z-index: 2;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px 9px;
.item {
position: relative;
width: calc((100vw - 36px - 9px - 36px) / 2);
display: flex;
flex: 1;
height: 40px;
align-items: center;
justify-content: center;
.item-bg {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1;
width: 100%;
height: 100%;
}
.text {
position: relative;
z-index: 2;
padding: 0 5px;
color: #fff;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ticked {
position: absolute;
z-index: 4;
top: -4px;
right: 0;
width: 56px;
height: 24px;
.img {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.meta {
position: absolute;
z-index: 2;
top: 3px;
left: 12px;
right: 0px;
color: #fff;
font-family: "PingFang SC";
font-size: 10px;
font-style: normal;
font-weight: 400;
line-height: 14px;
text-align: center;
}
}
}
}
}
.poiMap {
padding: 0 12px 12px 12px;
display: flex;
flex-direction: column;
align-items: center;
width: calc(100vw - 24px);
border-radius: 16px;
margin-bottom: 10px;
background: linear-gradient(155deg, #fff 3.79%, #fff6f6 84.49%);
border: 1px solid #fff;
.title {
max-width: calc(100vw - 24px);
margin-top: -1px;
position: relative;
padding: 0 23px;
display: flex;
align-items: center;
justify-content: center;
height: 36px;
gap: 3px;
.titlebg {
position: absolute;
z-index: 1;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
.star {
position: relative;
width: 10px;
height: 10px;
z-index: 2;
flex-shrink: 0;
}
.text {
position: relative;
z-index: 2;
color: #222;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: normal;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.map {
margin-top: 12px;
width: calc(100vw - 48px);
border-radius: 16px;
}
}
}
}
}
<view class="card">
<image wx:if="{{card}}" class="bg" src="{{card.backgroundImage}}" mode="" />
<image wx:if="{{card}}" class="bgTop" src="{{card.topBackgroundImage}}" mode="widthFix" />
<view class="header" style="background: rgba(255,255,255,{{scrollTop>144?1:scrollTop/144}}); padding-top: {{contentTop}}px; height: {{menuButtonInfo.height+contentTop+6}}px; padding-right: {{rightPadding}}px;">
<image class="back" src="./back.png" mode="" bind:tap="back" />
<view class="title">{{isEn?'Check-in Rewards':'活动有奖'}}</view>
<view class="placeholder"></view>
</view>
<view class="toast" wx:if="{{showToast}}">
<view class="t1">{{isEn?'Check-in Complete!':'打卡圆满完成'}}</view>
<view class="t2">{{isEn?'Rewards sent to Coupon Center. View now on homepage.':'活动奖励已发放至您的卡券中心,请至首页查看!'}}</view>
</view>
<scroll-view class="scroller" bindscroll="handleScroll" scroll-y wx:if="{{card}}">
<view class="scroll-content">
<view class="top"></view>
<view class="desc">
<view class="text {{collapsed ? '' : 'expanded'}}">{{isEn?card.introEn:card.intro}}</view>
<view class="toggle" wx:if="{{isOverflow}}" bind:tap="toggleCollapse">
{{isEn?(collapsed?'Read More':'Read Less'):(collapsed?'展开全部':'收起')}}
<image class="arrow" src="./{{collapsed?'arrowDown':'arrowUp'}}.png" mode="" />
</view>
</view>
<view class="pois">
<image class="poisBg" src="https://cdnimg.chinagoods.com/png/2025/12/18/zsk9v9knwhz4cf9wvfz6dfjnv1ju7s4n.png" mode="" />
<view class="title">
{{isEn?card.pointTitleEn:card.pointTitle }}
<view class="meta" wx:if="{{isEn?card.tipEn:card.tip}}">{{isEn?card.tipEn:card.tip}}</view>
</view>
<view class="grid">
<view class="item" wx:for="{{pois}}" wx:key="poiName" id="{{item.shopId}}" bind:tap="toPoi">
<view class="ticked" wx:if="{{item.checkInStatus===1}}">
<image class="img" src="./ticked.png" mode="" />
<view class="meta">{{isEn?'Checked':'已打卡'}}</view>
</view>
<image wx:if="{{item.checkInStatus===0}}" class="item-bg" src="https://cdnimg.chinagoods.com/png/2025/12/18/zlvfpfl0rxrrebfjyvyairvz3poq2dbp.png" mode="" />
<image wx:else src="https://cdnimg.chinagoods.com/png/2025/12/18/tqgtxm4vnpwe1neblbtyg8gob2j4my2q.png" class="item-bg" mode="" />
<view class="text">{{item.poiName}}</view>
</view>
</view>
</view>
<view class="poiMap" wx:if="{{card.pointMapImage}}">
<view class="title" wx:if="{{card.pointExplain}}">
<image class="titlebg" src="./titlebg.png" mode="" />
<image class="star" src="./star.png" mode="" />
<view class="text">{{card.pointExplain}}</view>
<image class="star" src="./star.png" mode="" />
</view>
<image class="map" bind:tap="showDetail" src="{{card.pointMapImage}}" mode="widthFix" />
</view>
</view>
</scroll-view>
</view>
\ No newline at end of file
import { getDistance } from "../../util";
// Constants
const API_URL = "https://apis.map.qq.com/ws/place/v1/search";
const API_PARAMS = "get_rich=0";
const PAGE_SIZE = 10;
const SEARCH_RADIUS = 1000;
/**
* 构建API请求URL
*/
export function buildApiUrl(keyword, pageIndex, currentBuilding, mapKey) {
const params = [
API_PARAMS,
`key=${mapKey}`,
`keyword=${encodeURI(keyword)}`,
`boundary=nearby(${currentBuilding.latlng.lat},${currentBuilding.latlng.lng},${SEARCH_RADIUS})`,
`page_size=${PAGE_SIZE}`,
`page_index=${pageIndex}`,
].join("&");
return `${API_URL}?${params}`;
}
/**
* 处理店铺数据,计算距离和分类
*/
export function processShopData(shops, currentBuilding) {
return shops.map((shop) => {
const result = { ...shop };
try {
result.distance = Math.ceil(
getDistance(
currentBuilding.latlng.lat,
currentBuilding.latlng.lng,
shop.location.lat,
shop.location.lng
)
);
result.minite = Math.ceil(result.distance / 1.4 / 60);
} catch (error) {
console.warn("Failed to calculate distance:", error);
result.distance = null;
result.minite = null;
}
try {
result.category = result.category?.split(":").pop() || "";
} catch (error) {
console.warn("Failed to process category:", error);
result.category = "";
}
return result;
});
}
/**
* 获取店铺列表数据
*/
export async function getShopList(
keyword,
pageIndex,
currentBuilding,
mapKey,
appInstance
) {
const apiUrl = buildApiUrl(keyword, pageIndex, currentBuilding, mapKey);
const { data } = await appInstance.get(apiUrl);
const rawData = data.data || [];
const totalCount = data.count || 0;
const processedData = processShopData(rawData, currentBuilding);
return {
rawData,
totalCount,
processedData,
};
}
{
"disableScroll": true,
"usingComponents": {
"custom-tab-bar": "../../components/custom-tab-bar/index"
}
}
/* components/explore/index.wxss */
.explore {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
.map {
width: 100vw;
height: calc(100vh - 140px);
}
.bottom-bg {
position: absolute;
bottom: 0;
z-index: 200;
display: flex;
flex-direction: column;
height: 414px;
width: 100vw;
border-radius: 8px;
border: 1px solid #fff;
background: linear-gradient(180deg, #fbfbfb 0%, #f4f4f4 41.8%);
}
.bottom-hud {
position: absolute;
bottom: 0;
z-index: 200;
height: 420px;
width: 100vw;
.handle {
position: absolute;
top: -4px;
left: 0;
right: 0;
margin: auto;
width: 40px;
height: 4px;
border-radius: 27px;
background: rgba(0, 0, 0, 0.2);
&::before {
content: "";
display: block;
position: absolute;
left: -5px;
right: -5px;
top: -10px;
bottom: -10px;
}
}
.title {
padding-top: 16px;
padding-left: 22px;
display: flex;
gap: 24px;
align-items: center;
.item {
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 2px;
.txt {
color: rgba(0, 0, 0, 0.7);
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 22px;
}
.mark {
width: 16px;
height: 4px;
border-radius: 17px;
}
&.active {
.txt {
color: rgba(0, 0, 0, 0.9);
font-weight: 600;
}
.mark {
background: #e92927;
}
}
}
}
.collapsed {
display: flex;
width: 100vw;
height: 62px;
align-items: center;
justify-content: center;
padding-top: 6px;
color: #333;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 18px;
}
.scroll-view {
position: absolute;
z-index: 1;
left: 10px;
right: 10px;
top: 58px;
height: calc(100vh - 158px);
width: calc(100vw - 20px);
.list {
display: inline-flex;
flex-direction: column;
width: calc(100vw - 20px);
gap: 8px;
.item {
position: relative;
width: calc(100vw - 20px);
border-radius: 8px;
background: #fff;
padding: 12px 16px;
.content {
display: inline-flex;
flex-direction: column;
flex: 1;
overflow: hidden;
.t1 {
color: #333;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 22px; /* 137.5% */
}
.t2 {
margin-top: 4px;
color: rgba(0, 0, 0, 0.4);
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
}
.t3 {
display: flex;
width: calc(100vw - 52px);
align-items: center;
gap: 4px;
margin-top: 8px;
color: #666;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
.loc {
width: 16px;
height: 16px;
}
.right {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.tel {
position: absolute;
top: 12px;
right: 16px;
display: flex;
flex-direction: column;
align-items: center;
color: #666;
font-family: "PingFang SC";
font-size: 11px;
font-style: normal;
font-weight: 400;
line-height: normal;
.phone {
width: 24px;
height: 24px;
}
}
}
.loading,
.no-more {
text-align: center;
padding: 10px;
color: #666;
font-size: 14px;
}
}
}
}
.detail {
position: absolute;
bottom: 0;
left: 0;
right: 0;
width: 100vw;
z-index: 2000;
.detail-bg {
position: absolute;
top: 0;
left: 0;
width: 100vw;
bottom: 0;
right: 0;
z-index: 1;
background: #fff;
}
.content {
position: relative;
z-index: 2;
background: #fff;
.close {
position: absolute;
top: 10px;
right: 8px;
width: 32px;
height: 32px;
z-index: 10;
}
.top {
position: relative;
display: flex;
flex-direction: column;
gap: 4px;
padding: 16px;
.t1 {
color: #333;
font-feature-settings: "case" on;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 22px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 24px;
}
.t2 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: rgba(0, 0, 0, 0.4);
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
padding-right: 24px;
}
.t3 {
display: flex;
width: calc(100vw - 52px);
align-items: center;
gap: 4px;
margin-top: 24px;
color: #666;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
.loc {
width: 16px;
height: 16px;
}
.right {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.tel {
position: absolute;
bottom: 16px;
right: 16px;
display: flex;
flex-direction: column;
align-items: center;
color: #666;
font-family: "PingFang SC";
font-size: 11px;
font-style: normal;
font-weight: 400;
line-height: normal;
.phone {
width: 24px;
height: 24px;
}
}
}
.bottom {
height: 98px;
border-top: 1px solid rgba(0, 0, 0, 0.06);
padding-top: 12px;
padding-left: 16px;
padding-right: 16px;
.btn {
border-radius: 99px;
background: linear-gradient(90deg, #fa643c 0%, #e92927 100%);
height: 40px;
display: flex;
gap: 8px;
align-items: center;
justify-content: center;
color: #fff;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 18px;
.img {
width: 24px;
height: 24px;
}
}
}
}
}
}
<view class="explore">
<map wx:if="{{latitude&&longitude}}" id="explore-map" class="map" show-compass latitude="{{latitude}}" longitude="{{longitude}}" max-scale="22" bind:markertap="handleMarkerTap"></map>
<textarea wx:if="{{!detail}}" disabled class="bottom-bg" style="z-index: 100;height: {{height - 6}}px;transition: {{!doTransition ? 'none' : 'height 0.5s ease'}}"></textarea>
<view class="bottom-hud" hidden="{{detail}}" style="height: {{height}}px;transition: {{!doTransition ? 'none' : 'height 0.5s ease'}}" bind:touchstart="handleTouchStart" bind:touchmove="handleTouchMove" bind:touchend="handleTouchEnd" bind:touchcancel="handleTouchEnd">
<view class="handle"></view>
<view class="title" wx:if="{{viewState!=='collapsed'}}">
<view class="item {{currentIndex===index?'active':''}}" wx:for="{{categories}}" wx:key="name" id="{{index}}" bind:tap="switchCat">
<view class="txt">{{isEn?item.nameEn:item.name}}</view>
<view class="mark"></view>
</view>
</view>
<view wx:if="{{viewState==='collapsed'}}" class="collapsed">{{isEn?'Show more':'上滑查看全部结果'}}</view>
<scroll-view hidden="{{viewState==='collapsed'}}" id="scroller" enhanced bounces="{{false}}" scroll-y="{{viewState==='fullscreen'&&!snapped}}" class="scroll-view" scroll-top="{{ nextTop }}" bindscrolltolower="onScrollToLower">
<view class="list">
<view class="item" wx:for="{{list}}" wx:for-item="shop" wx:key="id" id="{{shop.id}}" bind:tap="toDetail">
<view class="content">
<view class="t1">{{shop.title}}</view>
<view class="t2">{{isEn?'Distance':'距此'}}{{shop.distance}}m</view>
<view class="t3">
<image src="./loc.png" class="loc" mode="" />
<view class="right">{{shop.address}}</view>
</view>
</view>
<view wx:if="{{shop.tel}}" id="{{shop.tel}}" class="tel" catch:tap="makePhoneCall">
<image class="phone" src="./tel.png" mode="" />
{{isEn?'Tel':'电话'}}
</view>
</view>
<view wx:if="{{loading}}" class="loading">{{isEn?'Loading...':'加载中...'}}</view>
<view wx:elif="{{!hasMore}}" class="no-more">{{isEn?'No more data':'没有更多数据了'}}</view>
</view>
</scroll-view>
</view>
<view class="detail" wx:if="{{detail}}">
<textarea disabled class="detail-bg"></textarea>
<view class="content">
<image class="close" src="./close.png" mode="" bind:tap="back" />
<view class="top">
<view class="t1">{{detail.title}}</view>
<view class="t2">{{isEn?'Distance':'距此'}}{{detail.distance}}m</view>
<view class="t3">
<image src="./loc.png" class="loc" mode="" />
<view class="right">{{detail.address}}</view>
</view>
<view wx:if="{{detail.tel}}" id="{{detail.tel}}" class="tel" bind:tap="makePhoneCall">
<image class="phone" src="./tel.png" mode="" />
{{isEn?'Tel':'电话'}}
</view>
</view>
<view class="bottom">
<view class="btn" bind:tap="toApp">
<image class="img" src="./dir.png" mode="" />
<view>{{isEn?'Go here':'到这去'}}</view>
</view>
</view>
</view>
</view>
<custom-tab-bar current-index="{{2}}" bind:tab="handleTab"></custom-tab-bar>
</view>
\ No newline at end of file
// pages/feedback/index.js
Page({
/**
* 页面的初始数据
*/
data: { src: "" },
/**
* 生命周期函数--监听页面加载
*/
onLoad() {
const token = getApp().globalData.user.access_token;
this.setData({
src: `https://h5.chinagoods.com/aigc/feedback-list?token=${token}`,
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {},
});
{
"usingComponents": {},
"navigationBarTitleText": "贡献反馈"
}
/* pages/feedback/index.wxss */
\ No newline at end of file
<web-view src="{{src}}" />
\ No newline at end of file
......@@ -29,7 +29,7 @@ Component({
moveTouches(touches) {
if (!this.data.touchStart) return;
let touch = Array.from(touches).find(
({ identifier }) => identifier === this.data.touchStart.identifier
({ identifier }) => identifier === this.data.touchStart.identifier,
);
if (!touch) {
if (touches.length > 0) {
......@@ -50,14 +50,14 @@ Component({
this.setData({
height: Math.max(
Math.min(this.baseHeight() - delta, this.data.windowHeight - 24),
146
146,
),
});
},
endTouches(touches) {
if (!this.data.touchStart) return;
let touch = Array.from(touches).find(
({ identifier }) => identifier === this.data.touchStart.identifier
({ identifier }) => identifier === this.data.touchStart.identifier,
);
if (!touch) {
......@@ -188,31 +188,38 @@ Component({
console.log(error);
}
},
handlePoi({ detail: poi }) {
this.triggerEvent("poi", poi);
},
async getNavHistory() {
const { post, qmurl, shopIdMap, facilityIdMap, globalData } = getApp();
if (!globalData.user) return;
if (!shopIdMap) return;
const app = getApp();
const userId = app.globalData.user?.user?.userId;
if (!userId) return;
try {
const {
data: { data },
} = await post(
`${qmurl}/api/v1/applet/getUserFootPrintList?userId=${globalData.user.user.userId}`,
{
userId: globalData.user.user.userId,
}
} = await app.post(
`${app.qmurl}/api/v1/applet/getUserFootPrintList?userId=${userId}`,
{ userId },
);
if (data && data.length !== undefined) {
if (!Array.isArray(data)) return;
// 1. 性能优化:先过滤并截取前 10 条 (避免填充无需显示的后续数据)
const rawList = data.filter((item) => item.shopType === 1).slice(0, 10);
// 2. 自动填充 (利用 populate 默认读取 shopType/shopId 的特性,无需配置参数)
const populatedList = await app.poiApi.populate(rawList, {
targetField: "detail",
});
// 3. 提取结果并更新
this.setData({
navHistory: data
.map(({ shopType, shopId }) =>
shopType === 1 ? shopIdMap[shopId] : null
)
.filter((el) => el)
.slice(0, 10),
navHistory: populatedList.map((item) => item.detail).filter(Boolean),
});
}
} catch (error) {
console.log(error);
console.error(error);
}
},
},
......@@ -222,14 +229,7 @@ Component({
.select("#scroller")
.scrollOffset();
this.getPrimeSpots();
const app = getApp();
if (!app.shopIdMap) {
app.events.once("globalData", () => {
this.getNavHistory();
});
} else {
this.getNavHistory();
}
},
},
});
......@@ -8,7 +8,7 @@
<scroll-view id="scroller" enhanced bounces="{{false}}" scroll-y="{{viewState==='fullscreen'}}" class="scroll-view" scroll-top="{{ nextTop }}" bindscrolltolower="onScrollToLower" lower-threshold="251">
<view style="width: 100%; height: 46px;"></view>
<prime-spot wx:if="{{primeSpots.length>0&&!isEn}}" list="{{primeSpots}}"></prime-spot>
<nav-history wx:if="{{navHistory.length>0}}" list="{{navHistory}}" bind:navhistorycleared="getNavHistory"></nav-history>
<nav-history wx:if="{{navHistory.length>0}}" list="{{navHistory}}" bind:navhistorycleared="getNavHistory" bind:poi="handlePoi"></nav-history>
<shops scroll-end-count="{{scrollEndCount}}"></shops>
</scroll-view>
</view>
......
......@@ -40,7 +40,7 @@ Component({
},
handleShop({ currentTarget: { id: index } }) {
const poi = this.data.list[index];
getApp().focusPoi(poi);
this.triggerEvent("poi", poi);
},
async clearNavHistory() {
const { isEn } = this.data;
......
import langBehavior from "../../../../behaviors/langBehavior";
import buildingBehavior from "../../../../behaviors/buildingBehavior";
Component({
behaviors: [langBehavior],
behaviors: [langBehavior, buildingBehavior],
properties: {},
/**
......@@ -8,22 +9,13 @@ Component({
*/
data: {
placeholderIndex: 0,
placeholders: [
{
en: "District 2-East New Energy Product Market Welcome!",
cn: "欢迎光临二区东新能源产品市场",
placeholders: [],
},
{
en: "Search store number/facilities/block/exit number",
cn: "搜铺号/公共设施/街区号/出入口号",
observers: {
currentBuilding() {
this.setPlaceholder();
},
{
en: "Click or search shoplD for click navigation",
cn: "点击或搜索任意商铺可一键导航前往",
},
],
},
/**
* 组件的方法列表
*/
......@@ -34,6 +26,25 @@ Component({
aiTap() {
this.triggerEvent("ai");
},
setPlaceholder() {
const building = this.data.currentBuilding;
this.setData({
placeholders: [
{
en: `${building.displayNameEn} Welcome!`,
cn: `欢迎光临${building.displayName}`,
},
{
en: "Search store number/facilities/block/exit number",
cn: "搜铺号/公共设施/街区号/出入口号",
},
{
en: "Click or search shoplD for click navigation",
cn: "点击或搜索任意商铺可一键导航前往",
},
],
});
},
},
lifetimes: {
attached() {
......@@ -42,6 +53,7 @@ Component({
placeholderIndex: (this.data.placeholderIndex + 1) % 3,
});
}, 3000);
this.setPlaceholder();
},
detached() {
if (this.interval) {
......
......@@ -51,7 +51,7 @@
color: #000;
border-radius: 99px;
border: 0.2px solid var(--W-100, #fff);
background: rgba(255, 255, 255, 0.08);
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(33.05883026123047px);
}
}
......
......@@ -2,7 +2,7 @@
<image src="./search.png" class="search" mode="" />
<view class="text">{{placeholders[placeholderIndex][isEn?'en':'cn']}}</view>
<view class="ai" catch:tap="aiTap">
<image src="./ai.png" class="icon" mode="" />
<image src="https://cdnimg.chinagoods.com/png/2025/10/10/tabzvwxow9xlggugfr0e0oe3s5pahny2.png" class="icon" mode="" />
<view class="text" style="{{'width: '+(isEn?50:35)+'px'}}">{{isEn?"AI Search":"AI识物"}}</view>
</view>
</view>
\ No newline at end of file
import langBehavior from "../../../../behaviors/langBehavior";
import buildingBehavior from "../../../../behaviors/buildingBehavior";
Component({
behaviors: [langBehavior],
behaviors: [langBehavior, buildingBehavior],
/**
* 组件的属性列表
*/
......@@ -12,7 +13,10 @@ Component({
* 组件的初始数据
*/
data: {
formats: [{ key: "all", name: "全部", nameEn: "All" }, ...getApp().formats],
formats: [
{ key: "all", name: "全部", nameEn: "All" },
...getApp().currentBuilding.formats,
],
key: "all",
page: 1,
page_size: 10,
......@@ -20,6 +24,15 @@ Component({
isLoading: false,
},
observers: {
currentBuilding() {
this.setData({
formats: [
{ key: "all", name: "全部", nameEn: "All" },
...getApp().currentBuilding.formats,
],
key: "all",
});
},
key() {
this.setData({
page: 1,
......@@ -45,61 +58,68 @@ Component({
*/
methods: {
async getList(nxtPage = 1) {
const { post, marketurl, formats, md5, salt, shopIdMap } = getApp();
const { key, isEn, page_size } = this.data;
if (this.data.isLoading) return;
if (!shopIdMap) return;
try {
this.setData({
isLoading: true,
});
const app = getApp();
const { key, isEn, page_size, currentBuilding, list, isLoading } =
this.data;
if (isLoading) return;
this.setData({ isLoading: true });
try {
const {
data: {
data: { total_page, page, first_result, last_result, data },
},
} = await post(`${marketurl}/osc/v1/shops/open/toBaiDu/search`, {
data: { data: res },
} = await app.post(
`${app.marketurl}/osc/v1/shops/open/toBaiDu/search`,
{
page: nxtPage,
page_size,
industryKeyList:
key === "all" ? formats.map((format) => format.key) : [key],
key === "all" ? currentBuilding.formats.map((f) => f.key) : [key],
lang: isEn ? "en" : "zh",
keySecret: md5(md5(salt + nxtPage)),
keySecret: app.md5(app.md5(app.salt + nxtPage)),
zone: currentBuilding.zone,
},
);
// 1. 自动填充
const filledItems = await app.poiApi.populate(res.data, {
getType: () => "1",
getId: (i) => i.shopId,
getBooth: (i) => i.boothNo,
targetField: "detail",
});
const nxtList = data
.map((shop) => {
if (!shopIdMap[shop.shopId])
console.warn("列表接口里有,但是全量没有的店铺", shop);
return shopIdMap[shop.shopId];
})
.filter((el) => el);
// 2. 提取详情
const nxtList = filledItems.map((i) => i.detail).filter(Boolean);
// 3. 批量埋点
nxtList.forEach((poi) => {
const yw = poi.ywZh || {};
try {
getApp().sensors?.track("ExposureBoothActivity", {
app.sensors?.track("ExposureBoothActivity", {
shop_id: poi.shopId,
shop_name: poi.ywZh.name,
booth_no: poi.ywZh.boothNo,
store_name: poi.ywZh.name,
short_market_name: "二区东",
booth_addr_street: poi.ywZh.boothAddrStreet,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
shop_name: yw.name,
booth_no: yw.boothNo,
store_name: yw.name,
short_market_name: yw.marketNameDtl,
booth_addr_street: yw.boothAddrStreet,
industry: yw.frontIndustryCategory,
booth_floor: yw.addrFloor,
});
} catch (error) {
console.error("埋点失败", error);
} catch (e) {
console.error(e);
}
});
this.setData({
list: [...this.data.list, ...nxtList],
total_page,
page,
list: [...list, ...nxtList],
total_page: res.total_page,
page: res.page,
});
} catch (error) {
console.error(error);
} finally {
this.setData({
isLoading: false,
});
this.setData({ isLoading: false });
}
},
handleFormat({ currentTarget: { id: key } }) {
......@@ -110,36 +130,34 @@ Component({
}
},
handleShop({ currentTarget: { id: shopId } }) {
try {
const poi = getApp().shopIdMap[shopId];
getApp().sensors?.track("BoothActivityClick", {
// 1. 立即跳转 (UI 响应优先,不阻塞)
wx.navigateTo({ url: `/pages/shop/index?shopId=${shopId}` });
// 2. 异步埋点 (Fire-and-forget)
const app = getApp();
app.poiApi
.getOne({ shopType: "1", shopId })
.then((poi) => {
if (!poi) return;
const yw = poi.ywZh || {}; // 缓存对象,简化下方取值
app.sensors?.track("BoothActivityClick", {
shop_id: poi.shopId,
shop_name: poi.ywZh.name,
booth_no: poi.ywZh.boothNo,
store_name: poi.ywZh.name,
short_market_name: "二区东",
booth_addr_street: poi.ywZh.boothAddrStreet,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
});
} catch (error) {
console.error("埋点失败", error);
}
wx.navigateTo({
url: `/pages/shop/index?shopId=${shopId}`,
shop_name: yw.name,
booth_no: yw.boothNo,
store_name: yw.name,
short_market_name: yw.marketNameDtl,
booth_addr_street: yw.boothAddrStreet,
industry: yw.frontIndustryCategory,
booth_floor: yw.addrFloor,
});
})
.catch((e) => console.error("埋点失败", e));
},
},
lifetimes: {
attached() {
const app = getApp();
if (app.shopIdMap) {
this.getList();
} else {
app.events.once("globalData", () => {
this.getList();
});
}
},
},
});
......@@ -213,4 +213,12 @@
width: 16px;
height: 16px;
}
.card {
position: absolute;
top: 168px;
right: 2px;
width: 56px;
height: 56px;
z-index: 2;
}
}
<view class="index">
<map-wrapper type="{{isIndex?'index':'surroundings'}}" viewstate="{{viewstate}}" user-location="{{userLocation}}" acts="{{acts}}" reset-count="{{resetCount}}" building-id="{{buildingId}}" floor-name="{{floorName}}" facilities="{{currentFloorFacilities}}" bind:poi="handlePoi" bind:act="handleAct"></map-wrapper>
<lang-btn wx:if="{{!(isIndex&&viewstate==='fullscreen')}}"></lang-btn>
<bottom-hud-index wx:if="{{isIndex}}" bind:viewstate="handleBottomHudViewstate" bind:search="handleSearch" bind:ai="handleAi">
<floors never-authed="{{neverAuthed}}" show-success="{{getLocationSuccess}}" refreshing="{{gettingLocation}}" wx:if="{{viewstate!=='fullscreen'&&!focusedPoi}}" floors="{{floors}}" floor-name="{{floorName}}" bind:floorname="handleFloor" bind:resetmap="handleReset"></floors>
<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>
<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>
<bottom-hud-surroundings wx:else badge-num="{{currentFloorFacilities.length}}" active-id="{{activeId}}" fac-types="{{facTypes}}" bind:factypetap="handleFacTypeTap">
<floors never-authed="{{neverAuthed}}" show-success="{{getLocationSuccess}}" refreshing="{{gettingLocation}}" wx:if="{{!focusedPoi}}" floors="{{floors}}" floor-name="{{floorName}}" bind:floorname="handleFloor" bind:resetmap="handleReset"></floors>
<floors never-authed="{{neverAuthed}}" show-success="{{getLocationSuccess}}" refreshing="{{gettingLocation}}" wx:if="{{!focusedPoi}}" floors="{{currentBuilding.floors}}" floor-name="{{floorName}}" bind:floorname="handleFloor" bind:resetmap="handleReset"></floors>
</bottom-hud-surroundings>
<popup wx:if="{{focusedPoi}}" is-index="{{true}}" bind:showbluetoothmodal="openBluetoothModal" bind:showlocationmodal="openLocationModal" bind:showauthmodal="openAuthModal">
<floors never-authed="{{neverAuthed}}" show-success="{{getLocationSuccess}}" refreshing="{{gettingLocation}}" floors="{{floors}}" floor-name="{{floorName}}" bind:floorname="handleFloor" bind:resetmap="handleReset"></floors>
<floors never-authed="{{neverAuthed}}" show-success="{{getLocationSuccess}}" refreshing="{{gettingLocation}}" floors="{{currentBuilding.floors}}" floor-name="{{floorName}}" bind:floorname="handleFloor" bind:resetmap="handleReset"></floors>
</popup>
<custom-tab-bar current-index="{{isIndex?0:1}}" bind:tab="handleTab"></custom-tab-bar>
<view class="banner" wx:if="{{isIndex&&showBanner}}" bind:tap="closeBanner">
......@@ -46,4 +46,8 @@
</view>
<image src="./close.png" class="close" catch:tap="closeAct" mode="" />
</view>
<block wx:if="{{cardId}}">
<textarea class="card" disabled style="z-index: 1"></textarea>
<image class="card" src="./card.png" mode="" bind:tap="toCard" />
</block>
</view>
\ No newline at end of file
......@@ -20,10 +20,13 @@ Component({
touchStartY: 0,
},
observers: {
itineraryList(list) {
async itineraryList(list) {
this.setData({
notVisitedCount: list.filter(({ status }) => status !== 1).length,
listGroupByYmd: this.groupByCreateTime(list),
});
const listGroupByYmd = await this.groupByCreateTime(list);
this.setData({
listGroupByYmd,
});
},
bulkDeleting() {
......@@ -35,30 +38,28 @@ Component({
async handleGo({ currentTarget: { id } }) {
const { isEn, itineraryList } = this.data;
const iti = itineraryList.find((iti) => Number(id) === iti.id);
const poi = getApp().shopIdMap[iti.shopId];
const app = getApp();
const poi = await app.poiApi.getOne({
shopType: "1",
shopId: iti.shopId,
});
if (!poi) return;
try {
getApp().sensors?.track("NavEntryBtnClick", {
app.sensors?.track("NavEntryBtnClick", {
page_name: "我的行程",
short_market_name: "二区东",
...(poi.tx
? {
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
}
: {}),
...(poi.facilityId
? {
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,
}),
short_market_name: poi.ywZh?.marketNameDtl,
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);
......@@ -113,7 +114,7 @@ Component({
this.setData({
deleteIdMap: this.data.itineraryList.reduce(
(acc, nxt) => ({ ...acc, [nxt.id]: true }),
{}
{},
),
allSelected: true,
});
......@@ -163,44 +164,45 @@ Component({
wx.hideLoading();
}
},
groupByCreateTime(dataList) {
const { shopIdMap } = getApp();
if (!shopIdMap) return [];
if (!dataList || !Array.isArray(dataList)) return [];
dataList = dataList.filter(({ shopId }) => shopIdMap[shopId]);
if (dataList.length === 0) {
return [];
}
const today = new Date();
const todayStr = `${today.getFullYear()}-${(today.getMonth() + 1)
.toString()
.padStart(2, "0")}-${today.getDate().toString().padStart(2, "0")}`;
async groupByCreateTime(dataList) {
if (!Array.isArray(dataList) || dataList.length === 0) return [];
// 1. 自动填充店铺数据
const populatedList = await getApp().poiApi.populate(dataList, {
getType: () => "1",
getId: (item) => item.shopId,
targetField: "shop",
});
// 2. 获取今天的日期字符串 (YYYY-MM-DD)
const now = new Date();
const todayStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
const result = [];
let currentGroup = null;
dataList.forEach((item) => {
const datePart = item.createTime.split(" ")[0];
// 3. 遍历、过滤、格式化、分组 (一次循环完成)
populatedList.forEach((item) => {
// 过滤无效数据
if (!item?.shop) return;
// --- 价格格式化 (无需 try-catch) ---
// Number() 失败会返回 NaN,逻辑依然安全
const price = Number(item.goodsPrice) || 0;
item.yuan = Math.floor(price);
item.fen = `.${String(Math.round(price * 100) % 100).padStart(2, "0")}`;
// --- 分组逻辑 ---
const datePart = (item.createTime || "").split(" ")[0];
const dateKey = datePart === todayStr ? "今天" : datePart;
// 如果是新的一天,创建新组
if (!currentGroup || currentGroup.date !== dateKey) {
currentGroup = {
date: dateKey,
list: [],
};
currentGroup = { date: dateKey, list: [] };
result.push(currentGroup);
}
try {
item.goodsPrice = Number(item.goodsPrice);
item.yuan = Math.floor(item.goodsPrice);
item.fen =
"." +
String(Math.round(item.goodsPrice * 100) % 100).padStart(2, "0");
} catch (error) {
item.yuan = item.goodsPrice;
console.error(error);
}
currentGroup.list.push({ ...item, shop: shopIdMap[item.shopId] });
currentGroup.list.push(item);
});
return result;
......
<view class="itinerary">
<scroll-view class="scroller {{bulkDeleting?'bulk':''}}" scroll-y>
<view class="title">
<view class="left">{{isEn?'My Itinerary':'我的行程'}}
<view class="left">{{isEn?'Saved Items':'商品收藏'}}
<text class="nums"><text class="red">{{notVisitedCount}}</text>/{{itineraryList.length}}</text>
</view>
<view class="btns">
......
......@@ -5,6 +5,7 @@ Page({
checked: false,
phoneLock: false,
showModal: false,
bindingModalData: null,
},
/**
......@@ -29,6 +30,57 @@ Page({
});
}
},
async checkRedPocketOpenid() {
try {
const { marketurl, post, globalData } = getApp();
const {
data: { code, data, message },
} = await post(
`${marketurl}/rpt/user/openId/query`,
{},
{
Authorization: `Bearer ${globalData.user.access_token}`,
}
);
if (code === 20000) {
console.log("检查红包openid", data.hasOpen);
return data.hasOpen;
} else {
console.log("检查红包openid报错", message);
return true;
}
} catch (error) {
console.log("检查红包openid报错", error);
return true;
}
},
async getRedPocketOpenid() {
try {
const { marketurl, post, globalData } = getApp();
const {
data: { code, message },
} = await post(
`${marketurl}/rpt/user/openId`,
{
returnUrl: `https://h5.chinagoods.com/verify-openid/?targetPath=${encodeURIComponent(
"/pages/verify-openId/index"
)}`,
},
{
Authorization: `Bearer ${globalData.user.access_token}`,
}
);
if (code === 20000) {
wx.redirectTo({
url: `/pages/wap/index?url=${encodeURIComponent(message)}`,
});
return false;
} else return true;
} catch (error) {
console.log(error);
}
},
handleUnchecked() {
this.setData({ showModal: true });
},
......@@ -39,8 +91,26 @@ Page({
this.setData({ phoneLock: true });
try {
if (code) {
const success = await getApp().login(code);
if (success) this.back();
const response = await getApp().login(code);
if (!response)
return wx.showToast({
title: "登录失败",
icon: "none",
});
if (response.code === 20000) {
const hasOpenid = await this.checkRedPocketOpenid();
if (hasOpenid) this.back();
else {
await this.getRedPocketOpenid();
}
} else if (response.code === 88051) {
return this.setData({ bindingModalData: response.data });
} else {
return wx.showToast({
title: response.message,
icon: "none",
});
}
}
} catch (error) {
console.log("error", error);
......@@ -48,6 +118,9 @@ Page({
this.setData({ phoneLock: false });
}
},
closeBindingModal() {
this.setData({ bindingModalData: null });
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
......
......@@ -175,4 +175,84 @@
}
}
}
.binding-modal {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
gap: 40px;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 3;
background: rgba(0, 0, 0, 0.6);
.modal-content {
width: 304px;
padding: 32px 36px;
border-radius: 8px;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
.r1 {
color: #333;
text-align: center;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 18px;
}
.r2 {
color: #333;
text-align: center;
font-family: "PingFang SC";
font-size: 24px;
font-style: normal;
font-weight: 600;
line-height: normal;
}
.r3 {
display: flex;
width: 100%;
gap: 4px;
color: #666;
text-align: center;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: normal;
.icon {
width: 12px;
height: 12px;
margin-top: 1px;
flex-shrink: 0;
}
}
.r4 {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 40px;
border-radius: 99px;
border: 1px solid #e92927;
color: #e92927;
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 22px;
margin-top: 16px;
}
}
.close {
width: 32px;
height: 32px;
}
}
}
......@@ -25,7 +25,7 @@
</view>
</view>
<lang-btn type="black"></lang-btn>
<view class="modal" wx:if="{{showModal}}" bind:tap="closeModal">
<view class="modal" wx:if="{{showModal&&!bindingModalData}}" bind:tap="closeModal">
<view class="modal-content" catch:tap>
<view class="r1" wx:if="{{isEn}}">
Please read carefully and fully understand the relevant terms, click agree means that you have
......@@ -41,5 +41,21 @@
</view>
</view>
</view>
<view class="binding-modal" wx:if="{{bindingModalData}}" bind:tap="closeBindingModal">
<view class="modal-content" catch:tap>
<view class="r1">
当前微信注册的Chinagoods账号
已绑定其他手机号,占用绑定手机号为
</view>
<view class="r2">
{{bindingModalData}}
</view>
<view class="r3">
<image class="icon" src="./icon.png" mode="" />
<text style="text-align: left;">使用已绑定过微信账号的手机号进行登录,启用导航一键到店</text>
</view>
<view class="r4" catch:tap="closeBindingModal">切换账号登录</view>
</view>
<image src="./close.png" class="close" bind:tap="closeBindingModal" mode="" />
</view>
</view>
\ No newline at end of file
......@@ -34,7 +34,10 @@ Component({
this.setData({
formats: [
{ key: "all", name: "全部收藏", nameEn: "All" },
...getApp().formats.filter(({ key }) => formatKeyMap[key]),
...getApp()
.buildings.map(({ formats }) => formats)
.reduce((acc, nxt) => acc.concat(nxt), [])
.filter(({ key }) => formatKeyMap[key]),
],
});
this.setDisplayList();
......@@ -77,7 +80,7 @@ Component({
this.setData({
deleteIdMap: this.data.displayList.reduce(
(acc, nxt) => ({ ...acc, [nxt.id]: true }),
{}
{},
),
allSelected: true,
});
......@@ -121,16 +124,24 @@ Component({
toggleBulkDeleting() {
this.setData({ bulkDeleting: !this.data.bulkDeleting });
},
setPoiList() {
const { shopIdMap, facilityIdMap } = getApp();
if (!shopIdMap) return this.setData({ poiList: [] });
const poiList = this.data.collectList
.map(({ id, shopId, shopType }) => ({
id,
poi: shopType === 1 ? shopIdMap[shopId] : facilityIdMap[shopId],
}))
.filter(({ poi }) => poi);
this.setData({ poiList });
async setPoiList() {
const { collectList } = this.data;
// 1. 快速判空
if (!collectList?.length) return this.setData({ poiList: [] });
// 2. 自动填充 (省略默认配置,populate 默认读取 item.shopType 和 item.shopId)
const list = await getApp().poiApi.populate(collectList, {
targetField: "poi",
});
// 3. 过滤并重组 (最小化 setData 传输的数据量)
this.setData({
poiList: list
.filter((item) => item.poi)
.map(({ id, poi }) => ({ id, poi })),
});
this.setDisplayList();
},
cleanSwipeDeleteId() {
this.setData({ swipeDeleteId: null });
......@@ -151,14 +162,16 @@ Component({
const { isEn, displayList } = this.data;
const { poi } = displayList[index];
try {
const { buildingIdNameMap } = getApp();
getApp().sensors?.track("NavEntryBtnClick", {
page_name: "我的收藏列表",
short_market_name: "二区东",
rank: Number(index) + 1,
label_name: this.data.formats.find(({ key }) => this.data.key === key)
.name,
...(poi.tx
? {
short_market_name: buildingIdNameMap[poi.tx.bld_id],
x: Number(poi.tx.poi_location.longitude),
y: Number(poi.tx.poi_location.latitude),
}
......@@ -241,7 +254,7 @@ Component({
},
handleShopTap({ currentTarget: { id } }) {
const collect = this.data.displayList.find(
(collect) => Number(id) === collect.id
(collect) => Number(id) === collect.id,
);
if (!collect) return;
if (!this.data.bulkDeleting) {
......
<view class="collection">
<view class="title">
<view class="left">
{{isEn?'My Collection':'我收藏的地点'}}
<view>{{poiList.length}}</view>
{{isEn?'Saved Stores':'店铺收藏'}}
</view>
<block wx:if="{{poiList.length}}">
<view wx:if="{{bulkDeleting}}" class="edit red" bind:tap="toggleBulkDeleting">{{isEn?'Finish':'完成'}}</view>
......

2.9 KB | W: | H:

2.9 KB | W: | H:

pages/mine/history.png
pages/mine/history.png
pages/mine/history.png
pages/mine/history.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -30,7 +30,9 @@ Page({
getApp().login();
},
toggleBulkDeleting({ detail: bulkDeleting }) {
this.setData({ bulkDeleting });
this.setData({
bulkDeleting,
});
},
toCouponCenter() {
getApp().sensors?.track("MyCouponClick", {
......@@ -49,7 +51,11 @@ Page({
url: "/pages/itinerary/index",
});
},
onLoad(options) {
onLoad(params) {
console.log(params);
const { utm_campaign, utm_term } = params;
if (utm_campaign) getApp().utm_campaign = utm_campaign;
if (utm_term) getApp().utm_term = utm_term;
this.setItineraryCount = () =>
this.setData({
itineraryCount: getApp().itineraryList.filter(
......
......@@ -31,7 +31,7 @@
</view>
<view class="btn" bind:tap="toItinerary">
<image class="icon" src="./history.png" mode="" />
<view class="text">{{isEn?"My Itinerary":"我的行程"}}<text style="margin-left: 6px;" wx:if="{{itineraryCount>0}}">{{itineraryCount}}</text></view>
<view class="text">{{isEn?"Saved Items":"商品收藏"}}</view>
<image class="arrow" src="./arrow.png" mode="" />
</view>
</view>
......@@ -39,7 +39,7 @@
</view>
<view style="height: 90px;"></view>
</scroll-view>
<custom-tab-bar wx:if="{{!bulkDeleting}}" current-index="{{2}}" bind:tab="handleTab"></custom-tab-bar>
<custom-tab-bar wx:if="{{!bulkDeleting}}" current-index="{{3}}" bind:tab="handleTab"></custom-tab-bar>
<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 { findNearbyLocations } from "../../util";
import { findNearbyLocations, getPoiName, getDistance } from "../../util";
Page({
behaviors: [langBehavior],
/**
......@@ -9,6 +9,8 @@ Page({
showTip1: false,
showTip2: false,
showTip3: false,
showTip4: false,
pois: null,
couponId: null,
receivingCoupon: false,
poi: null,
......@@ -21,6 +23,7 @@ Page({
*/
async onLoad(options) {
const { lastNav } = getApp().globalData;
if (!lastNav) return this.toIndex();
this.setData({ lastNav });
try {
this.setData({
......@@ -29,12 +32,20 @@ Page({
} catch (error) {
console.error("设置卡路里失败", error);
}
if (!lastNav) return this.toIndex();
const poi = this.getEndPoi();
console.log("导航结束页面poi", poi);
// 自动收藏
// if (poi) this.collectPoi(poi);
this.setData({ poi });
if (getApp().isCardNav) {
getApp().isCardNav = false;
const checkInResult = await this.checkIn(poi);
if (checkInResult === "showTip4") return this.setData({ showTip4: true });
if (checkInResult) return this.setData({ pois: checkInResult });
return;
}
const rewardConfig = await this.getRewardConfig();
console.log(rewardConfig);
if (!rewardConfig) return;
......@@ -44,12 +55,12 @@ Page({
if (isvalid) {
try {
getApp().sensors?.track("ExposureActivityCoupon", {
short_market_name: "二区东",
...(poi.facilityId
? {
booth_floor: poi.tx.poi_fl_seq,
}
: {
short_market_name: poi.ywZh.marketNameDtl,
booth_addr_street: poi.ywZh.boothAddrStreet,
booth_no: poi.ywZh.boothNo,
industry: poi.ywZh.frontIndustryCategory,
......@@ -66,20 +77,117 @@ Page({
},
toIndex() {
getApp().globalData.lastNav = null;
console.log("toIndex");
wx.reLaunch({
url: "/pages/index/index",
});
},
async checkIn(poi) {
try {
const app = getApp();
const res = await app.cardApi.check(poi);
if (!res) return null;
if (res.isFinish && res.receiveIsSuccess === 1) return "showTip4";
if (res.isFinish || !res.activityId) return null;
// 1. 获取活动详情
const card = await app.cardApi.get(res.activityId);
const rawList = card?.activityShopList?.filter(
(el) => el.checkInStatus === 0,
);
if (!rawList?.length) return null;
// 2. 自动填充 POI
const list = await app.poiApi.populate(rawList, {
getType: (item) => item.shopType,
getId: (item) => item.shopId,
getBooth: (item) => item.boothNo,
});
const { userLocation } = app;
// 3. 处理数据 (距离计算 & 格式化)
const pois = list
.filter((item) => item.poi?.tx) // 确保有坐标
.map((item) => {
const { poi } = item;
let distance = null;
if (userLocation) {
const { latitude, longitude } = poi.tx.poi_location;
distance = Math.ceil(
getDistance(
userLocation.latitude,
userLocation.longitude,
Number(latitude),
Number(longitude),
),
);
}
return {
...item,
distance,
poiName: getPoiName(poi, this.data.isEn),
poiAvatar: poi.ywZh?.cover || poi.facility?.logo,
};
});
// 4. 排序与返回
if (userLocation) pois.sort((a, b) => a.distance - b.distance);
return pois.length ? pois : null;
} catch (error) {
console.error(error);
return null;
}
},
handleGo({ currentTarget: { id } }) {
const poi = this.data.pois.find((el) => el.shopId === id);
if (poi.shopType === 1)
wx.navigateTo({
url: `/pages/poi-map/index?shopId=${poi.shopId}&isCardNav=true`,
});
else {
wx.navigateTo({
url: `/pages/poi-map/index?facilityId=${poi.shopId}&isCardNav=true`,
});
}
},
async isCouponOnValid(couponId) {
try {
const { marketurl, get } = getApp();
const { marketurl, get, globalData } = getApp();
const {
data: { code, data },
} = await get(`${marketurl}/coupon/coupon/info?couponId=${couponId}`);
} = await get(`${marketurl}/coupon/coupon/info?couponId=${couponId}`, {
Authorization: `Bearer ${globalData.user.access_token}`,
});
if (code === 200) {
console.log("券详情", data);
if (data.leftQuantity > 0) return true;
// 检查库存
if (data.leftQuantity <= 0) {
console.log("券库存不足", data.leftQuantity);
return false;
}
// 检查有效期
const now = new Date();
const openStart = new Date(data.openStart);
const openEnd = new Date(data.openEnd);
if (now < openStart || now > openEnd) {
console.log("券未到领取时间", openStart, openEnd);
return false;
}
// 检查领取限制
if (data.recordSize >= data.receiveLimit) {
console.log("券到达领取限制", data.recordSize, data.receiveLimit);
return false;
}
return true;
} else {
return false;
}
......@@ -108,24 +216,40 @@ Page({
if (success) getApp().refreshCollection();
console.log(`自动收藏poi${success ? "成功" : "失败"}`);
},
getEndPoi() {
const { txQmMap, globalData, indexData } = getApp();
const { lastNav } = globalData;
const { latitude, longitude, floorName } = lastNav.endPoint;
async getEndPoi() {
const app = getApp();
const { txQmMap, indexData, globalData } = app;
// 防御性编程:防止 lastNav 为空报错
const endPoint = globalData.lastNav?.endPoint;
if (!endPoint) return null;
const { latitude, longitude, floorName } = endPoint;
try {
const list = findNearbyLocations(
// 1. 查找最近点 (利用 indexData 空间索引)
const [shineiId] = findNearbyLocations(
latitude,
longitude,
floorName,
indexData
indexData,
);
if (list.length) {
console.log("txQmMap[list[0]]", txQmMap[list[0]]);
return txQmMap[list[0]];
} else {
return null;
}
const baseInfo = txQmMap?.[shineiId];
// 2. 没找到基础信息,直接返回
if (!baseInfo) return null;
// 3. 动态查询详情
// facilityId 存在与否推断 "2"(设施) 或 "1"(店铺)
const poi = await app.poiApi.getOne({
shopType: baseInfo.facilityId ? "2" : "1",
shopId: baseInfo.shopId || baseInfo.facilityId,
boothNo: baseInfo.boothNo,
});
console.log("getEndPoi result:", poi);
return poi;
} catch (error) {
console.error("getEndPoi error:", error);
return null;
}
},
......@@ -140,7 +264,7 @@ Page({
{
Authorization: `Bearer ${globalData.user.access_token}`,
userId: globalData.user.user.userId,
}
},
);
if (code === 20000) {
console.log("积分领取成功" + message);
......@@ -162,13 +286,13 @@ Page({
const { poi, couponId } = this.data;
getApp().sensors?.track("ActivityCouponClick", {
is_receive: true,
short_market_name: "二区东",
coupon_record_id: couponId,
...(poi.facilityId
? {
booth_floor: poi.tx.poi_fl_seq,
}
: {
short_market_name: poi.ywZh.marketNameDtl,
booth_addr_street: poi.ywZh.boothAddrStreet,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
......@@ -186,7 +310,7 @@ Page({
{},
{
Authorization: `Bearer ${globalData.user.access_token}`,
}
},
);
if (code === 200) {
this.setData({ showTip2: false, showTip3: true });
......@@ -210,13 +334,13 @@ Page({
const { poi, couponId } = this.data;
getApp().sensors?.track("ActivityCouponClick", {
is_receive: false,
short_market_name: "二区东",
coupon_record_id: couponId,
...(poi.facilityId
? {
booth_floor: poi.tx.poi_fl_seq,
}
: {
short_market_name: poi.ywZh.marketNameDtl,
booth_addr_street: poi.ywZh.boothAddrStreet,
industry: poi.ywZh.frontIndustryCategory,
booth_floor: poi.ywZh.addrFloor,
......@@ -227,6 +351,12 @@ Page({
}
this.setData({ showTip2: false });
},
closeTip4() {
this.setData({ showTip4: false });
},
closePois() {
this.setData({ pois: null });
},
doNothing() {},
onReady() {},
......@@ -244,9 +374,7 @@ Page({
* 生命周期函数--监听页面卸载
*/
onUnload() {
wx.reLaunch({
url: "/pages/index/index",
});
getApp().blurPoi();
},
/**
......@@ -265,8 +393,8 @@ Page({
onShareAppMessage() {
return {
title: this.data.isEn
? "Share Chinagoods Nav District 2 East indoor navigation miniprogram"
: "分享义乌商贸城二区东室内导航小程序,助你场内高效找店",
? "Share Chinagoods Nav indoor navigation miniprogram"
: "义乌小商品城市场室内导航,助您精准导航到店",
path: `/pages/index/index?fromshare=true`,
imageUrl: this.data.isEn
? `https://cdnimg.chinagoods.com/png/2025/08/13/qmzbxkjo3fse9xs5c2uujdc60tsc3wum.png`
......
{
"usingComponents": {}
"usingComponents": {
"shop-maingoods": "/components/shop-maingoods/index",
"shop-addr": "/components/shop-addr/index",
"shop-name": "/components/shop-name/index"
}
}
......@@ -251,6 +251,218 @@
z-index: 3;
}
}
.tip4 {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 4;
.coupon {
position: absolute;
top: 77px;
left: 0;
right: 0;
margin: auto;
width: 304px;
height: 390px;
z-index: 1;
}
.close {
position: absolute;
display: flex;
top: 515px;
left: 0;
right: 0;
margin: auto;
width: 32px;
height: 32px;
justify-content: center;
align-items: center;
border-radius: 24px;
border: 1px solid rgba(0, 0, 0, 0.06);
background: rgba(0, 0, 0, 0.06);
backdrop-filter: blur(4px);
z-index: 3;
}
}
.pois {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 4;
.pois-inner {
position: absolute;
width: 302px;
left: 0;
right: 0;
top: 63px;
margin: auto;
background: #fff;
border-radius: 8px;
overflow: hidden;
.top-bg {
position: absolute;
top: 0;
right: 0;
width: 203px;
height: 212px;
z-index: 1;
}
.close {
position: absolute;
display: flex;
top: 10px;
right: 10px;
width: 32px;
height: 32px;
justify-content: center;
align-items: center;
border-radius: 24px;
background: rgba(0, 0, 0, 0.06);
z-index: 3;
}
.top {
position: relative;
z-index: 2;
padding: 20px 16px;
.avatar {
width: 96px;
height: 96px;
}
.t1 {
color: #333;
font-family: "PingFang SC";
font-size: 18px;
font-style: normal;
font-weight: 600;
line-height: 24px;
margin-top: 10px;
}
.t2 {
color: #666;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
margin-top: 6px;
}
.t3 {
color: #666;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 18px;
margin-top: 6px;
}
.row {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 18px;
.dis {
display: flex;
align-items: baseline;
color: #333;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
.v {
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 22px;
color: #e92927;
}
}
.go {
display: flex;
width: 174px;
height: 38px;
border-radius: 99px;
background: linear-gradient(90deg, #fa643c 0%, #e92927 100%);
gap: 4px;
align-items: center;
justify-content: center;
color: #fff;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 18px;
}
}
}
.list {
background: #f3f3f3;
height: 220px;
.inner {
padding: 16px;
.t1 {
color: #333;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 18px;
margin-bottom: 12px;
}
.item {
display: flex;
align-items: center;
padding: 8px 12px 8px 8px;
height: 56px;
margin-bottom: 8px;
border-radius: 10px;
background: linear-gradient(180deg, #fff 0%, #fff 100%);
.avatar {
width: 40px;
height: 40px;
border-radius: 8px;
}
.name {
flex: 1;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #333;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 600;
line-height: normal;
padding: 0 8px;
}
.go {
display: flex;
align-items: center;
justify-content: center;
width: 64px;
height: 31px;
border-radius: 99px;
background: linear-gradient(90deg, #fa643c 0%, #e92927 100%);
color: #fff3f3;
text-align: center;
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 600;
line-height: normal;
}
}
}
}
}
}
.size-20 {
width: 20px;
height: 20px;
......
......@@ -53,7 +53,7 @@
<view class="t1">积分领取成功!</view>
<view class="t2">导航到店积分福利已发放至您的会员账户</view>
</view>
<view class="tip2" bing:tap="closeTip2" wx:if="{{showTip2}}">
<view class="tip2" bind:tap="closeTip2" wx:if="{{showTip2}}">
<image class="coupon" src="https://cdnimg.chinagoods.com/png/2025/08/05/tokz4ivypgnaljlau3juad1zq2zgf2o4.png" mode="" catch:tap="doNothing" />
<image catch:tap="receiveCoupon" class="btn" src="./btn.png" mode="" />
<view class="close" catch:tap="closeTip2">
......@@ -64,4 +64,63 @@
<view class="t1">领取成功!</view>
<view class="t2">活动券将发放您的会员账户</view>
</view>
<view class="tip4" bind:tap="closeTip4" wx:if="{{showTip4}}">
<image class="coupon" src="https://cdnimg.chinagoods.com/png/2025/12/19/gnu2fvvbgoe6jvpt984ls43qocmldhad.png" mode="" catch:tap="doNothing" />
<view class="close" catch:tap="closeTip4">
<image class="size-20" src="./close.png" mode="" />
</view>
</view>
<view class="pois" wx:if="{{pois}}" catch:tap="closePois">
<view class="pois-inner" catch:tap="doNothing">
<image class="top-bg" src="https://cdnimg.chinagoods.com/png/2025/12/19/gq8chjlyczzz7rvadgnwgys0daeq2smq.png" mode="" />
<view class="close" catch:tap="closePois">
<image class="size-20" src="./close-black.png" mode="" />
</view>
<view class="top">
<image class="avatar" src="{{pois[0].poiAvatar}}" mode="aspectFill" />
<block wx:if="{{pois[0].poi.facility}}">
<view class="t1">
{{isEn?pois[0].poi.facility.nameEn:pois[0].poi.facility.name}}
</view>
<view class="t2">{{isEn?pois[0].poi.facility.addressEn:pois[0].poi.facility.address}}</view>
</block>
<block wx:else>
<view class="t1">
<shop-name shop="{{pois[0].poi}}"></shop-name>
</view>
<view class="t2">
<shop-addr shop="{{pois[0].poi}}"></shop-addr>
</view>
<view class="t3">
<shop-maingoods shop="{{pois[0].poi}}"></shop-maingoods>
</view>
</block>
<view class="row">
<view class="dis">{{!pois[0].distance?'':isEn?'':'距您:'}}
<view wx:if="{{pois[0].distance}}" class="v">{{pois[0].distance}}m</view>
{{!pois[0].distance?'':isEn?' away':''}}
</view>
<view class="go" bind:tap="handleGo" id="{{pois[0].shopId}}">
<image class="size-20" src="./go.png" mode="" />
<view>{{isEn?'Check in':'去打卡'}}</view>
</view>
</view>
</view>
<scroll-view class="list" wx:if="{{pois.length>1}}" scroll-y>
<view class="inner">
<view class="t1">{{isEn?'Other Check-in Spots':'其它打卡点'}}</view>
<view class="item" wx:for="{{pois}}" wx:key="shopId" wx:if="{{index!==0}}">
<image class="avatar" src="{{item.poiAvatar}}" mode="" />
<view class="name" wx:if="{{item.poi.facility}}">
{{isEn?item.poi.facility.nameEn:item.poi.facility.name}}
</view>
<view class="name" wx:else>
<shop-name shop="{{item.poi}}"></shop-name>
</view>
<view class="go" id="{{item.shopId}}" bind:tap="handleGo">{{isEn?'Check in':'去打卡'}}</view>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
\ No newline at end of file
......@@ -2,56 +2,36 @@ import langBehavior from "../../behaviors/langBehavior";
import poiFocusBehavior from "../../behaviors/poiFocusBehavior";
import modalBehavior from "../../behaviors/modalBehavior";
import { getShopShareTitle, getFacilityShareTitle } from "../../util";
const app = getApp();
Page({
behaviors: [langBehavior, poiFocusBehavior, modalBehavior],
data: {
buildingId: "3307001549220",
floorName: "1F",
floors: [
{ floorName: "3F", displayName: "3F" },
{ floorName: "2F", displayName: "2F" },
{ floorName: "1F", displayName: "1F" },
],
floors: [],
resetCount: 0,
userLocation: null,
reseting: false,
acts: [],
},
async onLoad({ shopId, facilityId }) {
const app = getApp();
if (shopId) {
if (!app.shopIdMap) {
app.events.once("globalData", () => {
const shop = app.shopIdMap[shopId];
async onLoad({ shopId, boothNo, facilityId, isCardNav }) {
app.isCardNav = !!isCardNav;
if (boothNo) {
const shop = await app.poiApi.getOne({ shopType: "1", shopId, boothNo });
if (shop) {
if (shop.tx) this.setData({ floorName: shop.tx.poi_fl_name });
app.focusPoi(shop);
this.setStateByPoi(shop);
}
});
} else {
const shop = app.shopIdMap[shopId];
} else if (shopId) {
const shop = await app.poiApi.getOne({ shopType: "1", shopId });
if (shop) {
if (shop.tx) this.setData({ floorName: shop.tx.poi_fl_name });
app.focusPoi(shop);
}
}
}
if (facilityId) {
if (!app.facilityIdMap) {
app.events.once("globalData", () => {
const facility = app.facilityIdMap[facilityId];
if (facility) {
if (facility.tx)
this.setData({ floorName: facility.tx.poi_fl_name });
app.focusPoi(facility);
this.setStateByPoi(shop);
}
} else if (facilityId) {
const facility = await app.poiApi.getOne({
shopType: "2",
shopId: facilityId,
});
} else {
const facility = app.facilityIdMap[facilityId];
if (facility) {
if (facility.tx) this.setData({ floorName: facility.tx.poi_fl_name });
app.focusPoi(facility);
}
this.setStateByPoi(facility);
}
}
this.setUserLocation = () => {
......@@ -60,6 +40,27 @@ Page({
getApp().events.on("userLocation", this.setUserLocation);
this.setUserLocation();
},
setStateByPoi(poi) {
const app = getApp();
if (poi?.tx) {
const building = app.buildings.find(
({ buildingId }) => buildingId === poi?.tx?.bld_id,
);
this.setData({
floors: building?.floors,
buildingId: poi.tx.bld_id,
floorName: poi.tx.poi_fl_name,
});
} else {
const building = app.currentBuilding;
this.setData({
floors: building.floors,
buildingId: building.buildingId,
floorName: building.floors[0],
});
}
app.focusPoi(poi);
},
onUnload() {
if (this.setUserLocation)
getApp().events.off("userLocation", this.setUserLocation);
......
import poiFocusBehavior from "../../../behaviors/poiFocusBehavior";
const defaultScale = 20;
const defaultRotate = 329;
const defaultLatitude = 29.331723;
const defaultLongitude = 120.106838;
const defaultSkew = 30;
Component({
......@@ -16,12 +14,12 @@ Component({
},
data: {
latitude: defaultLatitude,
longitude: defaultLongitude,
latitude: getApp().currentBuilding.latlng.lat,
longitude: getApp().currentBuilding.latlng.lng,
setting: {
skew: defaultSkew,
rotate: defaultRotate,
scale: defaultScale,
scale: getApp().currentBuilding.scale,
},
},
observers: {
......@@ -32,33 +30,6 @@ Component({
this.setIndoorFloor();
this.handleModel();
},
"floorName,acts"() {
this.setData({
markers: this.data.acts
.filter(({ floor_name }) => floor_name === this.data.floorName)
.map(({ latitude, longitude, short_name, id }) => ({
id,
latitude,
longitude,
iconPath: "./actMarker.png",
width: 1,
height: 1,
zIndex: 1,
callout: {
content: short_name,
color: "#E92927",
fontSize: 12,
bgColor: "#ffffff",
padding: 6,
borderRadius: 100,
borderWidth: 1,
borderColor: "#eeeeee",
textAlign: "center",
display: "ALWAYS",
},
})),
});
},
focusedPoi(poi) {
try {
if (!poi) {
......@@ -118,6 +89,16 @@ Component({
})
);
}, 500);
} else {
this.setData({
latitude: getApp().currentBuilding.latlng.lat,
longitude: getApp().currentBuilding.latlng.lng,
setting: {
skew: defaultSkew,
rotate: defaultRotate,
scale: getApp().currentBuilding.scale,
},
});
}
} catch (error) {
console.error(error);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论