WAP 定位模块维护规范
WAP 定位模块说明
核心原则(必读)
定位与首页版式完全解耦。 改 Index/index.html、index.css 时不要动定位文件。
header.html(唯一入口)
├── wapLocationBoot.js 打开/关闭弹层
├── locationService.js GPS / IP 定位
├── wapLocationCore.js 城市切换逻辑(纯 JS 文件,不在模板里)
└── city_display.html 仅 HTML + 样式(无内联脚本)
首页只放一个按钮:class="wap-location-trigger",其余交给 header。
文件清单
| 文件 | 职责 |
|---|---|
themes/default/Wap/public/header.html | 加载脚本、CITY_ID/GLOBAL_LOCATION_CONFIG、include 弹层 |
Public/js/wapLocationBoot.js | 启动层:顶栏点击打开/关闭弹层 |
Public/js/locationService.js | GPS→IP→默认城市 |
Public/js/wapLocationCore.js | 核心逻辑(从模板抽出,避免 ThinkPHP 破坏 JS) |
themes/default/Wap/public/city_display.html | 弹层 HTML + CSS |
Banyan/Lib/Action/Wap/LocationApiAction.class.php | 定位 API |
为什么从模板抽出 JS?
city_display.html 内联脚本经 ThinkPHP 编译后,正则 /\+/g 会变成 /+/g(非法),整段脚本不执行,面板永远「检测中…」。
现逻辑在 wapLocationCore.js,模板只输出 HTML。
页面开关
| 变量 | 效果 |
|---|---|
hide_wap_city_header=1 | 隐藏默认顶栏,弹层与脚本照常 |
hide_wap_city_location=1 | 整页关闭定位 |
改首页时的规矩
| 可以改 | 禁止改 |
|---|---|
| 首页 HTML/CSS | wapLocationCore.js / locationService.js |
| 按钮样式 | city_display.html 内联脚本(已删除) |
wap-location-trigger class | 首页里写弹层 JS |
部署后
清除 Banyan/Runtime/Cache/,强制刷新页面。
版本记录
- 2026-06-23 v3:定位逻辑抽到
wapLocationCore.js;city_display.html仅 HTML;首页去掉重复CITY_ID;新增.cursor/rules/wap-location-isolated.mdc - 2026-06-23 v2:IP 优先走
Home/getCityByIP;wapLocationBoot.js启动层
页面开关(Controller 赋值)
| 变量 | 值 | 效果 |
|---|---|---|
| (默认) | 未设置 | 加载完整模块 + 默认顶栏条 |
hide_wap_city_header = 1 | 首页等 | 隐藏 city_display 自带顶栏,弹层与脚本照常加载 |
hide_wap_city_location = 1 | 商家详情、AI 等 | 整页关闭定位模块 |
首页示例(IndexAction::index):
$this->assign('hide_wap_city_header', 1); // 用首页自定义顶栏
// 不要设置 hide_wap_city_location
首页正确写法
HTML(themes/default/Wap/Index/index.html):
<a href="javascript:void(0);" class="top-addr wap-location-trigger" title="切换城市">
<i class="iconfont icon-daohang"></i>
<span class="wap-location-city" id="header-current-city">城市名</span>
</a>
不要写:
// ❌ 禁止在首页重复绑定
$('#wap-city-selector').show();
$(document).on('click', '.wap-location-trigger', ...);
点击由 wapLocationBoot.js 统一处理,完整逻辑由 city_display.html 注册到 WapLocationBoot.register()。
全局 JS 接口
| 方法 | 说明 |
|---|---|
openWapCitySelector() | 打开城市弹层 |
closeWapCitySelector() | 关闭城市弹层 |
WapLocationBoot.register({ open, close }) | 由 city_display 注入完整实现 |
LocationService.getCurrentLocation() | 执行自动定位(Promise) |
window.CITY_ID / window.CITY_NAME | 当前城市(header 输出) |
API 端点(WAP)
/index.php?g=Wap&m=LocationApi&a=getCityByGPS POST
/index.php?g=Wap&m=LocationApi&a=getCityByIP GET
/index.php?g=Wap&m=LocationApi&a=getDefaultCity GET
/index.php?g=Wap&m=LocationApi&a=setManualCity POST
/index.php?g=Wap&m=LocationApi&a=getProvinceList GET
/index.php?g=Wap&m=LocationApi&a=getCitiesByProvince GET
/index.php?g=Wap&m=LocationApi&a=checkSubstation GET
修改首页时的注意事项
| 可以改 | 不要改 |
|---|---|
| 首页顶栏 HTML/CSS | city_display.html 内打开/关闭事件(已交给 boot) |
| 按钮样式、图标 | locationService.js 定位链路 |
hide_wap_city_header 开关 | 在首页复制一套 $('#wap-city-selector') 逻辑 |
常见问题
1. 点击城市没反应
- 确认
hide_wap_city_location未设为 1 - 确认按钮有 class
wap-location-trigger - 控制台是否有 JS 报错(旧微信不支持
URLSearchParams已用getUrlParam兼容) - 确认
wapLocationBoot.js已在header.html中加载
2. 弹层打开但信息全是「检测中…」或无法定位
- 线上
Wap/getCityByIP若未部署会报「非法操作」——IP 定位应走Home/getCityByIP(已在locationService.js和quickIpLocate中优先使用) - 弹层能开说明 boot 层正常;定位失败查控制台
[定位]/[LOCATION]日志 - 可手动执行
WapLocationRetry()重试定位
3. 生产环境 API 自测
curl "https://域名/index.php?g=Home&m=LocationApi&a=getCityByIP"
curl "https://域名/index.php?g=Wap&m=LocationApi&a=getDefaultCity"
4. 与 ba 项目同步
同步时整包复制以下文件,不要只改首页:
Public/js/wapLocationBoot.jsPublic/js/locationService.jsthemes/default/Wap/public/city_display.htmlthemes/default/Wap/public/header.html(加载顺序)Banyan/Lib/Action/Wap/LocationApiAction.class.php
部署后清除缓存:Banyan/Runtime/Cache/
版本记录
- 2026-06-23 v2:
locationService.js对齐 ba 简化 GPS 流程;IP 优先走Home/getCityByIP;新增quickIpLocate页面加载即定位;finally保证信息面板刷新;scheduleAutoLocate打开弹层时补定位。 - 2026-06-23 v1:新增
wapLocationBoot.js启动层;WAP 端补充getCityByIP(需部署到线上);兼容旧版微信 WebView。
