Appearance
Mobile 移动端
路径:packages/mobile
技术:uni-app + Vue 3(CLI + Vite,依赖见 catalogs.mobile)
下载
| 项 | 地址 |
|---|---|
| 脚手架 Mobile 安装包(Android APK) | xichen_mobile.apk |
TIP
APK 内置 API 地址取决于打包时的 .env.production。真机需能访问对应后端地址。
定位
- 业务端,不做完整系统管理(用户/角色/菜单 CRUD 在 Web/Desktop)
- 仿 uni-starter 三栏 Tab(首页 / 用户 / 我的),用户模块为真接口 CRUD 范例
- 登录、用户中心、权限宫格对接现有 RBAC auth
- 复用
@xichen-full-stack/types、@xichen-full-stack/auth、@xichen-full-stack/utils - HTTP 层在包内自实现(
uni.request),API 路径与@xichen-full-stack/api-client对齐
页面结构
| 页面 | 说明 | 权限 |
|---|---|---|
pages/grid/index | Tab 首页:Banner + RBAC 业务宫格 + 静态宫格 | 登录 |
pages/list/list | Tab 用户列表(分页、搜索、下拉刷新) | system:user:list |
pages/list/search | 用户高级搜索(debounce) | system:user:list |
pages/list/detail | 用户详情 | system:user:list |
pages/list/edit | 编辑用户 | system:user:update |
pages/ucenter/index | Tab 我的:资料、角色、退出 | 登录 |
pages/ucenter/userinfo | 个人资料(PUT 当前用户) | 登录 |
pages/ucenter/settings | 设置(静态演示) | 登录 |
pages/ucenter/about | 关于 | 登录 |
pages/common/webview | 内嵌 H5 | 登录 |
pages/login/index | 登录(Xm* UI) | 公开 |
pages/ui-kit/index | UI 组件库展示 | 登录 |
pages/demo/index | 健康检查示例 | system:user:list |
无 system:user:list 时进入「用户」Tab 会显示页内无权限提示(不自动跳转),见 constants/tab-pages.ts。
目录结构
text
src/
├── api/
│ ├── http.ts # uni.request + 401 Token 刷新
│ ├── index.ts # getApi() 单例
│ ├── token-storage.ts # getTokenStorage() 统一读写
│ └── modules/
│ ├── auth.ts # login / me / logout / health
│ └── system.ts # users / roles / menus / permissions(与 api-client 路径一致)
├── composables/
│ ├── usePermission.ts
│ ├── usePageGuard.ts # 登录 + bootstrap + 权限;accessGranted
│ ├── useRequest.ts # loading 计数、error toast、debounce
│ └── usePageList.ts # Tab 列表页范式
├── stores/auth.ts # Pinia;bootstrap / refreshSession
├── constants/
│ ├── entries.ts # 首页 RBAC 宫格 MOBILE_ENTRIES
│ ├── tab-pages.ts # Tab 页权限映射
│ └── mock/ # Banner、静态宫格(非业务 API)
├── components/xm-*/ # Xm* 通用 UI(easycom 自动引入)
├── pages/ # grid / list / ucenter / login / demo / ui-kit
├── utils/
│ ├── navigate.ts # Tab 跳转、ensureLoggedIn
│ ├── list-refresh.ts # markUserListStale / 编辑后刷新列表
│ └── user-display.ts
├── styles/theme.scss # NC 企业色
├── static/tabbar/ # TabBar 图标
└── App.vue # 启动 bootstrap;前后台 refreshSessionUI 组件(Xm*)
与 Web Xc* 对应,基于 uni 内置组件,适配 微信小程序 + Android App:
| 组件 | 说明 |
|---|---|
xm-page | 页面容器 |
xm-list-page | 列表三层:操作 / 内容 / 底部 |
xm-card / xm-section | 卡片与分组 |
xm-button / xm-input / xm-search-bar | 表单控件 |
xm-cell / xm-cell-group | 列表行 |
xm-tag / xm-grid | 标签与宫格 |
xm-empty / xm-divider | 空状态与分割线 |
xm-banner | 首页轮播 |
xm-load-state | 加载 / 错误 / 重试统一态 |
pages.json 配置 easycom:^xm-(.*) → @/components/xm-$1/xm-$1.vue。
从 我的 → UI 组件库 或 /pages/ui-kit/index 查看示例。
主题变量通过 src/uni.scss 注入各组件样式;vite.config.ts 中 SCSS includePaths 指向 src/,以便 @import 'styles/theme.scss' 正确解析。
TabBar 与导航
| Tab | 路径 | 说明 |
|---|---|---|
| 首页 | pages/grid/index | Banner + MOBILE_ENTRIES 权限宫格 |
| 用户 | pages/list/list | 系统用户列表(真接口) |
| 我的 | pages/ucenter/index | 用户信息 + 退出 |
| 工具 | 说明 |
|---|---|
goHome() | switchTab 到首页 |
goLogin() | reLaunch 登录页 |
ensureLoggedIn() | 经 getTokenStorage() 判断,未登录跳转 |
openPage(url) | Tab 页 switchTab,其余 navigateTo |
API 层
ts
import { getApi } from '@/api'
// 认证
await getApi().auth.login({ username, password })
await getApi().auth.me()
// 系统用户(路径与 web api-client 一致)
await getApi().system.users.list({ page: 1, pageSize: 10, keyword: 'admin' })
await getApi().system.users.get(id)
await getApi().system.users.update(id, { nickname: '新昵称' })新增业务域:在 src/api/modules/ 增加模块,于 api/index.ts 挂到 getApi()。
Composables 快速范式
页面守卫
ts
import { usePageGuard } from '@/composables/usePageGuard'
// Tab 根页:无权限时页内提示,不 redirect
const { whenReady, accessGranted } = usePageGuard({
permission: 'system:user:list',
redirectOnDeny: false,
})
onShow(() => {
whenReady(() => loadData())
})- 默认
waitAuth: true:校验前authStore.bootstrap() accessGranted === false时可渲染无权限空态
请求
ts
import { useRequest } from '@/composables/useRequest'
const { loading, error, run } = useRequest({ showErrorToast: true })
await run(() => getApi().auth.health())loading 为并发计数;useDebouncedFn 可用于搜索 debounce。
Tab 列表页
ts
import { usePageList } from '@/composables/usePageList'
import { getApi } from '@/api'
const {
list, keyword, page, total, totalPages,
loading, error, accessGranted,
reload, search, prevPage, nextPage,
setupTabPageLifecycle, goHome,
} = usePageList({
permission: 'system:user:list',
redirectOnDeny: false,
pageSize: 10,
fetch: (q) => getApi().system.users.list(q),
})
setupTabPageLifecycle() // onShow 首次/stale 加载 + onPullDownRefresh编辑成功后调用 markUserListStale()(utils/list-refresh.ts),返回列表 Tab 时自动刷新。
用户模块范例流程
text
首页宫格「用户管理」→ Tab 用户列表
→ 详情(system:user:list)
→ 编辑(system:user:update)→ 保存 → markUserListStale → 列表刷新
我的 → 个人资料 → PUT 当前用户 → refreshSession| 接口 | 方法 | 权限 |
|---|---|---|
/api/v1/system/users | GET | system:user:list |
/api/v1/system/users/:id | GET | system:user:list |
/api/v1/system/users/:id | PUT | system:user:update |
认证与前后台
stores/auth.ts:bootstrap()启动恢复会话;refreshSession()App 从后台回前台时刷新/auth/meApp.vue:onLaunchbootstrap;后续onShow调用refreshSession(跳过首次)- Token 统一经
getTokenStorage(),与ensureLoggedIn()一致
与 Web admin 的差异
| Web admin | Mobile |
|---|---|
| vue-router 动态 addRoute | pages.json 固定页面 + 入口显隐 |
axios + @xichen-full-stack/api-client | uni.request + 本地 getApi() |
| localStorage Token | uni.setStorageSync |
| Element Plus | Xm* 自研组件 |
环境变量
不会读取 .env.example
.env.example 仅为模板。Vite 按模式加载 .env.development / .env.production。
| 文件 | 场景 |
|---|---|
.env.development | dev:h5、dev:app-android 等开发 |
.env.production | build:app-android、HBuilderX 生产打包 |
env
# 示例:.env.production
VITE_API_BASE_URL=http://192.168.1.12:8080- H5 开发可用
localhost - App / 真机 必须用局域网 IP 或公网域名
- 修改 env 后须重新 build
配置入口:src/config/index.ts → getApiBaseUrl()。
manifest.json
| 字段 | 说明 |
|---|---|
appid | DCloud 应用 ID(Android App 必填) |
app-plus.distribute.android.permissions | 网络等权限 |
mp-weixin.appid | 微信小程序 AppID |
启动
bash
pnpm --filter mobile dev:h5 # H5
pnpm --filter mobile dev:mp-weixin # 微信小程序
pnpm --filter mobile dev:app-android # Android 调试
pnpm --filter mobile type-check # TS 检查默认账号:admin / admin123
Android 打包
CLI uni build 不能直接产出可分发 APK,需配合 HBuilderX(建议与 wgt 同版本,如 5.07)。
text
1. 配置 .env.production(API 地址)
2. pnpm --filter mobile build:app-android → dist/build/app
3. HBuilderX 打开 dist/build/app
4. 发行 → 原生 App-云打包 → Android真机调试需 自定义调试基座,勿用标准基座 + 新版 wgt 混用。
bash
pnpm --filter mobile build:app-android
pnpm --filter mobile build:h5
pnpm --filter mobile build:mp-weixin依赖与 catalog
mobile 使用 pnpm-workspace.yaml 的 catalogs.mobile(Vite 5、TS 4.9、@dcloudio/*),与 web/desktop 的 catalog 分离,不可混升。