2026-07-30 16:04:34 +08:00
# 光明文旅地图 POC
2026-07-31 12:50:14 +08:00
基于 uni-app、Vue 3、TypeScript 和 Pinia 开发的微信小程序 POC,用于验证深圳市光明区文旅资源地图探索、POI 数字化展示、文旅偏好收集、行程规划和真实定位到点打卡。
2026-07-30 16:04:34 +08:00
2026-07-31 12:50:14 +08:00
当前范围包括地图拖动缩放、POI 分类、marker 与摘要联动、用户主动授权后的前台实时定位、POI 详情、文旅偏好收集、推荐行程展示和到点打卡。路线规划支持基于当前位置的快速规划,以及用户自选 2–8 个 POI、2–10 小时时长的自定义规划;当前交付统一使用本地规划器按时间预算动态排程。打卡使用用户每次主动触发的位置请求结果核验到点范围,并在本机记录积分、徽章和足迹;当前不是道路级实时导航,也不包含登录或云端个人中心。
2026-07-30 16:04:34 +08:00
## 微信开发者工具
本仓库是 uni-app 源码工程,微信开发者工具不能直接编译 `src/**/*.vue` 。正确流程是由 Vite/uni-app 持续编译,再由微信开发者工具加载编译产物:
```sh
corepack pnpm install --frozen-lockfile
corepack pnpm dev:mp-weixin
```
保持最后一条命令运行,然后在微信开发者工具中选择“导入项目”,目录选择本仓库根目录。根目录的 `project.config.json` 已设置:
```text
miniprogramRoot = dist/dev/mp-weixin/
```
因此 IDE 会识别 `dist/dev/mp-weixin/app.json` 及页面产物。第一次导入前必须等终端显示编译完成;真正生成 `app.json` 、WXML 和 WXSS 的是持续运行的 `dev:mp-weixin` 。`prepare:mp-weixin` 仅供需要预先创建空目录的工具使用,不能替代编译。
微信构建脚本已内置 macOS 文件监听兼容处理;如系统会话的监听句柄上限较低,不需要额外手动设置即可避免 `EMFILE` 编译失败。
macOS 已安装微信开发者工具时,也可在另一个终端执行 `corepack pnpm ide:mp-weixin` 打开根目录项目。
正式构建使用:
```sh
corepack pnpm build:mp-weixin
```
2026-07-31 12:50:14 +08:00
开发编译后可运行 `corepack pnpm verify:mp-weixin` ,检查微信工程配置、启动页、七个业务页面、三个 tabBar 入口、六个图标和页面四件套是否完整。
2026-07-30 16:04:34 +08:00
2026-07-31 12:50:14 +08:00
生产产物位于 `dist/build/mp-weixin` 。微信 AppID 通过未提交的 `.env.local` 中 `UNI_MP_WEIXIN_APPID` 配置;根目录 `project.config.json` 也必须使用同一个项目 AppID。详细说明见 [微信小程序构建与验收说明 ](./docs/微信小程序构建与验收说明.md )。
2026-07-30 16:04:34 +08:00
生产验收时可直接导入 `dist/build/mp-weixin` , macOS 也可运行 `corepack pnpm ide:mp-weixin:build` 。根目录始终用于开发模式,不会因执行生产构建而自动切换到 `dist/build/mp-weixin` 。
## 业务目录
```text
src/
├── pages/map/index.vue # 小程序首页:全域地图
2026-07-31 12:50:14 +08:00
├── pages/assistant/index.vue # 文旅助手:偏好快捷入口
2026-07-30 16:04:34 +08:00
├── pages/planner/index.vue # 行程偏好表单
├── pages/itinerary/index.vue # 推荐路线与地图展示
├── pages/poi/detail.vue # POI 详情
2026-07-31 12:50:14 +08:00
├── pages/check-in/ # 真实定位打卡、积分、徽章与足迹
2026-07-30 16:04:34 +08:00
├── components/map/ # 地图筛选和摘要组件
├── components/poi/ # POI 图片、标签、状态和图集组件
├── components/travel/ # 行程点位展示组件
├── data/poi/ # POC 数据包与仓储
├── domain/poi/ # POI 类型、校验和选择器
├── domain/travel/ # 偏好、行程模型与本地规划规则
├── services/map/ # marker 数字 ID 适配
├── services/travel-assistant/ # 本地会话存储与可选远程服务适配
├── stores/modules/map.ts # 地图会话状态
└── static/ # 随包静态资源
```
2026-07-31 12:50:14 +08:00
## AI 后续接入说明
2026-07-30 16:04:34 +08:00
2026-07-31 12:50:14 +08:00
本期 AI 能力留空,不纳入交付和验收。当前 `createPlan` 业务入口固定走本地规划器,即使误配 `VITE_TRAVEL_ASSISTANT_API_BASE_URL` 也不会发起模型请求;页面展示的“本地 POC 规划”是确定性排程,不代表大模型生成,旧版本遗留的远程路线缓存也不会在本期恢复。
仓库保留了可选的 `server/` 和客户端远程适配层,但本期不与 `createPlan` 业务入口连接。后续接入时需要在代码中显式启用远程分支,部署 HTTPS 服务,设置 `LLM_MODE=real` 、`OPENAI_API_KEY` 、`OPENAI_MODEL` 、`VITE_TRAVEL_ASSISTANT_API_BASE_URL` ,并在微信公众平台加入对应合法 request 域名。模型只负责从审核 POI 白名单中返回推荐 ID、理由和建议顺序;当前位置、坐标、交通估算、时长适配和最终路线继续在本机处理。API Key、模型凭证和高德 Web Service Key 均不得进入客户端环境变量或构建产物。
实时位置仅由用户主动触发,并只在地图页处于前台时持续更新。“当前位置快速规划”要求使用 5 分钟内的位置快照;用户不授权时仍可使用不依赖定位的自选点位规划。每次打卡会重新请求一次 GCJ-02 位置,不复用地图或规划历史位置;只有在 200 米范围内且定位精度满足要求时才记录成功。精确坐标只用于本次内存计算,不写入匿名偏好、路线或打卡缓存,也不会发送给远程 AI 服务。iOS 真机使用前,需通过真实 AppID 在微信公众平台开通定位接口、完善《用户隐私保护指引》,并现场校验 POC 点位坐标和打卡半径。
## 打卡能力说明
`files/打卡` 仅作为功能参考。本项目复用了“积分摘要、打卡状态、徽章墙和本机记录”的交互概念,没有迁移其杭州模拟点位、CommonJS 页面代码、全量清缓存逻辑或橙黄色视觉。实际实现使用现有光明区已发布 POI,并统一采用项目的绿色文旅视觉体系。
打卡为匿名本机 POC: `src/data/check-in/tasks.ts` 会为当前 POI 仓库中的全部已发布点位生成打卡任务;点位下线后会自动停止新打卡,重新发布后仍保留本机历史记录以防重复领奖。所有点位的游客入口坐标与安全到达范围仍需 iOS 现场复核后才能用于正式验收。每个开放点位首次成功打卡增加 10 积分,累计完成 1、2、3 个开放点位时依次解锁徽章。积分、徽章与足迹使用独立版本化存储键;v1 旧格式首次升级时只迁移当前开放点位记录,进入 v2 后则保留合法历史足迹。清除操作只删除打卡数据,不影响路线和偏好。打卡记录不保存经纬度、定位精度或轨迹。微信客户端无法可靠识别系统级缓存位置或虚拟定位,因此本期只承诺每次点击重新调用定位接口并校验微信返回的精度,不提供虚拟定位测试入口或生产级反作弊承诺。
2026-07-30 16:04:34 +08:00
路由来自页面 SFC 的 `<route>` ,由 UniPages 在编译时生成 `src/pages.json` ;应用清单由 `manifest.config.ts` 生成 `src/manifest.json` 。不要直接修改这两个生成文件,也不要让微信开发者工具读取 `src` ; IDE 只读取 `dist/dev/mp-weixin` 。
## POC 数据声明
当前随包 POI 是从 2026-07-30 高德 Web Service 离线候选快照中精选的 30 个 POC 点位,覆盖文化场馆、公园湿地、田园休闲、人文地标和绿道户外。高德只参与开发期数据发现,微信客户端读取本地冻结数据,不携带或实时调用 Web Service Key。
这些点位仍不代表光明区全域权威清单。简介和推荐指数为明确标注的 POC 待审核内容,开放时间统一待确认,封面为开发占位素材,均不满足正式内容或图片验收。
如需重新采集候选,请在本机临时注入 Web Service Key,输出默认写入系统临时目录:
```sh
AMAP_WEB_SERVICE_KEY = ... corepack pnpm fetch:amap-pois
corepack pnpm test:amap-fetch
```
Key 不得写入源码、环境模板、文档、构建产物或日志;采集结果必须经过光明区过滤、去重和人工内容审核后才能固化。采集统计、字段映射与发布门槛见 [高德 POI 离线采集与数据快照说明 ](./docs/高德POI离线采集与数据快照说明.md )。
---
以下保留原模板的技术说明。
## 衍生项目
由于这个模板的业务场景非常的局限,下面提供了一个精心策划的列表。当然也欢迎你 PR 提供自己的项目!
###### 官方
- [unisave-lite ](https://github.com/sunpm/unisave-lite ) - unisave 的 js 版本
## 平台兼容性
在技术考量上,优先同时支持下列的平台,为兼容多个平台而舍弃一些实用的依赖插件。如发现下列平台环境开发编译出现问题,欢迎提 [issue ](https://github.com/sunpm/unisave/issues/new ) or [pr ](https://github.com/sunpm/unisave/pulls )
| H5 | IOS | 安卓 | 微信小程序 | 字节小程序 | 快手小程序 | 支付宝小程序 | 百度小程序 |
|:--:| :--: | :--: | :--------: | :--------: | :--------: | :----------: | :----------: |
| √ | √ | √ | √ | √ | √ | √ | √ |
## 特性
- 🗂 [基于文件的路由 ](./src/pages )
- 📦 [组件自动化加载 ](./src/components )
- 🍍 [使用 Pinia 的状态管理 ](https://github.com/vuejs/pinia )
- 📑 [布局系统 ](./src/layouts )
- 🔥 使用 [新的 `<script setup>` 语法 ](https://github.com/vuejs/rfcs/pull/227 )
- 📥 [API 自动加载 ](https://github.com/unplugin/unplugin-auto-import ) - 直接使用 Composition API 无需引入
- 🎨 [UnoCSS ](https://github.com/unocss/unocss ) - 高性能且极具灵活性的即时原子化 CSS 引擎
- 🦾 TypeScript, 为什么不呢
- ⚙️ 使用 [Vitest ](https://github.com/vitest-dev/vitest ) 进行单元测试
## 预配置
### UI 框架
- [uview-plus ](https://github.com/ijry/uview-plus ) uview-plus3.0是基于uView2.x修改的vue3版本
- [UnoCSS ](https://github.com/unocss/unocss ) 高性能且极具灵活性的即时原子化 CSS 引擎
- [unocss-preset-uni ](https://github.com/uni-helper/unocss-preset-uni ) 专为 uni-app 打造的 UnoCSS 预设
### 插件
- [Pinia ](https://github.com/vuejs/pinia ) - 直接的, 类型安全的, 使用 Composition API 的轻便灵活的 Vue 状态管理
- [`pinia-plugin-persist-uni` ](https://github.com/Allen-1998/pinia-plugin-persist-uni ) - pinia 在 uniapp 中数据持久化插件
- Router
- [`@uni-helper/vite-plugin-uni-pages` ](https://github.com/uni-helper/vite-plugin-uni-pages ) - 在 Vite 驱动的 uni-app 上使用基于文件的路由系统
- [`vite-plugin-vue-layouts` ](https://github.com/uni-helper/vite-plugin-uni-layouts ) - 页面布局系统
- [`@uni-helper/uni-use` ](https://github.com/uni-helper/uni-use ) - 使用 `useRouter` 封装路由方法 -> `src/composables/useNavigation.ts`
- 请求
- [`@uni-helper/uni-network` ](https://github.com/uni-helper/uni-network ) - 为 uni-app 打造的基于 Promise 的 HTTP 客户端
- `services` 目录封装通用请求
- [`unplugin-vue-components` ](https://github.com/antfu/unplugin-vue-components ) - 自动加载组件
- [`unplugin-auto-import` ](https://github.com/antfu/unplugin-auto-import ) - 直接使用 Composition API 等,无需导入
- [`@uni-helper/vite-plugin-uni-manifest` ](https://github.com/uni-helper/vite-plugin-uni-manifest ) - 使用 TypeScript 编写 `uni-app` 的 `manifest.json` 。
### 编码风格
- 使用 Composition API 地 [`<script setup>` SFC 语法 ](https://cn.vuejs.org/api/sfc-script-setup.html )
- [ESLint ](https://github.com/eslint/eslint ) 配置为 [@antfu/eslint-config ](https://github.com/antfu/eslint-config ) - 单引号, 无分号...
- [@unocss/eslint-config ](https://unocss.dev/integrations/eslint ) - 用于UnoCSS的ESLint配置
- [@uni-helper/eslint-config ](https://github.com/uni-helper/eslint-config ) - 适用于 uni-app 的 Anthony's ESLint 配置预设
### 各平台类型定义文件
- [x] [uni-app 组件 ](https://www.npmjs.com/package/@uni-helper/uni-app-types )
- [x] [微信小程序 ](https://www.npmjs.com/package/miniprogram-api-typings )
- [x] [支付宝小程序 ](https://www.npmjs.com/package/@mini-types/alipay )
- [x] [字节小程序 ](https://www.npmjs.com/package/@douyin-microapp/typings )
- [x] [快手小程序 ](https://www.npmjs.com/package/ks-miniprogram-types/global )
- [x] [百度小程序 ](https://www.npmjs.com/package/@types/baidu-app )
## 环境建议
**Node >= 18**
**pnpm >= 8**
## 使用该模版
```sh
npx degit sunpm/unisave#main my-unisave
cd my-unisave
pnpm install
```
如果你没装过 pnpm, 可以先运行: `npm install -g pnpm`
## 清单
使用此模板时,请尝试按照清单正确更新您自己的信息
- [ ] 在 `LICENSE` 中改变作者名或删除
- [ ] 在 `manifest.config.ts` 中修改项目名称,描述,`appid` 等
- [ ] 在 `.env.*` 更改环境变量
- [ ] 不需要部署到 netlify 请移除 `.netlify.toml` 文件
- [ ] 整理 README 并删除演示页面和组件
紧接着, 享受吧 :)
## 问题
怎么修改了 `pages.json` 没效果?
> 模版使用了 [`@uni-helper/vite-plugin-uni-pages`](https://github.com/uni-helper/vite-plugin-uni-pages)插件依赖,需要在`pages.config.ts`配置,编译会生成至`pages.json`,详细[点我看文档](https://github.com/uni-helper/vite-plugin-uni-pages)
怎么修改了 `manifest.json` 没效果?
> 模版使用了[`@uni-helper/vite-plugin-uni-manifest`](https://github.com/uni-helper/vite-plugin-uni-manifest)插件依赖,需要在`manifest.config.ts`配置,编译会生成至`manifest.json`,新增了自动生成项目配置信息的方法,详细[点击查看代码](./manifest.config.ts)
报错:`Uncaught SyntaxError: The requested module '/node_modules/vue-demi/lib/index.mjs?v=701bef9f' does not provide an export named 'hasInjectionContext'`
> pinia v2.1.X 版本要求 vue 3.3 或者 vue-demi latest ,如果 uniapp 的 vue 版本是 ^3.2.45,通过 pinia 降级到 2.0.X 可以运行和使用。
## 感谢
- [vitesse ](https://github.com/antfu/vitesse )
- [uni-helper ](https://github.com/uni-helper )
- [uni-vitesse ](https://github.com/Ares-Chang/uni-vitesse )