Skip to content

UniApp 移动端架构

技术栈

技术用途
Vue 3 Composition APIUI 框架(<script setup>
Pinia + persistedstate状态管理 + 持久化
vue-i18n国际化(zh-CN / zh-TW / en)
UnoCSS原子化 CSS(rem-to-rpx 转换)
SCSS主题变量系统

支持平台

平台说明
H5浏览器端
微信小程序WeChat Mini Program
iOSApp(uni-app 引擎)
AndroidApp(uni-app 引擎)
鸿蒙HarmonyOS

项目结构

uniapp-zq/
├── api/                         # API 接口
│   ├── auth.js                  # 认证 API
│   ├── dept.js                  # 部门
│   ├── file.js                  # 文件
│   ├── user.js                  # 用户
│   ├── workflow.js              # 工作流
│   ├── form.js                  # 表单
│   └── ...
├── components/
│   ├── zq-icon/                 # SVG 内联图标(Lucide 风格)
│   ├── zq-navbar/               # 自定义导航栏
│   ├── zq-tabbar/               # 自定义 TabBar
│   ├── zq-ui/                   # UI 组件库(32 个组件)
│   ├── form-render/             # 表单渲染器
│   ├── signature-pad/           # 手写签名
│   └── wf-icon/                 # 工作流图标
├── composables/
│   ├── useTheme.js              # 主题 Composable
│   ├── useFileUrl.js            # 文件 URL 管理
│   ├── useImageCache.js         # 图片缓存
│   └── useFormulaCalculation.js # 公式计算
├── i18n/                        # 国际化
│   ├── index.js
│   ├── zh-CN.js
│   ├── zh-TW.js
│   └── en.js
├── pages/                       # 页面
│   ├── login/                   # 登录
│   ├── index/                   # 首页
│   ├── workflow/                # 工作流
│   ├── mine/                    # 我的
│   └── demo/                    # 组件演示
├── stores/                      # Pinia 状态管理
├── styles/
│   ├── theme.scss               # CSS 变量默认值
│   ├── theme-colors.js          # 主题色配置
│   └── common.scss              # 公共样式
├── utils/
│   ├── request.js               # HTTP 请求封装
│   ├── route-guard.js           # 路由守卫
│   └── ...
├── pages.json                   # 页面配置
├── manifest.json                # 应用配置
├── main.js                      # 入口文件
└── App.vue                      # 根组件

入口文件 (main.js)

javascript
import { createSSRApp } from 'vue'
import * as Pinia from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import i18n from './i18n'
import { setupRouteGuard } from './utils/route-guard'

export function createApp() {
  const app = createSSRApp(App)
  const pinia = Pinia.createPinia()
  pinia.use(piniaPluginPersistedstate)
  app.use(pinia)
  app.use(i18n)
  setupRouteGuard()
  return { app, Pinia }
}

页面配置 (pages.json)

easycom 自动注册

json
{
  "easycom": {
    "autoscan": true,
    "custom": {
      "^zq-(icon|navbar|tabbar)$": "@/components/zq-$1/zq-$1.vue",
      "^zq-(.*)": "@/components/zq-ui/zq-$1/zq-$1.vue"
    }
  }
}

所有 zq- 前缀组件无需手动导入,直接在模板中使用。

页面定义

json
{
  "pages": [
    { "path": "pages/login/index", "style": { "navigationBarTitleText": "" } },
    { "path": "pages/index/index", "style": { "navigationStyle": "custom" } },
    { "path": "pages/workflow/index", "style": { "navigationStyle": "custom" } },
    { "path": "pages/mine/index", "style": { "navigationStyle": "custom" } }
  ],
  "tabBar": {
    "custom": true,
    "list": [
      { "pagePath": "pages/index/index" },
      { "pagePath": "pages/workflow/index" },
      { "pagePath": "pages/mine/index" }
    ]
  }
}

自定义导航栏

使用 navigationStyle: "custom" 配合 zq-navbar 组件实现自定义导航栏。

主题系统

设计原则

  • 所有颜色通过 CSS 变量控制,禁止硬编码颜色值
  • 支持 light / dark 两种主题
  • 主题色配置集中在 styles/theme-colors.js

theme-colors.js

定义 light 和 dark 两套颜色:

javascript
export const lightColors = {
  '--color-primary': '#409eff',
  '--color-success': '#67c23a',
  '--color-warning': '#e6a23c',
  '--color-error': '#f56c6c',
  '--color-bg-page': '#f5f7fa',
  '--color-bg-card': '#ffffff',
  '--color-text-primary': '#303133',
  '--color-text-secondary': '#909399',
  '--color-border': '#dcdfe6',
  // ...
}

export const darkColors = {
  '--color-primary': '#409eff',
  '--color-bg-page': '#1a1a2e',
  '--color-bg-card': '#16213e',
  '--color-text-primary': '#e4e7ed',
  // ...
}

useTheme Composable

在页面根元素设置 CSS 变量:

javascript
import { useTheme } from '../../composables/useTheme'

const { themeVars } = useTheme()

// 模板中使用
// <view class="page" :style="themeVars">

使用示例

scss
.page {
  background-color: var(--color-bg-page);
}

.card {
  background-color: var(--color-bg-card);
  border: 1rpx solid var(--color-border);
}

.title {
  color: var(--color-text-primary);
}

国际化

配置

支持三种语言,默认跟随系统:

语言文件说明
zh-CNi18n/zh-CN.js简体中文
zh-TWi18n/zh-TW.js繁体中文
eni18n/en.js英文

使用方式

vue
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

<template>
  <view>{{ t('common.save') }}</view>
</template>

路由守卫

utils/route-guard.js 实现登录检查:

javascript
const WHITE_LIST = [
  '/pages/login/index',
  // 不需要登录的页面
]

// 拦截 navigateTo / redirectTo / switchTab
// 检查 token,无 token 且不在白名单则跳转登录页

后端对接

请求配置

javascript
// H5 开发环境:使用 Vite 代理
const BASE_URL = '/basic-api'

// 其他平台:完整 URL
const BASE_URL = 'http://192.168.1.100:8000'

登录认证

javascript
POST /api/core/login
{
  "username": "admin",
  "password": "xxx"
}

// 响应
{
  "accessToken": "eyJ...",
  "refreshToken": "eyJ...",
  "tokenType": "bearer",
  "expireTime": 86400
}

Token 存储在 Pinia(持久化到 Storage),请求拦截器自动添加 Authorization: Bearer {token}

页面模板

vue
<template>
  <view class="page" :style="themeVars">
    <zq-navbar :title="t('page.title')" show-back />

    <view class="page-content">
      <!-- 页面内容 -->
    </view>

    <!-- TabBar 页面 -->
    <zq-tabbar />
  </view>
</template>

<script setup>
import { useI18n } from 'vue-i18n'
import { useTheme } from '../../composables/useTheme'

const { t } = useI18n()
const { themeVars } = useTheme()
</script>

<style lang="scss" scoped>
.page {
  min-height: 100vh;
  background-color: var(--color-bg-page);
}

.page-content {
  padding: 24rpx;
}
</style>

生命周期

必须使用 UniApp 提供的生命周期,禁止使用 Vue 原生生命周期:

UniAppVue 原生说明
onLoadcreated页面加载
onShowmounted页面显示
onHide-页面隐藏
onUnloadunmounted页面卸载
onPullDownRefresh-下拉刷新
onReachBottom-触底加载

尺寸单位

使用 rpx(750rpx = 屏幕宽度),确保多端适配:

scss
.card {
  width: 690rpx;           // 750 - 30*2 边距
  padding: 24rpx;
  border-radius: 16rpx;
  margin: 0 30rpx 24rpx;
}

注意事项

  • 禁止使用 documentwindow 等浏览器 API,使用 uni.xxx 替代
  • 禁止使用 emoji,使用 zq-icon 组件替代
  • 样式避免复杂 CSS 选择器嵌套(小程序兼容性)
  • 微信小程序中嵌套 flex + scroll-view 高度不可靠,使用明确像素高度

Released under the MIT License.