@lmy54321/design-system 1.2.0 → 1.3.1

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.
@@ -93,20 +93,23 @@ cp node_modules/@lmy54321/design-system/template/index.html index.html
93
93
  cp node_modules/@lmy54321/design-system/template/vite.config.ts vite.config.ts
94
94
  cp node_modules/@lmy54321/design-system/template/tsconfig.json tsconfig.json
95
95
 
96
- # 复制 public 资源(manifest 等)
97
- cp -r node_modules/@lmy54321/design-system/template/public/* public/ 2>/dev/null || true
96
+ # 复制 public 资源(manifest 等,图片通过 CDN 加载无需复制)
97
+ cp node_modules/@lmy54321/design-system/template/public/manifest.json public/manifest.json 2>/dev/null || true
98
98
 
99
99
  # 删除 Vite 默认生成的无用文件
100
100
  rm -f src/App.css src/assets/react.svg public/vite.svg
101
101
  ```
102
102
 
103
103
  > **说明:** 模板包含以下路由页面,启动后可通过浏览器访问:
104
- > - `/` — Demo 首页(手机预览效果,含地图首页、探索、行程、我的四个 Tab)
105
- > - `/dev` — 开发者入口(四个功能卡片导航)
104
+ > - `/` — 开发者入口(默认首页,四个功能卡片导航)
105
+ > - `/dev` — 开发者入口(同上)
106
+ > - `/demo` — Demo 手机预览(地图首页、探索、行程、我的四个 Tab)
106
107
  > - `/components` — 组件库交互式展示
107
108
  > - `/sync` — 规范同步工具
108
109
  > - `/deploy` — 部署预览
109
110
  >
111
+ > **注意:** 模板中的图片资源通过 CDN 加载(jsDelivr + GitHub),无需在本地存放图片文件。
112
+ >
110
113
  > **注意:** 模板中的 `src/index.css` 已配置好样式导入,不需要手动修改。不要在其中单独写 `@import "tailwindcss"`,设计系统样式内部已包含 Tailwind 初始化。
111
114
 
112
115
  ### 7. 启动开发服务器
@@ -120,8 +123,8 @@ npm run dev
120
123
  「项目已初始化完成!已加载完整的 Demo 项目,包含多个示例页面。
121
124
 
122
125
  **访问地址:**
123
- - 首页(手机预览):http://localhost:5173/
124
- - 开发者入口:http://localhost:5173/dev
126
+ - 开发者入口(默认首页):http://localhost:5173/
127
+ - Demo 手机预览:http://localhost:5173/demo
125
128
  - 组件库:http://localhost:5173/components
126
129
 
127
130
  你可以在这些 Demo 的基础上修改,或者描述你想要的新页面。」
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmy54321/design-system",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "A comprehensive React component library and design system based on Tailwind CSS and Motion.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -19,6 +19,7 @@
19
19
  "dist",
20
20
  "styles",
21
21
  "template",
22
+ "!template/public/images",
22
23
  ".codebuddy/rules/design-system.mdc",
23
24
  ".codebuddy/rules/init-project.mdc"
24
25
  ],
@@ -0,0 +1,12 @@
1
+ /**
2
+ * CDN 资源配置
3
+ * 图片托管在 GitHub,通过 jsDelivr CDN 全球加速访问
4
+ */
5
+
6
+ const CDN_BASE =
7
+ "https://cdn.jsdelivr.net/gh/lmy910510/design-system-assets@main";
8
+
9
+ /** 拼接 CDN 图片完整 URL */
10
+ export function cdnImage(path: string): string {
11
+ return `${CDN_BASE}${path}`;
12
+ }
@@ -1,4 +1,4 @@
1
- @import "@lmy54321/design-system/styles";
2
-
3
1
  @source "../src";
4
2
  @source "../node_modules/@lmy54321/design-system/dist";
3
+
4
+ @import "@lmy54321/design-system/styles";
@@ -12,9 +12,9 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
12
12
  <React.StrictMode>
13
13
  <BrowserRouter>
14
14
  <Routes>
15
- {/* Demo 首页 — 手机预览的内容 */}
16
- <Route path="/*" element={<App />} />
17
- {/* 开发者入口 */}
15
+ {/* 开发者入口(默认首页) */}
16
+ <Route path="/" element={<DevPortal />} />
17
+ {/* 开发者入口别名 */}
18
18
  <Route path="/dev" element={<DevPortal />} />
19
19
  {/* 组件库展示 */}
20
20
  <Route path="/components" element={<ComponentLibrary />} />
@@ -22,6 +22,8 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
22
22
  <Route path="/sync" element={<SyncTool />} />
23
23
  {/* 部署预览 */}
24
24
  <Route path="/deploy" element={<DeployPage />} />
25
+ {/* Demo 手机预览内容(通配符放最后作为 fallback) */}
26
+ <Route path="/demo/*" element={<App />} />
25
27
  </Routes>
26
28
  </BrowserRouter>
27
29
  </React.StrictMode>
@@ -7,6 +7,7 @@ import { Toast } from "@lmy54321/design-system";
7
7
  import { ImageWithFallback } from "@lmy54321/design-system";
8
8
  import { IconFont } from "@lmy54321/design-system";
9
9
  import { TencentMap } from "@lmy54321/design-system";
10
+ import { cdnImage } from "../config/cdn";
10
11
 
