jls-weapp
觉林寺微信小程序,基于 Taro 4 + Vue 3 + NutUI 搭建
🚀 快速开始
安装依赖
pnpm install
开发模式
# 微信小程序
pnpm dev:weapp
# H5
pnpm dev:h5
# 支付宝小程序
pnpm dev:alipay
生产构建
pnpm build:weapp
📁 项目结构
src/
├── api/ # API 接口层
│ ├── index.js # 业务接口定义(需根据业务修改)
│ ├── fn.js # HTTP 请求封装
│ └── wx/ # 微信相关接口(可选)
├── assets/ # 静态资源
│ ├── images/ # 图片资源
│ ├── styles/ # 全局样式
│ └── css/ # CSS 文件
├── components/ # 通用组件
│ ├── PosterBuilder/ # 海报生成器(可选)
│ ├── time-picker-data/ # 时间选择器
│ ├── indexNav.vue # 底部导航
│ └── qrCode.vue # 二维码组件(可选)
├── composables/ # Composition API hooks
│ ├── useOfflineBookingCache.js # 离线缓存 hook
│ └── useOfflineBookingCachePolling.js # 轮询刷新 hook
├── hooks/ # 自定义 hooks
│ └── useGo.js # 导航辅助 hook
├── pages/ # 页面组件
│ ├── index/ # 首页(示例页面)
│ └── auth/ # 认证页(必须保留)
├── stores/ # Pinia 状态管理
│ ├── router.js # 路由状态(用于认证回跳)
│ ├── main.js # 主 store
│ ├── host.js # 配置 store
│ └── counter.js # 示例 store
├── utils/ # 工具函数
│ ├── authRedirect.js # 认证流程核心(必须)
│ ├── request.js # HTTP 客户端核心(必须)
│ ├── network.js # 网络状态监测
│ ├── config.js # 环境配置(⚠️ 需修改)
│ ├── tools.js # 通用工具
│ ├── uiText.js # 文案管理
│ ├── wechatPay.js # 微信支付(可选)
│ ├── mixin.js # Vue mixin
│ ├── polyfill.js # 浏览器兼容
│ └── weapp.js # 小程序工具
├── app.js # 应用入口
├── app.config.js # 页面路由配置
└── app.less # 全局样式
⚙️ 配置说明
1. 修改服务器配置
环境读取逻辑集中在 src/utils/config.js,实际运行模式由构建配置决定:
export const API_ENVIRONMENTS = {
production: {
baseURL: 'https://your-production-domain.com',
requestDefaultParams: {
f: 'YOUR_MODULE',
client_id: 'YOUR_CLIENT_ID',
},
},
mock: {
baseURL: 'https://your-production-domain.com',
requestDefaultParams: {
f: 'YOUR_MODULE',
client_id: 'YOUR_CLIENT_ID',
},
useMock: true,
},
}
1.1 正式环境 / 本地 Mock 环境
仓库现在内置两套 API 运行模式:
-
production:正式环境,走真实接口 -
mock:本地 Mock 环境,开发态默认启用
核心文件:
-
config/dev.js:本地开发环境开关,默认API_RUNTIME_ENV = "mock" -
config/prod.js:生产构建环境开关,默认API_RUNTIME_ENV = "production" -
src/utils/config.js:环境定义与当前配置读取 -
src/mock/index.js:统一 Mock 入口 -
src/mock/modules/:按模块拆分的 Mock 处理器 -
src/mock/shared/:请求解析、响应包装、路由匹配等公共能力 -
src/mock/stores/:需要状态的 Mock 数据存储 -
src/mock/fixtures/:纯静态样本和数据工厂 -
src/mock/README.md:新增模块时的目录约定与 handler 示例 -
src/api/message.js:消息列表 / 详情接口示例
当前已经预置了以下 mock:
- 启动授权:
/srv/?a=openid - 支付参数:
/srv/?a=pay(f、client_id由请求层统一补齐)、/srv/?a=icbc_pay_wxamp - 分享配置:
/srv/?a=wx_share - 短信与上传:
/srv/?a=sms、/srv/?a=upload - 消息示例:
/srv/?a=message&t=list、/srv/?a=message&t=detail
如果你想让本地所有接口都走 Mock,只改一个地方就行:
// config/dev.js
env: {
NODE_ENV: '"development"',
API_RUNTIME_ENV: '"mock"',
}
要切回本地真实接口,把它改成:
API_RUNTIME_ENV: '"production"'
这套开关是“全局生效”的:
-
mock:当前构建下所有接口统一走src/mock/ -
production:当前构建下所有接口统一走真实接口
页面层不要自己再写局部 USE_MOCK_DATA 开关,避免同一个页面和别的页面跑在不同环境里。
建议的接入顺序:
- 先在
src/mock/fixtures/里按真实字段准备样本数据。 - 如果该接口存在状态变化,再在
src/mock/stores/里补状态读写。 - 在
src/mock/modules/里新增对应 handler,并在src/mock/modules/index.js注册。 - 页面继续只调用正常的
xxxAPI,先对着 mock 跑通交互。 - 拿到真实接口后,把
config/dev.js切回production,再开始联调真实 API。
1.2 Mock 目录约定
src/mock/ 当前按这几个层次组织:
-
index.js统一入口,只负责创建请求上下文、匹配 handler、返回 axios / Taro 兼容结果。 -
modules/*.mock.js按模块定义接口级 handler,一个 handler 对应一个method + action + type组合。 -
stores/*.store.js放有状态的 mock 数据,比如消息已读、列表新增删除、详情回写等。 -
fixtures/*.fixture.js放纯静态样本和数据工厂,不直接处理状态变化。 -
shared/*.js放请求解析、响应包装、匹配规则等可复用能力。
详细约定见 src/mock/README.md。
1.3 CDN 静态图片缓存更新
如果仓库里的页面直接写死了 https://cdn.ipadbiz.cn/jls_weapp/images/ 下的图片地址,不建议每次换图都改代码重新提审,也不要在每个页面里临时手工拼时间戳。当前项目已经约定用 version.json 统一控制这类本地写死 CDN 图片的缓存版本。
当前固定地址:
https://cdn.ipadbiz.cn/jls_weapp/version.json
当前文件结构:
{
"image_version": "20260515-1"
}
运行方式:
- 应用启动时会预加载这份
version.json - 本地写死的
https://cdn.ipadbiz.cn/jls_weapp/images/xxx.png会自动变成https://cdn.ipadbiz.cn/jls_weapp/images/xxx.png?v=<image_version> - 这样当 CDN 覆盖同名图片后,只要版本值变化,小程序就会把它当成新资源重新拉取
当前边界:
- 这套机制只默认作用于“仓库里本地写死的 CDN 图片地址”
- 接口动态返回的图片 URL 默认不处理,避免把首页/后台内容图也一起卷进缓存策略
开发约定:
- 新增这类本地写死图片时,优先通过
src/utils/assetUrl.js里的getVersionedImageAssetByName('xxx.png')接入 - 不要继续在页面里裸写完整 CDN 地址后再各自补
?v=或时间戳
当你要替换同名图片时,推荐流程是:
- 上传同名图片覆盖 CDN 旧文件
- 手动刷新图片 CDN 缓存
- 修改
version.json里的image_version - 再刷新
version.json自己的 CDN 缓存
2. 定义 API 接口
编辑 src/api/index.js,添加您的业务接口:
import { buildApiUrl } from '@/utils/tools'
export const yourAPI = (params) => {
return buildApiUrl('your_action', params)
}
3. 配置页面路由
编辑 src/app.config.js,添加您的页面:
export default {
pages: [
'pages/index/index',
'pages/auth/index',
'pages/your-page/index', // 添加您的页面
],
// ...
}
4. 双设计宽度体系
项目采用双设计宽度体系:
- NutUI 组件:基准宽度 375px
- 其他所有页面:基准宽度 750px
此配置已在 config/index.js 中设置,请确保遵循此规范。
🧭 动态底部导航与 WebView 承接
当前底部导航不是微信原生 tabBar,而是首页里的自定义 AppTabbar。除 home 外,其余按钮的菜单地址都来自后台 app_menu 配置,但最终仍然统一落到固定承接页 pages/webview-preview/index,再由该页把 url / title 传给 <web-view>。
这里有一个很重要的导航约定:
-
home可以继续用redirectTo - 非
home的动态菜单必须用navigateTo
原因不是业务页是否固定,而是页面栈是否保住。只要首页点击动态菜单时用的是 navigateTo,webview-preview 就会作为新页面入栈,微信原生左上角返回按钮才能正常出现;如果改成 redirectTo,首页会被替换掉,进入 WebView 后就不会有原生返回按钮。
只有一种场景例外:如果小程序是冷启动后直接打开某个 WebView 页面,那么它天然没有上一页,这时即使用的是同一个承接页,也不会凭空出现原生返回按钮。这类场景需要另外设计“返回首页”兜底,不要误判成 tabbar 跳转逻辑失效。
🔐 认证流程
项目内置完整的微信登录认证系统:
- 静默认证:应用启动时自动执行静默认证
- 401 自动刷新:当接口返回 401 时,自动刷新会话并重试请求
- 授权页回跳:认证完成后自动跳转回原页面
核心文件:
-
src/utils/authRedirect.js- 认证流程管理 -
src/utils/request.js- HTTP 请求拦截器
重要:当前授权链路使用的是 /srv/?a=openid。如果后端动作名、cookie 返回方式或公共参数发生变化,需要同时检查真实授权链路和本地 mock 授权链路是否保持一致。
如果你同时修改了动态菜单跳转、webview-preview 或授权回跳逻辑,建议至少手工验证一次这条闭环:
- 首页点击底部动态菜单进入 WebView
- 如未授权则跳到授权页
- 授权成功后回到原来的 WebView 页面
- 左上角原生返回按钮仍然可以返回首页
🌐 弱网/离线支持
项目内置弱网和离线支持:
- 请求超时处理:自动检测网络超时并降级处理
- 离线缓存:支持离线数据缓存和读取
- 弱网提示:统一的弱网提示文案
相关文件:
src/composables/useOfflineBookingCache.jssrc/composables/useOfflineBookingCachePolling.jssrc/utils/uiText.js
📦 技术栈
- 框架:Taro 4.x
- UI 库:Vue 3 + NutUI 4.x
- 状态管理:Pinia
- HTTP:axios-miniprogram
- 样式:Less + TailwindCSS
- 构建工具:Webpack 5
🎯 路径别名
已配置的路径别名:
@/utils -> src/utils
@/components -> src/components
@/images -> src/assets/images
@/assets -> src/assets
@/composables-> src/composables
@/api -> src/api
@/stores -> src/stores
@/hooks -> src/hooks
📝 开发规范
组件编写
- 使用 Vue 3 Composition API
- 组件统一放在
src/components/目录 - Props 定义清晰,注释详细
API 调用
- 接口统一放在
src/api/下按模块定义 - 使用
xxxAPI(params)命名格式 - 请求方法统一使用
src/api/fn.js中的封装 - 页面不要直接判断当前是否 Mock,统一让
src/api/fn.js和src/mock/兜底
状态管理
- 使用 Pinia 进行状态管理
- Store 文件统一放在
src/stores/目录 - 复杂逻辑使用 composables 封装
样式编写
- 通用样式使用 TailwindCSS 工具类
- 组件样式使用 Less
- NutUI 组件使用 375px 设计稿,其他使用 750px
🔧 可选功能
以下功能可以根据项目需求选择使用或移除:
-
二维码组件:
src/components/qrCode.vue -
海报生成器:
src/components/PosterBuilder/ -
微信支付:
src/utils/wechatPay.js、src/api/wx/ -
时间选择器:
src/components/time-picker-data/ -
离线缓存:
src/composables/useOfflineBookingCache.js
📚 相关文档
⚠️ 注意事项
- 小程序启动会自动执行静默认证,确保后端接口正常
- 请求超时默认 5 秒,可在
src/utils/request.js中修改 - NutUI 组件已配置自动导入,无需手动引入
- TailwindCSS 已禁用 preflight,避免与小程序样式冲突
- 认证失败会自动跳转到
/pages/auth/index
📄 License
MIT