clxx 3.0.2 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/AGENTS.md +49 -3
  2. package/build/Alert/style.js +15 -14
  3. package/build/CarouselNotice/style.js +2 -1
  4. package/build/CitySelect/style.js +40 -39
  5. package/build/Container/index.js +21 -1
  6. package/build/DatePicker/style.d.ts +1 -1
  7. package/build/DatePicker/style.js +25 -24
  8. package/build/Indicator/index.js +2 -1
  9. package/build/Loading/Wrapper.js +3 -2
  10. package/build/Loading/style.js +7 -6
  11. package/build/MapLocationSelection/buildSelectedLocation.d.ts +16 -0
  12. package/build/MapLocationSelection/buildSelectedLocation.js +123 -0
  13. package/build/MapLocationSelection/createProvider.d.ts +8 -0
  14. package/build/MapLocationSelection/createProvider.js +33 -0
  15. package/build/MapLocationSelection/getLocation.d.ts +8 -0
  16. package/build/MapLocationSelection/getLocation.js +112 -0
  17. package/build/MapLocationSelection/index.d.ts +16 -0
  18. package/build/MapLocationSelection/index.js +985 -0
  19. package/build/MapLocationSelection/loader.amap.d.ts +48 -0
  20. package/build/MapLocationSelection/loader.amap.js +125 -0
  21. package/build/MapLocationSelection/loader.bmap.d.ts +8 -0
  22. package/build/MapLocationSelection/loader.bmap.js +60 -0
  23. package/build/MapLocationSelection/provider.amap.d.ts +38 -0
  24. package/build/MapLocationSelection/provider.amap.js +659 -0
  25. package/build/MapLocationSelection/provider.bmap.d.ts +36 -0
  26. package/build/MapLocationSelection/provider.bmap.js +837 -0
  27. package/build/MapLocationSelection/provider.d.ts +45 -0
  28. package/build/MapLocationSelection/provider.js +10 -0
  29. package/build/MapLocationSelection/style.d.ts +4 -0
  30. package/build/MapLocationSelection/style.js +442 -0
  31. package/build/MapLocationSelection/types.d.ts +29 -0
  32. package/build/MapLocationSelection/types.js +22 -0
  33. package/build/MapLocationSelection/userMarker.d.ts +2 -0
  34. package/build/MapLocationSelection/userMarker.js +95 -0
  35. package/build/RegionPicker/style.js +34 -33
  36. package/build/ScrollView/style.js +5 -4
  37. package/build/Toast/style.js +6 -5
  38. package/build/index.d.ts +3 -0
  39. package/build/index.js +8 -2
  40. package/build/utils/rem.d.ts +1 -0
  41. package/build/utils/rem.js +48 -0
  42. package/package.json +2 -2
  43. package/test/src/index/index.jsx +5 -0
  44. package/test/src/index.jsx +1 -0
  45. package/test/src/map-location-selection/index.jsx +192 -0
@@ -5,6 +5,7 @@ exports.createStyle = createStyle;
5
5
  const react_1 = require("@emotion/react");
6
6
  const color_1 = require("../utils/color");
7
7
  const theme_1 = require("../utils/theme");
8
+ const rem_1 = require("../utils/rem");
8
9
  // 与 CitySelect 一致的设计变量(带线条风格)
9
10
  const textPrimary = "#1f2328";
10
11
  const textSecondary = "#6b7280";
@@ -15,7 +16,7 @@ const border = "#e5e7eb";
15
16
  exports.DEFAULT_PRIMARY = "#2f7dff";