11
12
  /* ══════════════════════════════════════════
12
13
  数据
@@ -38,7 +39,7 @@ const brandStores: BrandStore[] = [
38
39
  {
39
40
  id: "1",
40
41
  brand: "麦当劳",
41
- logo: "/images/scene/hamburger.png",
42
+ logo: cdnImage("/images/scene/hamburger.png"),
42
43
  branch: "人民广场店",
43
44
  distance: "3.3km",
44
45
  type: "destination",
@@ -48,7 +49,7 @@ const brandStores: BrandStore[] = [
48
49
  {
49
50
  id: "2",
50
51
  brand: "瑞幸咖啡",
51
- logo: "/images/scene/pour-coffee.png",
52
+ logo: cdnImage("/images/scene/pour-coffee.png"),
52
53
  branch: "人民广场店",
53
54
  distance: "3.1km",
54
55
  type: "destination",
@@ -58,7 +59,7 @@ const brandStores: BrandStore[] = [
58
59
  {
59
60
  id: "3",
60
61
  brand: "达美乐披萨",
61
- logo: "/images/scene/pizza.png",
62
+ logo: cdnImage("/images/scene/pizza.png"),
62
63
  branch: "科技广场店",
63
64
  distance: "2.6km",
64
65
  type: "enroute",
@@ -68,7 +69,7 @@ const brandStores: BrandStore[] = [
68
69
  {
69
70
  id: "4",
70
71
  brand: "奈雪の茶",
71
- logo: "/images/scene/matcha.png",
72
+ logo: cdnImage("/images/scene/matcha.png"),
72
73
  branch: "科技广场店",
73
74
  distance: "1.3km",
74
75
  type: "nearby",
@@ -78,7 +79,7 @@ const brandStores: BrandStore[] = [
78
79
  {
79
80
  id: "5",
80
81
  brand: "星巴克",
81
- logo: "/images/scene/cafe.png",
82
+ logo: cdnImage("/images/scene/cafe.png"),
82
83
  branch: "CBD中心店",
83
84
  distance: "2.9km",
84
85
  type: "destination",
@@ -88,7 +89,7 @@ const brandStores: BrandStore[] = [
88
89
  {
89
90
  id: "6",
90
91
  brand: "肯德基",
91
- logo: "/images/scene/hamburger.png",
92
+ logo: cdnImage("/images/scene/hamburger.png"),
92
93
  branch: "太古里店",
93
94
  distance: "1.8km",
94
95
  type: "enroute",
@@ -117,7 +118,7 @@ const dealItems: DealItem[] = [
117
118
  name: "大堡口福套餐",
118
119
  store: "麦当劳三诺大厦店",
119
120
  distance: "2.1km",
120
- image: "/images/scene/hamburger.png",
121
+ image: cdnImage("/images/scene/hamburger.png"),
121
122
  price: 22.9,
122
123
  originalPrice: 39.9,
123
124
  actionLabel: "选 1 号",
@@ -128,7 +129,7 @@ const dealItems: DealItem[] = [
128
129
  name: "大橘美式咖啡",
129
130
  store: "瑞幸万豪店",
130
131
  distance: "1.1km",
131
- image: "/images/scene/pour-coffee.png",
132
+ image: cdnImage("/images/scene/pour-coffee.png"),
132
133
  price: 12.9,
133
134
  originalPrice: 23.9,
134
135
  actionLabel: "选 2 号",
@@ -140,7 +141,7 @@ const dealItems: DealItem[] = [
140
141
  name: "照烧风味牛肉披萨",
141
142
  store: "达美乐江夏店",
142
143
  distance: "1.2km",
143
- image: "/images/scene/pizza.png",
144
+ image: cdnImage("/images/scene/pizza.png"),
144
145
  price: 59,
145
146
  originalPrice: 88.9,
146
147
  actionLabel: "选 3 号",
@@ -152,7 +153,7 @@ const dealItems: DealItem[] = [
152
153
  name: "超浓千层抹茶拿铁",
153
154
  store: "奈雪の茶科技广场店",
154
155
  distance: "1.3km",
155
- image: "/images/scene/matcha.png",
156
+ image: cdnImage("/images/scene/matcha.png"),
156
157
  price: 18.9,
157
158
  originalPrice: 32,
158
159
  actionLabel: "选 4 号",
@@ -1,6 +1,7 @@
1
1
  import { useNavigate } from "react-router-dom";
2
2
  import { Btn, IconFont, cn } from "@lmy54321/design-system";
3
3
  import { motion } from "motion/react";
4
+ import designSystemPkg from "@lmy54321/design-system/package.json";
4
5
 
5
6
  interface PortalCard {
6
7
  id: string;
@@ -18,7 +19,7 @@ const PORTAL_CARDS: PortalCard[] = [
18
19
  title: "Demo 演示",
19
20
  description: "查看当前项目的业务 Demo,这也是手机预览看到的内容",
20
21
  icon: "mobile",
21
- route: "/",
22
+ route: "/demo",
22
23
  colorClass: "bg-[#22C55E]",
23
24
  },
24
25
  {
@@ -152,7 +153,7 @@ export function DevPortal() {
152
153
  npm 包
153
154
  </a>
154
155
  <span className="text-[13px] text-muted-foreground">
155
- 当前版本: v1.2.0
156
+ 当前版本: v{designSystemPkg.version}
156
157
  </span>
157
158
  </div>
158
159
  </motion.div>
@@ -12,6 +12,7 @@ import { Btn } from "@lmy54321/design-system";
12
12
  import { Toast } from "@lmy54321/design-system";
13
13
  import { RouteDetailPage } from "./RouteDetailPage";
14
14
  import type { RouteItem } from "./RouteDetailPage";
15
+ import { cdnImage } from "../config/cdn";
15
16
 
16
17
  /* ── 筛选标签 ── */
