AGILE TEAM
Skip to content

移动端 uniApp — 概览 & 技术选型

基座定位

wl-mbase(华新移动端门户基座)是基于 Vue 3 + UniApp + TypeScript 的企业移动端统一入口——不是业务应用,而是承载所有业务子应用的基础平台。一套源码通过 UniApp 条件编译,同时运行于微信小程序 / 钉钉 H5 / 普通浏览器 H5 / App 四端。

核心定位:用户在基座登录一次,即可免登进入各业务子系统(智慧安全、智慧安防、智慧环保等),实现 SSO 集成。

三端运行架构

容器方案子应用加载钉钉 JSAPI导航栏
微信小程序<web-view> 组件URL 拼接 token不可用系统自带
钉钉 H5iframe 嵌入 + 基座桥接URL 拼接 token + postMessage 桥接✅ 全量可用钉钉原生
普通浏览器 H5iframe 嵌入URL 拼接 token不可用基座自定义玻璃态

同一套源码通过 UniApp 条件编译(#ifdef MP-WEIXIN / #ifdef H5)+ 运行时 UA 检测(isDingTalkEnv)自动适配各端差异。


技术栈

技术版本职责
Vue3.5.30响应式 + 组合式
UniApp(@dcloudio)3.0.0跨端核心框架(H5/小程序/App)
TypeScript5.7.3类型安全
Vite + vite-plugin-uni5.x构建工具
Pinia + persistedstate2.3.1 / 3.2.3状态管理 + 持久化(uni.storage)
wot-design-uni1.14.0跨平台 UI 组件库
UnoCSS + SCSS66.5.1原子化 CSS
jsencrypt3.5.4RSA 密码加密传输
opencc-js1.3.1简繁中文转换
oxlint + ESLint代码质量(Flat Config)
husky + lint-stagedGit 提交校验
commitizen + commitlint交互式规范提交

环境要求:Node.js >= 18、pnpm >= 10。


基座核心能力

统一登录

  • OAuth2 密码模式(Password Grant)+ RSA 非对称加密传输密码
  • 钉钉 H5 微应用内自动免登:requestAuthCode 换系统 token,失败时不露出账号密码登录框
  • 登录一次,所有子应用免登(SSO)
  • 访客模式:OAuth2 client_credentials 换取受限 token,外部人员免账号密码进入(仅微信小程序端)

子应用免登集成

基座登录 → 读取当前公司上下文
         → 拼接 URL(含 portal_token + user_id + from=portal + companyId + companyName)
         → iframe/web-view 加载子应用
         → 子应用检测 portal_token → 写入登录态 → 跳过登录页

钉钉消息单点跳转

钉钉消息点击后,不先落工作台,而是完成基座免登并直达子应用具体页面。由静态中转页 public/relay.html 承接,不依赖 uni-app 路由初始化与 Nginx 深路径 fallback。审批流消息单独走 FLOW_ 模板分流。详见 H5 子应用集成方案

公司上下文

工作台通过 /hrms/user/getCurUser/hrms/user/getById 读取 userOrganizeInfo,用户选择当前公司后,打开子应用时透传 companyId/companyName;子应用后端必须用 portal_token + companyId 再次校验权限。

钉钉 JSAPI 鉴权与桥接

  • 进入子应用时惰性 dd.config 签名鉴权(拍照/定位为敏感 API,必须鉴权),按 URL 缓存
  • 52013 签名错误自动重试;非敏感 API(扫码)免鉴权
  • 子应用 iframe 受限无法直调 JSAPI,由基座统一代理,通过 mbase-bridge postMessage 桥接回传(拍照/上传/定位/扫码)

HTTP 请求层

请求去重、路由切换自动取消、401 防抖(只弹一次)、refresh_token 静默续期。


多端编译目标

平台编译指令说明
H5uni -p h5运行于移动浏览器 / 钉钉 WebView
微信小程序uni -p mp-weixin上线前需配置微信公众平台业务域名白名单
App(全平台)uni -p app同时支持 Android / iOS
App-Androiduni -p app-android独立 Android 包
App-iOSuni -p app-ios独立 iOS 包

快速开始

bash
pnpm install          # 安装依赖
pnpm dev:h5           # H5 开发(端口 1999,走本地 Mock)
pnpm dev:wx           # 微信小程序开发
pnpm dev:app          # App 开发

首次运行需确保内网可访问 172.28.99.172:9000,或修改 env/.env.development 中的 VITE_API_BASE_URL 指向可用服务。


常用命令

命令分两类:联调(dev server,不出包、实时编译、可连不同后端)与构建(build,压缩出包、产物 dist/build/)。环境共 5 套:dev / sit / uat / pre / prd

本地联调(dev server 直连后端)

命令联调目标说明
pnpm dev:h5本地 Mock纯前端开发,vite-plugin-mock-dev-server
pnpm sitSIT 后端dev server 直连 SIT 接口(端口 1999)
pnpm uatUAT 后端dev server 直连 UAT 接口
pnpm prePRE 后端dev server 直连 PRE 接口

PRD 生产环境不提供本地联调命令(不随意直连生产调试)。

生产构建

命令环境平台
pnpm build:h5:devdevH5
pnpm build:h5:sitsitH5
pnpm build:h5:uatuatH5
pnpm build:h5:prepreH5
pnpm build:h5(或 pnpm buildprdH5
pnpm build:wx:sitsit微信小程序
pnpm build:wx:uatuat微信小程序
pnpm build:wx:prepre微信小程序
pnpm build:wxprd微信小程序
pnpm build:app / build:app-android / build:app-iosprdApp

其他

bash
pnpm lint    # oxlint + ESLint 自动修复
pnpm format  # Prettier 格式化
pnpm cz      # 规范提交(commitizen 交互式)
pnpm push    # 推送到 origin / gitee / gitcode

目录结构

wl-mbase/
├── docs/                        # 项目文档(集成文档/钉钉免登/JSAPI鉴权/真机调试/审批流/消息中心)
├── public/
│   └── relay.html               # 钉钉消息单点跳转静态中转页
├── env/                         # 多环境配置(Vite 编译时注入)
│   ├── .env                     # 公共基础变量
│   ├── .env.development         # 开发环境
│   ├── .env.sit                 # SIT 测试环境
│   ├── .env.uat                 # UAT 预发布环境
│   ├── .env.pre                 # PRE 预生产环境
│   └── .env.production          # PRD 生产环境
├── mock/                        # Mock 数据(vite-plugin-mock-dev-server)
├── scripts/                     # 构建辅助脚本(postbuild-mp-weixin.cjs 等)
├── src/
│   ├── api/                     # 接口层
│   │   ├── factory.ts           #   请求实例工厂
│   │   └── modules/             #   业务模块(user/company/message/dingtalk/approval/wechat)
│   ├── components/global/       # 全局组件(easycom 自动注册)
│   │   ├── C_Header/            #   顶部导航栏(钉钉/通用自适应)
│   │   ├── C_Layout/            #   页面骨架布局
│   │   ├── C_Tabbar/            #   底部标签栏
│   │   ├── C_Logo/              #   企业 Logo
│   │   └── C_VirtualStatusBar/  #   虚拟状态栏(钉钉环境适配)
│   ├── composables/             # 组合式函数(locale.ts 语言切换 / use-logout.ts 统一退出)
│   ├── config/
│   │   ├── env.ts               # 运行时环境变量(VITE_* 优先,硬编码兜底)
│   │   └── portal-apps.ts       # 子应用注册表(名称/图标/URL/角色/排序/平台/访客)
│   ├── constants/               # 全局常量(应用标识、OAuth 凭据等)
│   ├── directives/              # 自定义 Vue 指令
│   ├── pages/
│   │   ├── index/               # 工作台首页(子应用入口列表)
│   │   ├── login/               # 登录页(OAuth2 密码模式 + RSA + 访客入口)
│   │   ├── launch/              # 冷启动停留页(消费 redirect,避免被默认跳转覆盖)
│   │   ├── relay/               # 旧 SPA 中转入口(兼容历史消息配置)
│   │   ├── approval/            # 基座内置审批详情页(FLOW_COMMENTS 通过/驳回)
│   │   ├── message/             # 消息中心
│   │   ├── profile/             # 个人中心
│   │   ├── scan/                # 扫码(分包,调钉钉原生扫码)
│   │   ├── settings/            # 设置 / 修改密码(分包)
│   │   └── webview/             # H5 子应用容器(分包,核心集成点)
│   │       ├── index.vue        #   容器组件 + 消息分发
│   │       ├── mp-webview.vue   #   小程序 <web-view> 组件
│   │       ├── bridge-capabilities.ts # 能力桥接处理(拍照/定位/扫码)
│   │       ├── photo-utils.ts   #   图片归一化(dataURI/fetch/base64)
│   │       └── data.ts          #   常量(超时/进度/动画时长)
│   ├── static/                  # 静态资源(图片 / 字体)
│   ├── stores/modules/          # Pinia 状态
│   │   ├── app.ts               #   应用全局状态(系统信息/加载状态)
│   │   ├── company.ts           #   公司上下文(组织关系/选择/错误态)
│   │   ├── user.ts              #   用户状态(token/权限/角色/登录态)
│   │   └── message.ts           #   消息中心状态
│   ├── styles/                  # 全局样式 & mixins
│   ├── types/                   # TypeScript 类型定义
│   ├── utils/
│   │   ├── http.ts              # HTTP 封装(去重/取消/重试/401防抖)
│   │   ├── http-helpers.ts / http-types.ts  # HTTP 辅助与类型
│   │   ├── router.ts            # 路由守卫(鉴权/权限/已登录拦截)
│   │   ├── rsa.ts               # RSA 密码加密
│   │   ├── dingtalk/            # 钉钉 JSAPI 工具集(按职责拆分)
│   │   │   ├── shared.ts        #   环境检测/JSAPI加载/通用调用/类型
│   │   │   ├── config.ts        #   dd.config 鉴权/初始化/导航栏/诊断
│   │   │   ├── photo.ts         #   拍照/选图(渐进增强)
│   │   │   ├── upload.ts        #   文件上传/拍照直传(安卓/iOS 双路)
│   │   │   └── device.ts        #   定位/扫码(非敏感API免鉴权)
│   │   ├── dingtalk-redirect.ts # 钉钉消息 redirect 捕获/白名单/跳转消费
│   │   ├── flow-message.ts      # 审批流消息分流
│   │   ├── visitor-auth.ts      # 访客模式(client_credentials 换 token)
│   │   ├── wechat-openid.ts     # 微信 openid 获取(访客身份识别)
│   │   ├── user-identity.ts     # 用户账号标识归一化
│   │   ├── app-layout-prefs.ts  # 布局偏好
│   │   ├── logger.ts            # 日志
│   │   └── error-handler.ts     # 全局错误处理
│   ├── manifest.json            # 多端平台配置(AppID / 权限 / H5 路由)
│   └── pages.json               # 页面路由 & tabbar 配置(主包+分包)
├── vite.config.js
├── uno.config.ts
└── package.json

多环境配置

环境文件MockAPI 地址说明
开发.env.development开启http://172.28.99.172:9000Vite DevProxy
SIT.env.sit关闭https://ytiop-sit.walsin.com.cn/sit-api测试环境
UAT.env.uat关闭https://ytiop-uat.walsin.com.cn/uat-api预发布环境
PRE.env.pre关闭https://ytiop-pre.walsin.com.cn/pre-api预生产环境
生产.env.production关闭https://ytiop-prd.walsin.com.cn/prd-api必须 HTTPS

切换环境只改 env 文件(VITE_API_BASE_URL / VITE_DOMAIN),无需改代码。H5 开发环境请求通过 Vite Proxy 转发,小程序/App 直接使用完整地址。


平台检测与钉钉集成

平台检测无独立 platform.ts,统一通过 UniApp 条件编译 + 钉钉 isDingTalkEnv()(基于 UA)实现:

平台检测方式特殊处理
微信小程序UniApp 条件编译 #ifdef MP-WEIXIN<web-view> 嵌入子应用,无自定义导航栏
AppUniApp 条件编译 #ifdef APP-PLUSwebview 组件 + 自定义玻璃态导航栏
钉钉 H5isDingTalkEnv()(UA 含 DingTalk)隐藏自定义导航栏,注入 JSAPI 桥接
普通浏览器 H5默认 fallback完整自定义导航栏,Vite devServer 代理调试

src/utils/dingtalk/ 封装钉钉 JSAPI 能力,非钉钉环境下所有 API 安全 no-op,不影响其他平台。主要导出:

API作用
initDingTalk()App.vue#onLaunch 初始化
dingtalkConfig() / dingtalkReady()dd.config 签名鉴权 / ready 等待
setDingTalkTitle(title)同步页面标题到钉钉原生导航栏
getDingTalkAuthCode()获取免登 authCode
dingtalkTakePhoto() / dingtalkChooseImage()拍照 / 选图(含 iOS 降级)
dingtalkTakePhotoAndUpload()拍照直传后端
dingtalkGetLocation()定位(gcj02,需鉴权)
dingtalkScan()扫一扫(免鉴权)
getDingTalkDebugInfo()签名诊断信息

钉钉微应用上线前需在钉钉开放平台配置:微应用首页 URLJSAPI 安全域名


已注册子应用

应用mpPath说明钉钉 JSAPI
智慧安全/mbase/aq安全生产管理系统拍照/上传/定位
智慧安防/mbase/af安防监控管理系统拍照/上传/定位/扫码
智慧环保/mbase/hb环保监测管理系统-

mpPath 运行时与 VITE_DOMAIN 动态拼接,切换环境只改 env 文件。新增子应用时必须同步维护 src/config/portal-apps.tspublic/relay.html 的消息跳转白名单。

详细集成方案(SSO 免登、消息单点跳转、JSAPI 桥接、访客模式、公司上下文、openid 分发)请参阅 H5 子应用集成方案


核心功能页面

页面路径包类型说明
工作台首页pages/index/index主包子应用图标入口列表,支持角色/平台过滤
登录页pages/login/index主包OAuth2 密码模式 + RSA + 微信访客入口
冷启动停留页pages/launch/index主包已登录冷启动消费 redirect,避免默认跳转覆盖
旧 SPA 中转入口pages/relay/index主包兼容历史消息配置(新消息首选 relay.html
审批详情页pages/approval/index主包FLOW_COMMENTS 审批,支持通过/驳回
消息中心pages/message/index主包系统消息列表与已读/未读状态
个人中心pages/profile/index主包用户信息、语言切换、退出登录
H5 子应用容器pages/webview/index分包核心:iframe/web-view 嵌入,SSO Token 自动注入
扫码pages/scan/index分包调用设备摄像头扫码
设置 / 修改密码pages/settings/index分包主题/语言/密码修改等个人设置

全局组件(C_ 系列)

所有全局组件通过 easycom 规则(^C_(.*) → @/components/global/C_$1/index.vue自动注册,无需手动导入:

组件功能
<C_Header />自定义导航栏,玻璃态效果,支持多端(含钉钉适配)
<C_Layout />页面通用布局容器,处理安全区域 padding
<C_Tabbar />底部 Tab 导航(工作台/消息/个人中心)
<C_Logo />品牌 Logo,支持主题切换
<C_VirtualStatusBar />H5/App 虚拟状态栏,补偿原生状态栏高度

多环境地址对照

线上环境

环境域名API 前缀
SITytiop-sit.walsin.com.cn/sit-api
UATytiop-uat.walsin.com.cn/uat-api
PREytiop-pre.walsin.com.cn/pre-api
PRDytiop-prd.walsin.com.cn/prd-api

⚠️ PRE 域名 / API 前缀为按规律推断的占位值,上线前需确认替换。

开发环境(内网直连)

服务地址说明
移动端网关http://172.28.99.172:9000OAuth2 / JWT Token
智慧安全 H5本地 Vite 代理 /mbase/aq子应用,iframe 嵌入
智慧安防 H5本地 Vite 代理 /mbase/af子应用,iframe 嵌入
智慧环保 H5本地 Vite 代理 /mbase/hb子应用,iframe 嵌入

You may not distribute, modify, or sell this software without permission.