16
17
  function createStyle(primary, rounded = true) {
17
18
  const primaryActive = (0, color_1.darken)(primary, 0.15);
18
- const sheetRadius = rounded ? ".24rem" : "0";
19
+ const sheetRadius = rounded ? (0, rem_1.r)(24) : "0";
19
20
  return {
20
21
  // 内容容器:动画/遮罩/全屏由 Dialog 提供,这里只保留视觉与排版
21
22
  sheet: (0, react_1.css)({
@@ -36,27 +37,27 @@ function createStyle(primary, rounded = true) {
36
37
  // 标题栏:底部 hairline 与列表区分;按钮中等字重
37
38
  header: (0, react_1.css)({
38
39
  flexShrink: 0,
39
- height: ".92rem",
40
+ height: (0, rem_1.r)(92),
40
41
  display: "flex",
41
42
  alignItems: "center",
42
43
  justifyContent: "space-between",
43
- padding: "0 .16rem",
44
+ padding: `0 ${(0, rem_1.r)(16)}`,
44
45
  borderBottom: `1px solid ${border}`,
45
46
  }),
46
47
  title: (0, react_1.css)({
47
48
  flex: 1,
48
49
  textAlign: "center",
49
- fontSize: ".3rem",
50
+ fontSize: (0, rem_1.r)(30),
50
51
  fontWeight: 600,
51
52
  color: textPrimary,
52
- letterSpacing: ".01rem",
53
+ letterSpacing: (0, rem_1.r)(1),
53
54
  }),
54
55
  btn: (0, react_1.css)({
55
- minWidth: "1.1rem",
56
- padding: "0 .08rem",
57
- fontSize: ".28rem",
56
+ minWidth: (0, rem_1.r)(110),
57
+ padding: `0 ${(0, rem_1.r)(8)}`,
58
+ fontSize: (0, rem_1.r)(28),
58
59
  fontWeight: 400,
59
- lineHeight: ".92rem",
60
+ lineHeight: (0, rem_1.r)(92),
60
61
  cursor: "pointer",
61
62
  transition: "opacity .15s, color .15s",
62
63
  }),
@@ -83,8 +84,8 @@ function createStyle(primary, rounded = true) {
83
84
  flexShrink: 0,
84
85
  display: "flex",
85
86
  alignItems: "stretch",
86
- height: ".8rem",
87
- padding: "0 .16rem",
87
+ height: (0, rem_1.r)(80),
88
+ padding: `0 ${(0, rem_1.r)(16)}`,
88
89
  backgroundColor: bgSubtle,
89
90
  borderBottom: `1px solid ${border}`,
90
91
  }),
@@ -94,8 +95,8 @@ function createStyle(primary, rounded = true) {
94
95
  display: "flex",
95
96
  alignItems: "center",
96
97
  justifyContent: "center",
97
- padding: "0 .08rem",
98
- fontSize: ".26rem",
98
+ padding: `0 ${(0, rem_1.r)(8)}`,
99
+ fontSize: (0, rem_1.r)(26),
99
100
  color: textSecondary,
100
101
  position: "relative",
101
102
  cursor: "pointer",
@@ -103,7 +104,7 @@ function createStyle(primary, rounded = true) {
103
104
  whiteSpace: "nowrap",
104
105
  overflow: "hidden",
105
106
  textOverflow: "ellipsis",
106
- letterSpacing: ".01rem",
107
+ letterSpacing: (0, rem_1.r)(1),
107
108
  }),
108
109
  tabPlaceholder: (0, react_1.css)({
109
110
  color: textTertiary,
@@ -115,18 +116,18 @@ function createStyle(primary, rounded = true) {
115
116
  content: '""',
116
117
  position: "absolute",
117
118
  left: "50%",
118
- bottom: ".06rem",
119
+ bottom: (0, rem_1.r)(6),
119
120
  transform: "translateX(-50%)",
120
- width: ".32rem",
121
- height: ".04rem",
121
+ width: (0, rem_1.r)(32),
122
+ height: (0, rem_1.r)(4),
122
123
  backgroundColor: primary,
123
- borderRadius: ".02rem",
124
+ borderRadius: (0, rem_1.r)(2),
124
125
  },
125
126
  }),
126
127
  // 选项列表:固定高度避免跳变
127
128
  list: (0, react_1.css)({
128
129
  flexShrink: 0,
129
- height: "5.28rem",
130
+ height: (0, rem_1.r)(528),
130
131
  overflowY: "auto",
131
132
  overflowX: "hidden",
132
133
  WebkitOverflowScrolling: "touch",
@@ -136,11 +137,11 @@ function createStyle(primary, rounded = true) {
136
137
  // 列表项:底部 hairline 分隔(CitySelect 风),按下浅灰底
137
138
  listItem: (0, react_1.css)({
138
139
  position: "relative",
139
- height: ".88rem",
140
+ height: (0, rem_1.r)(88),
140
141
  display: "flex",
141
142
  alignItems: "center",
142
- padding: "0 .3rem",
143
- fontSize: ".3rem",
143
+ padding: `0 ${(0, rem_1.r)(30)}`,
144
+ fontSize: (0, rem_1.r)(30),
144
145
  color: textPrimary,
145
146
  backgroundColor: bgPage,
146
147
  borderBottom: `1px solid ${border}`,
@@ -155,7 +156,7 @@ function createStyle(primary, rounded = true) {
155
156
  whiteSpace: "nowrap",
156
157
  overflow: "hidden",
157
158
  textOverflow: "ellipsis",
158
- letterSpacing: ".01rem",
159
+ letterSpacing: (0, rem_1.r)(1),
159
160
  }),
160
161
  listItemSelected: (0, react_1.css)({
161
162
  color: primary,
@@ -163,28 +164,28 @@ function createStyle(primary, rounded = true) {
163
164
  }),
164
165
  // 对勾
165
166
  checkIcon: (0, react_1.css)({
166
- width: ".32rem",
167
- height: ".32rem",
167
+ width: (0, rem_1.r)(32),
168
+ height: (0, rem_1.r)(32),
168
169
  flexShrink: 0,
169
- marginLeft: ".16rem",
170
+ marginLeft: (0, rem_1.r)(16),
170
171
  position: "relative",
171
172
  "&::after": {
172
173
  content: '""',
173
174
  position: "absolute",
174
- left: ".06rem",
175
- top: ".04rem",
176
- width: ".1rem",
177
- height: ".2rem",
175
+ left: (0, rem_1.r)(6),
176
+ top: (0, rem_1.r)(4),
177
+ width: (0, rem_1.r)(10),
178
+ height: (0, rem_1.r)(20),
178
179
  border: `solid ${primary}`,
179
- borderWidth: "0 .03rem .03rem 0",
180
+ borderWidth: `0 ${(0, rem_1.r)(3)} ${(0, rem_1.r)(3)} 0`,
180
181
  transform: "rotate(45deg)",
181
182
  },
182
183
  }),
183
184
  // 空数据占位
184
185
  empty: (0, react_1.css)({
185
- padding: ".6rem 0",
186
+ padding: `${(0, rem_1.r)(60)} 0`,
186
187
  textAlign: "center",
187
- fontSize: ".26rem",
188
+ fontSize: (0, rem_1.r)(26),
188
189
  color: textTertiary,
189
190
  }),
190
191
  };
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.style = void 0;
4
4
  const react_1 = require("@emotion/react");
5
+ const rem_1 = require("../utils/rem");
5
6
  // 模仿 iOS「正在输入」气泡的三点呼吸节奏
6
7
  const dotPulse = (0, react_1.keyframes) `
7
8
  0%, 80%, 100% {
@@ -23,12 +24,12 @@ exports.style = {
23
24
  display: "flex",
24
25
  alignItems: "center",
25
26
  justifyContent: "center",
26
- gap: ".12rem",
27
- padding: ".24rem 0",
27
+ gap: (0, rem_1.r)(12),
28
+ padding: `${(0, rem_1.r)(24)} 0`,
28
29
  },
29
30
  loadingDot: (0, react_1.css) `
30
- width: 0.12rem;
31
- height: 0.12rem;
31
+ width: ${(0, rem_1.r)(12)};
32
+ height: ${(0, rem_1.r)(12)};
32
33
  border-radius: 50%;
33
34
  background: #c7c7cc;
34
35
  animation: ${dotPulse} 1.2s ease-in-out infinite both;
@@ -4,6 +4,7 @@ exports.style = exports.bottomHideAnimation = exports.bottomShowAnimation = expo
4
4
  exports.getAnimation = getAnimation;
5
5
  const react_1 = require("@emotion/react");
6
6
  const theme_1 = require("../utils/theme");
7
+ const rem_1 = require("../utils/rem");
7
8
  const easing = "cubic-bezier(.22,.61,.36,1)";
8
9
  exports.middleShowAnimation = (0, react_1.keyframes) `
9
10
  from {
@@ -95,7 +96,7 @@ exports.style = {
95
96
  left: "50%",
96
97
  transform: "translateX(-50%)",
97
98
  zIndex: 9999,
98
- maxWidth: "6rem",
99
+ maxWidth: (0, rem_1.r)(600),
99
100
  pointerEvents: "none",
100
101
  fontFamily: theme_1.fontStack,
101
102
  WebkitFontSmoothing: "antialiased",
@@ -111,12 +112,12 @@ exports.style = {
111
112
  whiteSpace: "pre-wrap",
112
113
  wordBreak: "break-word",
113
114
  lineHeight: 1.5,
114
- fontSize: ".28rem",
115
+ fontSize: (0, rem_1.r)(28),
115
116
  fontWeight: 400,
116
- letterSpacing: ".01rem",
117
+ letterSpacing: (0, rem_1.r)(1),
117
118
  textAlign: "center",
118
- padding: ".2rem .32rem",
119
- boxShadow: "0 .12rem .32rem rgba(0,0,0,.18)",
119
+ padding: `${(0, rem_1.r)(20)} ${(0, rem_1.r)(32)}`,
120
+ boxShadow: `0 ${(0, rem_1.r)(12)} ${(0, rem_1.r)(32)} rgba(0,0,0,.18)`,
120
121
  backdropFilter: "blur(20px) saturate(160%)",
121
122
  WebkitBackdropFilter: "blur(20px) saturate(160%)",
122
123
  }),
package/build/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export { defaultScroll } from './utils/defaultScroll';
9
9
  export { is } from './utils/is';
10
10
  export { waitFor, waitUntil } from './utils/wait';
11
11
  export { normalizeUnit, splitValue } from './utils/cssUtil';
12
+ export { r } from './utils/rem';
12
13
  export { createApp, history, getHistory } from './utils/createApp';
13
14
  export { createPortalDOM } from './utils/dom';
14
15
  export { useInterval } from './Effect/useInterval';
@@ -37,3 +38,5 @@ export { CarouselNotice } from './CarouselNotice';
37
38
  export { CitySelect, showCitySelect } from './CitySelect';
38
39
  export { DatePicker, showDatePicker } from './DatePicker';
39
40
  export { RegionPicker, showRegionPicker } from './RegionPicker';
41
+ export { MapLocationSelection, showMapLocationSelection, getLocation, } from './MapLocationSelection';
42
+ export type { MapLocationSelectionProps, SelectedLocation, GetLocationOptions, } from './MapLocationSelection';
package/build/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.showUniqToast = exports.showToast = exports.Overlay = exports.Countdowner = exports.ColStart = exports.ColEvenly = exports.ColEnd = exports.ColCenter = exports.ColBetween = exports.ColAround = exports.Col = exports.RowStart = exports.RowEvenly = exports.RowEnd = exports.RowCenter = exports.RowBetween = exports.RowAround = exports.Row = exports.FlexItem = exports.Flex = exports.Container = exports.Ago = exports.useViewport = exports.useWindowResize = exports.useUpdate = exports.useTick = exports.useInterval = exports.createPortalDOM = exports.getHistory = exports.history = exports.createApp = exports.splitValue = exports.normalizeUnit = exports.waitUntil = exports.waitFor = exports.is = exports.defaultScroll = exports.Countdown = exports.calendarTable = exports.registerHostAlias = exports.buildUrlByOption = exports.sendRequest = exports.sugarSend = exports.sendJSON = exports.POST = exports.GET = exports.ago = exports.uniqKey = exports.jsonp = exports.tick = void 0;
4
- exports.showRegionPicker = exports.RegionPicker = exports.showDatePicker = exports.DatePicker = exports.showCitySelect = exports.CitySelect = exports.CarouselNotice = exports.ScrollView = exports.showAlert = exports.AutoGrid = exports.SafeArea = exports.showLoadingAtLeast = exports.showLoading = exports.Indicator = exports.Clickable = exports.showDialog = void 0;
3
+ exports.showToast = exports.Overlay = exports.Countdowner = exports.ColStart = exports.ColEvenly = exports.ColEnd = exports.ColCenter = exports.ColBetween = exports.ColAround = exports.Col = exports.RowStart = exports.RowEvenly = exports.RowEnd = exports.RowCenter = exports.RowBetween = exports.RowAround = exports.Row = exports.FlexItem = exports.Flex = exports.Container = exports.Ago = exports.useViewport = exports.useWindowResize = exports.useUpdate = exports.useTick = exports.useInterval = exports.createPortalDOM = exports.getHistory = exports.history = exports.createApp = exports.r = exports.splitValue = exports.normalizeUnit = exports.waitUntil = exports.waitFor = exports.is = exports.defaultScroll = exports.Countdown = exports.calendarTable = exports.registerHostAlias = exports.buildUrlByOption = exports.sendRequest = exports.sugarSend = exports.sendJSON = exports.POST = exports.GET = exports.ago = exports.uniqKey = exports.jsonp = exports.tick = void 0;
4
+ exports.getLocation = exports.showMapLocationSelection = exports.MapLocationSelection = exports.showRegionPicker = exports.RegionPicker = exports.showDatePicker = exports.DatePicker = exports.showCitySelect = exports.CitySelect = exports.CarouselNotice = exports.ScrollView = exports.showAlert = exports.AutoGrid = exports.SafeArea = exports.showLoadingAtLeast = exports.showLoading = exports.Indicator = exports.Clickable = exports.showDialog = exports.showUniqToast = void 0;
5
5
  var tick_1 = require("./utils/tick");
6
6
  Object.defineProperty(exports, "tick", { enumerable: true, get: function () { return tick_1.tick; } });
7
7
  var jsonp_1 = require("./utils/jsonp");
@@ -32,6 +32,8 @@ Object.defineProperty(exports, "waitUntil", { enumerable: true, get: function ()
32
32
  var cssUtil_1 = require("./utils/cssUtil");
33
33
  Object.defineProperty(exports, "normalizeUnit", { enumerable: true, get: function () { return cssUtil_1.normalizeUnit; } });
34
34
  Object.defineProperty(exports, "splitValue", { enumerable: true, get: function () { return cssUtil_1.splitValue; } });
35
+ var rem_1 = require("./utils/rem");
36
+ Object.defineProperty(exports, "r", { enumerable: true, get: function () { return rem_1.r; } });
35
37
  var createApp_1 = require("./utils/createApp");
36
38
  Object.defineProperty(exports, "createApp", { enumerable: true, get: function () { return createApp_1.createApp; } });
37
39
  Object.defineProperty(exports, "history", { enumerable: true, get: function () { return createApp_1.history; } });
@@ -106,3 +108,7 @@ Object.defineProperty(exports, "showDatePicker", { enumerable: true, get: functi
106
108
  var RegionPicker_1 = require("./RegionPicker");
107
109
  Object.defineProperty(exports, "RegionPicker", { enumerable: true, get: function () { return RegionPicker_1.RegionPicker; } });
108
110
  Object.defineProperty(exports, "showRegionPicker", { enumerable: true, get: function () { return RegionPicker_1.showRegionPicker; } });
111
+ var MapLocationSelection_1 = require("./MapLocationSelection");
112
+ Object.defineProperty(exports, "MapLocationSelection", { enumerable: true, get: function () { return MapLocationSelection_1.MapLocationSelection; } });
113
+ Object.defineProperty(exports, "showMapLocationSelection", { enumerable: true, get: function () { return MapLocationSelection_1.showMapLocationSelection; } });
114
+ Object.defineProperty(exports, "getLocation", { enumerable: true, get: function () { return MapLocationSelection_1.getLocation; } });
@@ -0,0 +1 @@
1
+ export declare function r(px750: number): string;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.r = r;
4
+ // 把 750 设计稿下的像素值转成响应式 css 长度。
5
+ //
6
+ // 库内组件统一使用 r() 表达尺寸,不再写 ".28rem" 字面量——这样即便用户在
7
+ // Container 上传入非 750 的 designWidth(如 375 / 1080),库内组件的视觉比例
8
+ // 仍然按 750 设计稿计算,不会被放大或缩小。
9
+ //
10
+ // 实现原理:依赖 Container 注入的 --clxx-px 变量。
11
+ // - --clxx-px 的语义是「750 设计稿下的 1px 在当前视口下渲染成多少 css px」
12
+ // 即 --clxx-px = clamp(viewport, maxWidth) / 750(单位 px)
13
+ // - r(28) → calc(28 * var(--clxx-px, 1px))
14
+ // 视口 750 时 = 28px
15
+ // 视口 375 时 = 14px
16
+ // 视口 1080(无 maxWidth)时 = 40.32px
17
+ // —— 与原 ".28rem" 在默认 designWidth=750 + 同视口下完全一致
18
+ //
19
+ // fallback 1px:用户未挂 Container 时(或 SSR 首屏未注入 :root 变量),
20
+ // calc 不会因 var() 解析失败而整体 invalid,组件至少能以 750 设计稿原像素显示,
21
+ // 不会坍缩成 width:auto / padding:0。
22
+ //
23
+ // 与「写字面 rem」相比的关键差异:
24
+ // - rem 字面量受 html font-size 影响,html font-size 由 Container 按
25
+ // **用户的** designWidth 计算 —— 用户改 designWidth=375 时库内 rem 视觉翻倍;
26
+ // - r() 走独立 CSS 变量 --clxx-px,与用户 designWidth 完全解耦,永远稳。
27
+ //
28
+ // 性能:calc/var 是 specified→computed 一次求值,结果进 computed style 缓存,
29
+ // 不会每帧重算。同 px 值复用同一字符串实例(cache),减少 GC 压力,emotion
30
+ // className hash 命中率也更高。
31
+ //
32
+ // @param px750 在 750 设计稿下的像素值
33
+ // @returns css 长度字符串,可直接喂给 emotion css 对象 / 模板字符串 / 内联 style
34
+ //
35
+ // @example
36
+ // // before
37
+ // const style = css({ padding: ".2rem .32rem" });
38
+ // // after
39
+ // const style = css({ padding: `${r(20)} ${r(32)}` });
40
+ const cache = new Map();
41
+ function r(px750) {
42
+ const cached = cache.get(px750);
43
+ if (cached !== undefined)
44
+ return cached;
45
+ const value = `calc(${px750} * var(--clxx-px, 1px))`;
46
+ cache.set(px750, value);
47
+ return value;
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clxx",
3
- "version": "3.0.2",
3
+ "version": "3.0.4",
4
4
  "description": "Basic JS library for mobile devices",
5
5
  "main": "./build/index.js",
6
6
  "module": "./build/index.js",
@@ -8,7 +8,7 @@
8
8
  "example": "example"
9
9
  },
10
10
  "scripts": {
11
- "start": "tsc -w --pretty",
11
+ "dev": "tsc -w --pretty",
12
12
  "build": "rimraf ./build && tsc",
13
13
  "pub": "npm run build && npm publish"
14
14
  },
@@ -19,6 +19,11 @@ const pageConfig = [
19
19
  { path: "city-select", title: "CitySelect城市选择器", enable: true },
20
20
  { path: "date-picker", title: "DatePicker日期时间选择器", enable: true },
21
21
  { path: "region-picker", title: "RegionPicker省市区选择器", enable: true },
22
+ {
23
+ path: "map-location-selection",
24
+ title: "MapLocationSelection地图选址",
25
+ enable: true,
26
+ },
22
27
  ];
23
28
 
24
29
  export default function Index() {
@@ -7,6 +7,7 @@ createApp({
7
7
  target: "#root",
8
8
  // maxDocWidth: 10000,
9
9
  maxWidth: 750,
10
+ // designWidth: 375,
10
11
  async render(pathname) {
11
12
  const module = await import(`./${pathname}/index.jsx`);
12
13
  const Page = module.default;
@@ -0,0 +1,192 @@
1
+ import { showMapLocationSelection, getLocation } from "@";
2
+
3
+ const AMAP_KEY = "9e93b7084bb3da8d2094c02dc4221d47";
4
+ // JSAPI v2.0 调用 PlaceSearch / Geocoder / AutoComplete 等服务类接口必须配置安全密钥
5
+ const AMAP_SECURITY_JS_CODE = "d57bb5e049555d04e0dabcd7557ce5e2";
6
+
7
+ const BMAP_AK = "YS5En8FGCXQnAt65nAXn5LOUP5ANRRQy";
8
+
9
+ const reportSelected = (loc) => {
10
+ console.log("选择了位置:", loc);
11
+ const region = [loc.province, loc.city, loc.district]
12
+ .filter(Boolean)
13
+ .join(" / ");
14
+ const codes = [loc.provinceCode, loc.cityCode, loc.districtCode]
15
+ .filter(Boolean)
16
+ .join(" / ");
17
+ alert(
18
+ `已选择:${loc.name || "(无名称)"}\n` +
19
+ `地址:${loc.address}\n` +
20
+ `经纬度:${loc.longitude.toFixed(6)}, ${loc.latitude.toFixed(6)}\n` +
21
+ `行政区划:${region || "(未返回)"}\n` +
22
+ `行政区划码:${codes || "(未返回)"}`,
23
+ );
24
+ };
25
+
26
+ // 调用函数式 getLocation,返回值与组件 onSelect 完全同结构(共享
27
+ // buildSelectedLocation 拼装),用 reportSelected 弹同样的展示框。
28
+ const reportError = (err) => {
29
+ console.error("getLocation 失败:", err);
30
+ alert(`定位失败:${err?.message || err}`);
31
+ };
32
+
33
+ export default function Index() {
34
+ return (
35
+ <div
36
+ style={{
37
+ display: "flex",
38
+ flexDirection: "column",
39
+ gap: "0.2rem",
40
+ padding: "0.3rem",
41
+ }}
42
+ >
43
+ <button
44
+ onClick={() => {
45
+ showMapLocationSelection({
46
+ amapKey: AMAP_KEY,
47
+ securityJsCode: AMAP_SECURITY_JS_CODE,
48
+ onSelect: reportSelected,
49
+ onClose: () => {
50
+ console.log("关闭了地图选址(高德)");
51
+ },
52
+ });
53
+ }}
54
+ >
55
+ 打开地图选址(高德)
56
+ </button>
57
+
58
+ <button
59
+ onClick={() => {
60
+ showMapLocationSelection({
61
+ amapKey: AMAP_KEY,
62
+ securityJsCode: AMAP_SECURITY_JS_CODE,
63
+ initialCity: "上海",
64
+ // GCJ02 上海人民广场
65
+ initialCenter: [121.473667, 31.230525],
66
+ primary: "#07c160",
67
+ onSelect: reportSelected,
68
+ });
69
+ }}
70
+ >
71
+ 打开地图选址(高德 - 上海,绿色主题)
72
+ </button>
73
+
74
+ <button
75
+ onClick={() => {
76
+ showMapLocationSelection({
77
+ provider: "bmap",
78
+ bmapAk: BMAP_AK,
79
+ onSelect: reportSelected,
80
+ onClose: () => {
81
+ console.log("关闭了地图选址(百度)");
82
+ },
83
+ });
84
+ }}
85
+ >
86
+ 打开地图选址(百度)
87
+ </button>
88
+
89
+ <button
90
+ onClick={() => {
91
+ showMapLocationSelection({
92
+ provider: "bmap",
93
+ bmapAk: BMAP_AK,
94
+ // BD09 上海人民广场
95
+ initialCenter: [121.479675, 31.236397],
96
+ primary: "#07c160",
97
+ onSelect: reportSelected,
98
+ });
99
+ }}
100
+ >
101
+ 打开地图选址(百度 - 上海,绿色主题)
102
+ </button>
103
+
104
+ {/* 函数式 getLocation:不弹窗、直接拿一份 SelectedLocation。
105
+ 数据格式与上方 reportSelected 完全一致,复用同一个展示弹框。 */}
106
+ <button
107
+ onClick={() => {
108
+ getLocation({
109
+ amapKey: AMAP_KEY,
110
+ securityJsCode: AMAP_SECURITY_JS_CODE,
111
+ })
112
+ .then(reportSelected)
113
+ .catch(reportError);
114
+ }}
115
+ >
116
+ getLocation(高德 - 默认,禁用 IP 兜底)
117
+ </button>
118
+
119
+ <button
120
+ onClick={() => {
121
+ getLocation({
122
+ amapKey: AMAP_KEY,
123
+ securityJsCode: AMAP_SECURITY_JS_CODE,
124
+ allowIpFallback: true,
125
+ })
126
+ .then(reportSelected)
127
+ .catch(reportError);
128
+ }}
129
+ >
130
+ getLocation(高德 - 允许 IP 兜底)
131
+ </button>
132
+
133
+ <button
134
+ onClick={() => {
135
+ getLocation({
136
+ provider: "bmap",
137
+ bmapAk: BMAP_AK,
138
+ })
139
+ .then(reportSelected)
140
+ .catch(reportError);
141
+ }}
142
+ >
143
+ getLocation(百度 - 默认,禁用 IP 兜底)
144
+ </button>
145
+
146
+ <button
147
+ onClick={() => {
148
+ getLocation({
149
+ provider: "bmap",
150
+ bmapAk: BMAP_AK,
151
+ allowIpFallback: true,
152
+ })
153
+ .then(reportSelected)
154
+ .catch(reportError);
155
+ }}
156
+ >
157
+ getLocation(百度 - 允许 IP 兜底)
158
+ </button>
159
+
160
+ {/* 组件入口的 IP 兜底测试:在 H5 GPS 失败 / 拒绝授权 / 室内信号差时,
161
+ 高德 / 百度 SDK 内部默认会自动 IP 定位(城市级精度,accuracy 通常
162
+ ≥ 5000m)。组件默认丢弃 IP 结果(allowIpFallback=false)→ 回到
163
+ fallback 中心;传 allowIpFallback=true 后接受 IP 结果 → 列表展示
164
+ city 级附近。 */}
165
+ <button
166
+ onClick={() => {
167
+ showMapLocationSelection({
168
+ amapKey: AMAP_KEY,
169
+ securityJsCode: AMAP_SECURITY_JS_CODE,
170
+ allowIpFallback: true,
171
+ onSelect: reportSelected,
172
+ });
173
+ }}
174
+ >
175
+ 打开地图选址(高德 - 允许 IP 兜底)
176
+ </button>
177
+
178
+ <button
179
+ onClick={() => {
180
+ showMapLocationSelection({
181
+ provider: "bmap",
182
+ bmapAk: BMAP_AK,
183
+ allowIpFallback: true,
184
+ onSelect: reportSelected,
185
+ });
186
+ }}
187
+ >
188
+ 打开地图选址(百度 - 允许 IP 兜底)
189
+ </button>
190
+ </div>
191
+ );
192
+ }