17
18
  const categories = [
@@ -40,7 +41,7 @@ export const routeRecommendations: RouteItem[] = [
40
41
  id: "r1",
41
42
  title: "一天走完中轴线!累但值得",
42
43
  desc: "从永定门一路暴走到钟鼓楼,把北京城600年的底蕴踩在脚下,步数3w+但每一步都是历史",
43
- image: "/images/feed-axis.png",
44
+ image: cdnImage("/images/feed-axis.png"),
44
45
  duration: "1天",
45
46
  distance: "7.8km",
46
47
  stops: [
@@ -61,7 +62,7 @@ export const routeRecommendations: RouteItem[] = [
61
62
  id: "r2",
62
63
  title: "什刹海半日闲逛|拍照巨出片",
63
64
  desc: "恭王府逛完溜达到后海,路上随便一拍就是大片,咖啡也绝绝子",
64
- image: "/images/feed/route-shichahai.png",
65
+ image: cdnImage("/images/feed/route-shichahai.png"),
65
66
  duration: "半天",
66
67
  distance: "3.2km",
67
68
  stops: [
@@ -80,7 +81,7 @@ export const routeRecommendations: RouteItem[] = [
80
81
  id: "r3",
81
82
  title: "朝阳觅食一整天!从brunch吃到宵夜",
82
83
  desc: "早上国贸吃brunch,中午三里屯逛吃,晚上望京撸串,这条线我走了不下5遍",
83
- image: "/images/feed/route-food-cbd.png",
84
+ image: cdnImage("/images/feed/route-food-cbd.png"),
84
85
  duration: "1天",
85
86
  distance: "4.5km",
86
87
  stops: [
@@ -100,7 +101,7 @@ export const routeRecommendations: RouteItem[] = [
100
101
  id: "r4",
101
102
  title: "京郊自驾赏秋|美哭了真的",
102
103
  desc: "坡峰岭的红叶太震撼了!拍了300张照片,随手一张都是壁纸级别",
103
- image: "/images/feed/route-autumn.png",
104
+ image: cdnImage("/images/feed/route-autumn.png"),
104
105
  duration: "1天",
105
106
  distance: "120km",
106
107
  stops: [
@@ -143,7 +144,7 @@ const feeds: FeedItem[] = [
143
144
  {
144
145
  id: "1",
145
146
  type: "article",
146
- image: "/images/feed-hutong.png",
147
+ image: cdnImage("/images/feed-hutong.png"),
147
148
  title: "救命!北京胡同也太好逛了吧",
148
149
  content: "从南锣鼓巷一路逛到五道营,每条胡同都有惊喜!墙上的涂鸦、藏在深处的咖啡馆、老北京四合院的门墩...",
149
150
  author: "迷路的南方人",
@@ -160,7 +161,7 @@ const feeds: FeedItem[] = [
160
161
  {
161
162
  id: "2",
162
163
  type: "route",
163
- image: "/images/feed-axis.png",
164
+ image: cdnImage("/images/feed-axis.png"),
164
165
  title: "一天走完中轴线!累但值得",
165
166
  content: "从永定门一路暴走到钟鼓楼,步数3w+但每一步都值了!",
166
167
  author: "在逃的建筑系学生",
@@ -178,7 +179,7 @@ const feeds: FeedItem[] = [
178
179
  {
179
180
  id: "3",
180
181
  type: "article",
181
- image: "/images/feed-coffee-sanlitun.png",
182
+ image: cdnImage("/images/feed-coffee-sanlitun.png"),
182
183
  title: "三里屯这家咖啡也太绝了|环境氛围感拉满",
183
184
  content: "被种草很久终于来了!loft风的装修超有feel,拿铁拉花巨好看,坐窗边随手一拍就是大片",
184
185
  author: "每日一杯美式续命",
@@ -194,7 +195,7 @@ const feeds: FeedItem[] = [
194
195
  {
195
196
  id: "4",
196
197
  type: "route",
197
- image: "/images/feed/route-food-cbd.png",
198
+ image: cdnImage("/images/feed/route-food-cbd.png"),
198
199
  title: "朝阳觅食一整天!从brunch吃到宵夜",
199
200
  content: "早上国贸brunch,中午三里屯逛吃,晚上望京撸串,这条线走了不下5遍",
200
201
  author: "朝阳干饭王小陈",
@@ -212,7 +213,7 @@ const feeds: FeedItem[] = [
212
213
  {
213
214
  id: "5",
214
215
  type: "article",
215
- image: "/images/feed/feed-autumn.png",
216
+ image: cdnImage("/images/feed/feed-autumn.png"),
216
217
  title: "京郊红叶拍照攻略|朋友圈直接炸了",
217
218
  content: "坡峰岭的红叶真的太震撼了!分享几个绝佳机位,随手拍都是壁纸级别",
218
219
  author: "周末出逃计划",
@@ -229,7 +230,7 @@ const feeds: FeedItem[] = [
229
230
  {
230
231
  id: "6",
231
232
  type: "article",
232
- image: "/images/feed/feed-museum.png",
233
+ image: cdnImage("/images/feed/feed-museum.png"),
233
234
  title: "故宫这个展太绝了!冲冲冲",
234
235
  content: "千秋佳人特展,展品超精美!建议留出半天时间慢慢看,记得提前预约",
235
236
  author: "博物馆女孩日记",
@@ -246,7 +247,7 @@ const feeds: FeedItem[] = [
246
247
  {
247
248
  id: "7",
248
249
  type: "route",
249
- image: "/images/feed/route-shichahai.png",
250
+ image: cdnImage("/images/feed/route-shichahai.png"),
250
251
  title: "什刹海半日闲逛|拍照巨出片",
251
252
  content: "恭王府逛完溜达到后海,路上随便一拍就是大片",
252
253
  author: "胡同串子阿瑶",
@@ -263,7 +264,7 @@ const feeds: FeedItem[] = [
263
264
  {
264
265
  id: "8",
265
266
  type: "article",
266
- image: "/images/feed/feed-food.png",
267
+ image: cdnImage("/images/feed/feed-food.png"),
267
268
  title: "簋街深夜暴走!吃到扶墙出系列",
268
269
  content: "从东直门一路吃到北新桥,小龙虾、烤鱼、卤煮、炒肝…热量炸弹一晚上全补回来了",
269
270
  author: "深夜放毒小分队",
@@ -280,7 +281,7 @@ const feeds: FeedItem[] = [
280
281
  {
281
282
  id: "9",
282
283
  type: "article",
283
- image: "/images/feed/feed-temple.png",
284
+ image: cdnImage("/images/feed/feed-temple.png"),
284
285
  title: "雍和宫求啥最灵?本地人来说说",
285
286
  content: "作为北京土著分享一下经验:求事业去法轮殿,求学业去万福阁,求姻缘去…",
286
287
  author: "佛系北京妞",
@@ -296,7 +297,7 @@ const feeds: FeedItem[] = [
296
297
  {
297
298
  id: "10",
298
299
  type: "route",
299
- image: "/images/feed/route-autumn.png",
300
+ image: cdnImage("/images/feed/route-autumn.png"),
300
301
  title: "京郊自驾赏秋|美哭了真的",
301
302
  content: "坡峰岭红叶太震撼!拍了300张照片随手一张都是壁纸",
302
303
  author: "周末出逃计划",
@@ -313,7 +314,7 @@ const feeds: FeedItem[] = [
313
314
  {
314
315
  id: "11",
315
316
  type: "article",
316
- image: "/images/feed/feed-park.png",
317
+ image: cdnImage("/images/feed/feed-park.png"),
317
318
  title: "朝阳公园遛娃天花板!孩子玩疯了",
318
319
  content: "带娃来了N次了,沙坑、滑梯、草坪野餐…一待就是一整天,大人也能放松",
319
320
  author: "俩娃妈的日常",
@@ -329,7 +330,7 @@ const feeds: FeedItem[] = [
329
330
  {
330
331
  id: "12",
331
332
  type: "article",
332
- image: "/images/feed/feed-art.png",
333
+ image: cdnImage("/images/feed/feed-art.png"),
333
334
  title: "798这几个展我愿称之为年度最佳",
334
335
  content: "UCCA尤伦斯的新展、木木美术馆的沉浸式体验、还有长征空间…周末花一天刷完",
335
336
  author: "艺术民工小王",
@@ -12,6 +12,7 @@ import { IconFont } from "@lmy54321/design-system";
12
12
  import { ImageWithFallback } from "@lmy54321/design-system";
13
13
  import { TencentMap } from "@lmy54321/design-system";
14
14
  import { SearchFlowDemo } from "./SearchFlowDemo";
15
+ import { cdnImage } from "../config/cdn";
15
16
 
16
17
  /* ── 功能入口(5个均分) ── */
17
18
  const serviceEntries = [
@@ -30,7 +31,7 @@ const nearbyPOIs = [
30
31
  category: "咖啡厅",
31
32
  distance: "320m",
32
33
  rating: "4.8",
33
- photo: "/images/scene/cafe.png",
34
+ photo: cdnImage("/images/scene/cafe.png"),
34
35
  tag: "人气推荐",
35
36
  lat: 39.9088,
36
37
  lng: 116.4605,
@@ -41,7 +42,7 @@ const nearbyPOIs = [
41
42
  category: "火锅",
42
43
  distance: "580m",
43
44
  rating: "4.7",
44
- photo: "/images/scene/hotpot.png",
45
+ photo: cdnImage("/images/scene/hotpot.png"),
45
46
  tag: "排队中",
46
47
  lat: 39.9320,
47
48
  lng: 116.4540,
@@ -52,7 +53,7 @@ const nearbyPOIs = [
52
53
  category: "北京菜",
53
54
  distance: "1.2km",
54
55
  rating: "4.5",
55
- photo: "/images/scene/peking-duck.png",
56
+ photo: cdnImage("/images/scene/peking-duck.png"),
56
57
  tag: "老字号",
57
58
  lat: 39.8992,
58
59
  lng: 116.3974,
@@ -63,7 +64,7 @@ const nearbyPOIs = [
63
64
  category: "购物中心",
64
65
  distance: "1.5km",
65
66
  rating: "4.6",
66
- photo: "/images/scene/mall.png",
67
+ photo: cdnImage("/images/scene/mall.png"),
67
68
  tag: "",
68
69
  lat: 39.9210,
69
70
  lng: 116.4810,
@@ -74,7 +75,7 @@ const nearbyPOIs = [
74
75
  category: "景点",
75
76
  distance: "2.3km",
76
77
  rating: "4.9",
77
- photo: "/images/feed-axis.png",
78
+ photo: cdnImage("/images/feed-axis.png"),
78
79
  tag: "必去",
79
80
  lat: 39.9163,
80
81
  lng: 116.3972,
@@ -6,6 +6,7 @@ import { Tag } from "@lmy54321/design-system";
6
6
  import { Toast } from "@lmy54321/design-system";
7
7
  import { ImageWithFallback } from "@lmy54321/design-system";
8
8
  import { IconFont } from "@lmy54321/design-system";
9
+ import { cdnImage } from "../config/cdn";
9
10
 
10
11
  /* ══════════════════════════════════════════
11
12
  数据
@@ -30,12 +31,12 @@ const hotSearches = [
30
31
  ];
31
32
 
32
33
  const quickCategories = [
33
- { icon: "fork", label: "美食", image: "/images/scene/peking-duck.png" },
34
- { icon: "tea", label: "咖啡", image: "/images/scene/cafe.png" },
35
- { icon: "building", label: "酒店", image: "/images/scene/hotel.png" },
36
- { icon: "vehicle", label: "加油站", image: "/images/scene/gas-station.png" },
37
- { icon: "map-marked", label: "停车场", image: "/images/scene/parking.png" },
38
- { icon: "film", label: "电影", image: "/images/scene/cinema.png" },
34
+ { icon: "fork", label: "美食", image: cdnImage("/images/scene/peking-duck.png") },
35
+ { icon: "tea", label: "咖啡", image: cdnImage("/images/scene/cafe.png") },
36
+ { icon: "building", label: "酒店", image: cdnImage("/images/scene/hotel.png") },
37
+ { icon: "vehicle", label: "加油站", image: cdnImage("/images/scene/gas-station.png") },
38
+ { icon: "map-marked", label: "停车场", image: cdnImage("/images/scene/parking.png") },
39
+ { icon: "film", label: "电影", image: cdnImage("/images/scene/cinema.png") },
39
40
  ];
40
41
 
41
42
  /* 分类卡片的倾斜角度和偏移 */
@@ -9,31 +9,32 @@ import { BottomNavigationBar } from "@lmy54321/design-system";
9
9
  import type { TabId } from "@lmy54321/design-system";
10
10
  import { ImageWithFallback } from "@lmy54321/design-system";
11
11
  import { DraggablePanel, DRAWER_STATES } from "@lmy54321/design-system";
12
+ import { cdnImage } from "../config/cdn";
12
13
 
13
14
  /* ── 四个入口模块数据 ── */
14
15
  const entryModules = [
15
16
  {
16
17
  value: "12",
17
18
  desc: "足迹城市",
18
- image: "/images/city-footprint.png",
19
+ image: cdnImage("/images/city-footprint.png"),
19
20
  rotate: "-8deg",
20
21
  },
21
22
  {
22
23
  value: "3,280",
23
24
  desc: "行程公里",
24
- image: "/images/km-journey.png",
25
+ image: cdnImage("/images/km-journey.png"),
25
26
  rotate: "6deg",
26
27
  },
27
28
  {
28
29
  value: "48",
29
30
  desc: "收藏地点",
30
- image: "/images/fav-places.png",
31
+ image: cdnImage("/images/fav-places.png"),
31
32
  rotate: "-5deg",
32
33
  },
33
34
  {
34
35
  value: "26",
35
36
  desc: "评价数",
36
- image: "/images/reviews-count.png",
37
+ image: cdnImage("/images/reviews-count.png"),
37
38
  rotate: "7deg",
38
39
  },
39
40
  ];
@@ -7,6 +7,7 @@ import { Toast } from "@lmy54321/design-system";
7
7
  import { ImageWithFallback } from "@lmy54321/design-system";
8
8
  import { IconFont } from "@lmy54321/design-system";
9
9
  import { TencentMap } from "@lmy54321/design-system";
10
+ import { cdnImage } from "../config/cdn";
10
11
 
11
12
  /* ══════════════════════════════════════════
12
13
  推荐卡片数据
@@ -27,7 +28,7 @@ const poiCards: POICard[] = [
27
28
  {
28
29
  id: "1",
29
30
  images: [
30
- "/images/scene/relax.png",
31
+ cdnImage("/images/scene/relax.png"),
31
32
  ],
32
33
  title: "\u5076\u5c14\u653e\u7a7a\uff0c\u5728\u5306\u5fd9\u7684\u57ce\u5e02\u4eab\u53d7\u9633\u5149",
33
34
  tags: [
@@ -42,8 +43,8 @@ const poiCards: POICard[] = [
42
43
  {
43
44
  id: "2",
44
45
  images: [
45
- "/images/scene/poi-relax.png",
46
- "/images/scene/cafe.png",
46
+ cdnImage("/images/scene/poi-relax.png"),
47
+ cdnImage("/images/scene/cafe.png"),
47
48
  ],
48
49
  title: "\u5076\u5c14\u653e\u7a7a\uff0c\u5728\u5306\u5fd9\u7684\u57ce\u5e02\u4eab\u53d7\u9633\u5149",
49
50
  tags: [
@@ -57,7 +58,7 @@ const poiCards: POICard[] = [
57
58
  {
58
59
  id: "3",
59
60
  images: [
60
- "/images/scene/friends-outing.png",
61
+ cdnImage("/images/scene/friends-outing.png"),
61
62
  ],
62
63
  title: "\u5076\u5c14\u653e\u7a7a\uff0c\u5728\u5306\u5fd9\u7684\u57ce\u5e02\u4eab\u53d7\u9633\u5149",
63
64
  tags: [
@@ -72,9 +73,9 @@ const poiCards: POICard[] = [
72
73
  {
73
74
  id: "4",
74
75
  images: [
75
- "/images/scene/poi-retro.png",
76
- "/images/scene/restaurant.png",
77
- "/images/scene/cafe.png",
76
+ cdnImage("/images/scene/poi-retro.png"),
77
+ cdnImage("/images/scene/restaurant.png"),
78
+ cdnImage("/images/scene/cafe.png"),
78
79
  ],
79
80
  title: "\u590d\u53e4\u56de\u6f6e\uff1a\u63a2\u5e97\u5357\u5934\u53e4\u57ce5\u5bb6\u6000\u65e7\u98ce\u5c0f\u5e97",
80
81
  tags: [
@@ -89,7 +90,7 @@ const poiCards: POICard[] = [
89
90
  {
90
91
  id: "5",
91
92
  images: [
92
- "/images/feed/feed-park.png",
93
+ cdnImage("/images/feed/feed-park.png"),
93
94
  ],
94
95
  title: "\u5076\u5c14\u653e\u7a7a\uff0c\u5728\u5306\u5fd9\u7684\u57ce\u5e02\u4eab\u53d7\u9633\u5149",
95
96
  tags: [
@@ -14,6 +14,7 @@ import { PlanDetailPage } from "./PlanDetailPage";
14
14
  import { TemplateDetailPage } from "./TemplateDetailPage";
15
15
  import type { TemplateData } from "./TemplateDetailPage";
16
16
  import type { NewPlanPayload } from "../App";
17
+ import { cdnImage } from "../config/cdn";
17
18
 
18
19
  /* -- 快速创建模板(属于"新建"功能的快捷入口) -- */
19
20
  const templates: TemplateData[] = [
@@ -122,7 +123,7 @@ const initialTrips: Trip[] = [
122
123
  days: 2,
123
124
  status: "即将出发",
124
125
  statusColor: "bg-accent/10 text-accent",
125
- image: "/images/scene/trip-culture.png",
126
+ image: cdnImage("/images/scene/trip-culture.png"),
126
127
  },
127
128
  {
128
129
  id: "2",
@@ -133,7 +134,7 @@ const initialTrips: Trip[] = [
133
134
  days: 1,
134
135
  status: "进行中",
135
136
  statusColor: "bg-[#10B981]/10 text-[#10B981]",
136
- image: "/images/scene/trip-food.png",
137
+ image: cdnImage("/images/scene/trip-food.png"),
137
138
  },
138
139
  {
139
140
  id: "3",
@@ -144,7 +145,7 @@ const initialTrips: Trip[] = [
144
145
  days: 1,
145
146
  status: "已完成",
146
147
  statusColor: "bg-black/[0.04] text-muted-foreground",
147
- image: "/images/scene/trip-palace.png",
148
+ image: cdnImage("/images/scene/trip-palace.png"),
148
149
  },
149
150
  ];
150
151
 
@@ -237,7 +238,7 @@ export function PlanPage({ activeTab, onTabChange, newPlan, onNewPlanConsumed }:
237
238
  days: 1,
238
239
  status: "规划中",
239
240
  statusColor: "bg-accent/10 text-accent",
240
- image: "/images/scene/trip-culture.png",
241
+ image: cdnImage("/images/scene/trip-culture.png"),
241
242
  isNew: true,
242
243
  };
243
244
  setTrips(prev => [newTrip, ...prev]);
@@ -8,6 +8,7 @@ import { Toast } from "@lmy54321/design-system";
8
8
  import { IconFont } from "@lmy54321/design-system";
9
9
  import { BottomSheet } from "@lmy54321/design-system";
10
10
  import { ImageWithFallback } from "@lmy54321/design-system";
11
+ import { cdnImage } from "../config/cdn";
11
12
 
12
13
  /* ══════════════════════════════════════════
13
14
  类型定义
@@ -99,11 +100,11 @@ const searchResultPOIs: POIDetail[] = [
99
100
  distance: "5.8km", rating: "4.7", ratingCount: "3.2万", pricePerPerson: "168",
100
101
  phone: "010-65260008", hours: "11:00-22:00", lat: 39.9120, lng: 116.4050,
101
102
  tags: ["烤鸭", "老字号", "排队名店"],
102
- image: "/images/scene/peking-duck.png",
103
+ image: cdnImage("/images/scene/peking-duck.png"),
103
104
  photos: [
104
- "/images/scene/peking-duck.png",
105
- "/images/scene/hotpot.png",
106
- "/images/scene/pizza.png",
105
+ cdnImage("/images/scene/peking-duck.png"),
106
+ cdnImage("/images/scene/hotpot.png"),
107
+ cdnImage("/images/scene/pizza.png"),
107
108
  ],
108
109
  },
109
110
  {
@@ -111,10 +112,10 @@ const searchResultPOIs: POIDetail[] = [
111
112
  distance: "2.3km", rating: "4.6", ratingCount: "1.8万", pricePerPerson: "135",
112
113
  phone: "010-64788899", hours: "10:00-次日07:00", lat: 39.9920, lng: 116.4800,
113
114
  tags: ["火锅", "服务好", "24小时"],
114
- image: "/images/scene/hotpot.png",
115
+ image: cdnImage("/images/scene/hotpot.png"),
115
116
  photos: [
116
- "/images/scene/hotpot.png",
117
- "/images/scene/peking-duck.png",
117
+ cdnImage("/images/scene/hotpot.png"),
118
+ cdnImage("/images/scene/peking-duck.png"),
118
119
  ],
119
120
  },
120
121
  {
@@ -122,10 +123,10 @@ const searchResultPOIs: POIDetail[] = [
122
123
  distance: "4.5km", rating: "4.4", ratingCount: "8765", pricePerPerson: "108",
123
124
  phone: "010-64178800", hours: "11:30-凌晨02:00", lat: 39.9340, lng: 116.4540,
124
125
  tags: ["小龙虾", "网红餐厅", "夜宵"],
125
- image: "/images/scene/crayfish.png",
126
+ image: cdnImage("/images/scene/crayfish.png"),
126
127
  photos: [
127
- "/images/scene/crayfish.png",
128
- "/images/scene/hotpot.png",
128
+ cdnImage("/images/scene/crayfish.png"),
129
+ cdnImage("/images/scene/hotpot.png"),
129
130
  ],
130
131
  },
131
132
  // ── 咖啡 ──
@@ -134,11 +135,11 @@ const searchResultPOIs: POIDetail[] = [
134
135
  distance: "5.2km", rating: "4.5", ratingCount: "6543", pricePerPerson: "25",
135
136
  phone: "010-65051234", hours: "07:30-20:00", lat: 39.9085, lng: 116.4600,
136
137
  tags: ["精品咖啡", "性价比", "自带杯减5"],
137
- image: "/images/scene/pour-coffee.png",
138
+ image: cdnImage("/images/scene/pour-coffee.png"),
138
139
  photos: [
139
- "/images/scene/pour-coffee.png",
140
- "/images/scene/cafe.png",
141
- "/images/scene/matcha.png",
140
+ cdnImage("/images/scene/pour-coffee.png"),
141
+ cdnImage("/images/scene/cafe.png"),
142
+ cdnImage("/images/scene/matcha.png"),
142
143
  ],
143
144
  },
144
145
  {
@@ -146,10 +147,10 @@ const searchResultPOIs: POIDetail[] = [
146
147
  distance: "4.6km", rating: "4.3", ratingCount: "1.2万", pricePerPerson: "42",
147
148
  phone: "010-64176688", hours: "07:00-23:00", lat: 39.9350, lng: 116.4530,
148
149
  tags: ["臻选门店", "手冲咖啡", "空间大"],
149
- image: "/images/scene/cafe.png",
150
+ image: cdnImage("/images/scene/cafe.png"),
150
151
  photos: [
151
- "/images/scene/cafe.png",
152
- "/images/scene/pour-coffee.png",
152
+ cdnImage("/images/scene/cafe.png"),
153
+ cdnImage("/images/scene/pour-coffee.png"),
153
154
  ],
154
155
  },
155
156
  // ── 酒店 ──
@@ -158,10 +159,10 @@ const searchResultPOIs: POIDetail[] = [
158
159
  distance: "5.3km", rating: "4.8", ratingCount: "2.1万", pricePerPerson: "1280",
159
160
  phone: "010-65052299", hours: "全天", lat: 39.9080, lng: 116.4610,
160
161
  tags: ["五星级", "商务出行", "CBD核心"],
161
- image: "/images/scene/hotel.png",
162
+ image: cdnImage("/images/scene/hotel.png"),
162
163
  photos: [
163
- "/images/scene/hotel.png",
164
- "/images/scene/hotel-room.png",
164
+ cdnImage("/images/scene/hotel.png"),
165
+ cdnImage("/images/scene/hotel-room.png"),
165
166
  ],
166
167
  },
167
168
  {
@@ -169,10 +170,10 @@ const searchResultPOIs: POIDetail[] = [
169
170
  distance: "2.0km", rating: "4.6", ratingCount: "9876", pricePerPerson: "458",
170
171
  phone: "010-64789900", hours: "全天", lat: 39.9930, lng: 116.4790,
171
172
  tags: ["人文主题", "免费书吧", "性价比"],
172
- image: "/images/scene/hotel-room.png",
173
+ image: cdnImage("/images/scene/hotel-room.png"),
173
174
  photos: [
174
- "/images/scene/hotel-room.png",
175
- "/images/scene/hotel.png",
175
+ cdnImage("/images/scene/hotel-room.png"),
176
+ cdnImage("/images/scene/hotel.png"),
176
177
  ],
177
178
  },
178
179
  // ── 加油站 ──
@@ -181,9 +182,9 @@ const searchResultPOIs: POIDetail[] = [
181
182
  distance: "1.8km", rating: "4.2", ratingCount: "3245", pricePerPerson: "",
182
183
  phone: "010-64739988", hours: "06:00-23:00", lat: 39.9870, lng: 116.4720,
183
184
  tags: ["92号", "95号", "柴油"],
184
- image: "/images/scene/gas-station.png",
185
+ image: cdnImage("/images/scene/gas-station.png"),
185
186
  photos: [
186
- "/images/scene/gas-station.png",
187
+ cdnImage("/images/scene/gas-station.png"),
187
188
  ],
188
189
  },
189
190
  {
@@ -191,9 +192,9 @@ const searchResultPOIs: POIDetail[] = [
191
192
  distance: "3.1km", rating: "4.0", ratingCount: "2180", pricePerPerson: "",
192
193
  phone: "010-64371122", hours: "全天", lat: 39.9750, lng: 116.4900,
193
194
  tags: ["24小时", "洗车服务", "便利店"],
194
- image: "/images/scene/gas-station.png",
195
+ image: cdnImage("/images/scene/gas-station.png"),
195
196
  photos: [
196
- "/images/scene/gas-station.png",
197
+ cdnImage("/images/scene/gas-station.png"),
197
198
  ],
198
199
  },
199
200
  // ── 停车场 ──
@@ -202,9 +203,9 @@ const searchResultPOIs: POIDetail[] = [
202
203
  distance: "2.1km", rating: "4.1", ratingCount: "5432", pricePerPerson: "8",
203
204
  phone: "010-64780088", hours: "全天", lat: 39.9925, lng: 116.4785,
204
205
  tags: ["地下停车", "8元/小时", "车位充足"],
205
- image: "/images/scene/parking.png",
206
+ image: cdnImage("/images/scene/parking.png"),
206
207
  photos: [
207
- "/images/scene/parking.png",
208
+ cdnImage("/images/scene/parking.png"),
208
209
  ],
209
210
  },
210
211
  {
@@ -212,9 +213,9 @@ const searchResultPOIs: POIDetail[] = [
212
213
  distance: "4.5km", rating: "3.9", ratingCount: "8765", pricePerPerson: "10",
213
214
  phone: "010-64170088", hours: "全天", lat: 39.9345, lng: 116.4535,
214
215
  tags: ["消费满减", "10元/小时", "节假日拥挤"],
215
- image: "/images/scene/parking.png",
216
+ image: cdnImage("/images/scene/parking.png"),
216
217
  photos: [
217
- "/images/scene/parking.png",
218
+ cdnImage("/images/scene/parking.png"),
218
219
  ],
219
220
  },
220
221
  // ── 电影 ──
@@ -223,9 +224,9 @@ const searchResultPOIs: POIDetail[] = [
223
224
  distance: "2.5km", rating: "4.5", ratingCount: "2.3万", pricePerPerson: "55",
224
225
  phone: "010-64738866", hours: "09:00-次日01:00", lat: 39.9880, lng: 116.4680,
225
226
  tags: ["IMAX", "杜比全景声", "VIP厅"],
226
- image: "/images/scene/cinema.png",
227
+ image: cdnImage("/images/scene/cinema.png"),
227
228
  photos: [
228
- "/images/scene/cinema.png",
229
+ cdnImage("/images/scene/cinema.png"),
229
230
  ],
230
231
  },
231
232
  {
@@ -233,9 +234,9 @@ const searchResultPOIs: POIDetail[] = [
233
234
  distance: "4.7km", rating: "4.6", ratingCount: "1.5万", pricePerPerson: "68",
234
235
  phone: "010-64176677", hours: "10:00-次日00:00", lat: 39.9348, lng: 116.4528,
235
236
  tags: ["4DX", "ScreenX", "情侣座"],
236
- image: "/images/scene/cinema.png",
237
+ image: cdnImage("/images/scene/cinema.png"),
237
238
  photos: [
238
- "/images/scene/cinema.png",
239
+ cdnImage("/images/scene/cinema.png"),
239
240
  ],
240
241
  },
241
242
  // ── 景点(保留原有) ──
@@ -244,12 +245,12 @@ const searchResultPOIs: POIDetail[] = [
244
245
  distance: "7.0km", rating: "4.9", ratingCount: "28.6万", pricePerPerson: "60",
245
246
  phone: "010-85007421", hours: "08:30-17:00", lat: 39.9163, lng: 116.3972,
246
247
  tags: ["5A景区", "世界文化遗产", "必去打卡"],
247
- image: "/images/feed-axis.png",
248
+ image: cdnImage("/images/feed-axis.png"),
248
249
  photos: [
249
- "/images/feed-axis.png",
250
- "/images/feed/feed-museum.png",
251
- "/images/scene/trip-palace.png",
252
- "/images/scene/jingshan.png",
250
+ cdnImage("/images/feed-axis.png"),
251
+ cdnImage("/images/feed/feed-museum.png"),
252
+ cdnImage("/images/scene/trip-palace.png"),
253
+ cdnImage("/images/scene/jingshan.png"),
253
254
  ],
254
255
  },
255
256
  {
@@ -257,10 +258,10 @@ const searchResultPOIs: POIDetail[] = [
257
258
  distance: "6.8km", rating: "4.8", ratingCount: "15.3万", pricePerPerson: "2",
258
259
  phone: "010-64038098", hours: "06:00-21:00", lat: 39.9245, lng: 116.3967,
259
260
  tags: ["登高望远", "故宫全景", "历史遗迹"],
260
- image: "/images/scene/jingshan.png",
261
+ image: cdnImage("/images/scene/jingshan.png"),
261
262
  photos: [
262
- "/images/scene/jingshan.png",
263
- "/images/scene/trip-palace.png",
263
+ cdnImage("/images/scene/jingshan.png"),
264
+ cdnImage("/images/scene/trip-palace.png"),
264
265
  ],
265
266
  },
266
267
  ];
@@ -7,6 +7,7 @@ import { IconFont } from "@lmy54321/design-system";
7
7
  import { Toast } from "@lmy54321/design-system";
8
8
  import { DraggablePanel, DRAWER_STATES } from "@lmy54321/design-system";
9
9
  import { TencentMap } from "@lmy54321/design-system";
10
+ import { cdnImage } from "../config/cdn";
10
11
 
11
12
  export interface TemplateData {
12
13
  icon: string;
@@ -49,7 +50,7 @@ export function TemplateDetailPage({ template, onBack, onCreatePlan }: Props) {
49
50
  onCreatePlan({
50
51
  title: template.label,
51
52
  spots: template.stops.length,
52
- image: "/images/scene/trip-culture.png",
53
+ image: cdnImage("/images/scene/trip-culture.png"),
53
54
  stops: template.stops,
54
55
  });
55
56
  }, 800);