# base-uniapp
**Repository Path**: riskboy/base-uniapp
## Basic Information
- **Project Name**: base-uniapp
- **Description**: base-uniapp
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-12-09
- **Last Updated**: 2025-12-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# base-uniapp
基于 Vue 3 + TypeScript + Vite 的 uni-app 多端开发基础模板。
## 技术栈
- Vue 3.4 + TypeScript
- Vite 5
- Pinia 状态管理
- UnoCSS 原子化 CSS
- uview-plus UI 组件库
- vue-i18n 国际化
## 支持平台
H5 / 微信小程序 / 支付宝小程序 / 抖音小程序 / QQ小程序 / APP
## 项目结构
```
src/
├── api/ # 接口定义
├── components/ # 组件
│ ├── my/ # 自定义组件
│ ├── navbarContent/
│ └── tabbar/
├── hooks/ # 组合式函数
├── pages/ # 页面
├── static/ # 静态资源
├── stores/ # Pinia 状态
├── types/ # 类型定义
└── utils/ # 工具函数
```
## 命令
```bash
pnpm dev:h5 # H5 开发
pnpm dev:mp-weixin # 微信小程序开发
pnpm dev:app # APP 开发
pnpm build:h5 # H5 构建
pnpm build:mp-weixin # 微信小程序构建
pnpm build:app # APP 构建
pnpm lint # 代码检查
pnpm lint:fix # 代码修复
```
## 环境变量
```
VITE_API_URL # API 基础地址
VITE_API_PREFIX # API 前缀
```
## API 规范
```ts
// src/api/xxx.ts
import request from "@/utils/request";
export const xxxApi = {
getList: (params: object) => request({ url: "/xxx", method: "GET", params }),
create: (data: object) => request({ url: "/xxx", method: "POST", data })
}
```
### Request 配置项
| 参数 | 类型 | 说明 |
|------|------|------|
| url | string | 请求路径 |
| method | GET/POST | 请求方法 |
| params | object | GET 参数(自动过滤空值) |
| data | object | POST 数据 |
| header | object | 请求头 |
| prefix | string | 接口前缀(覆盖 VITE_API_PREFIX) |
| cancelPrevious | boolean | 是否取消之前的同 key 请求 |
| requestKey | string | 请求标识(配合 cancelPrevious 使用) |
Token 自动从 `uni.getStorageSync("token")` 获取并携带。
## Utils 工具函数
| 函数 | 说明 |
|------|------|
| `redirect(options)` | 页面跳转,自动识别 tabbar 页面 |
| `copy(value, callback)` | 复制到剪贴板 |
| `getElementRect(selector, instance?)` | 获取元素布局信息 |
| `currRoute()` | 获取当前路由路径 |
| `currFullPath()` | 获取当前完整路径(含 /) |
| `formatArguments(data)` | 过滤对象中的空值 |
| `getPx(value, unit?)` | 转换 rpx/upx 为 px |
| `addUnit(value, unit?)` | 添加单位 |
| `delay(ms)` | 延迟 Promise |
| `isUrl(str)` | 判断是否是 URL |
| `isJsonString(str)` | 判断是否是 JSON 字符串 |
| `isWeixinBrowser()` | 判断是否微信浏览器 |
| `getTabbarPages()` | 获取 tabbar 页面列表 |
| `queryParams(params, filterEmpty?)` | 对象转查询字符串 |
| `parseQuery(query)` | 查询字符串转对象 |
| `getImageInfo(src)` | 获取图片信息 Promise |
| `getDownloadFileInfo(url)` | 下载文件 Promise |
### redirect 配置
```ts
redirect({
url: "/pages/xxx/index",
mode: "navigateTo" | "switchTab" | "reLaunch" | "redirectTo",
param: { id: 1 },
success: () => {},
fail: () => {}
})
```
## Hooks
### useList - 列表分页
```ts
const { data, total, isLoading, isLoadMore, error, getList, resetState } = useList(api, {
immediate: true,
needReachBottom: true,
params: { page: 1, size: 10 },
path: { dataKey: "list", totalKey: "count", pageKey: "page", sizeKey: "size" },
manageData: (data) => {}
})
```
### useResetState - 状态重置
```ts
const [state, reset] = useResetReactive({ name: "", age: 0 })
const [refState, resetRef] = useResettableRef({ count: 0 })
```
### useSafeAreaInsets - 安全区域
```ts
const { saveTop, safeBottom } = useSafeAreaInsets()
```
### useMenuButtonInfo - 胶囊按钮信息
```ts
const { menuLeft, menuRight, menuTop, menuHeight } = useMenuButtonInfo()
```
### useSaveTopBoxHeight - 导航栏高度
```ts
const { height, contentHeight, contentWidth, statusBarHeight } = useSaveTopBoxHeight(contentHeight?)
```
### useScrollTop - 页面滚动
```ts
const { scrollTop } = useScrollTop(handleScroll?)
```
### useAnimation - 元素进入动画
```ts
const { show, AnimationFormat, transitionDuration } = useAnimation(selector, { delay: 0.1, duration: 0.3 })
```
### useImgInfo - 图片尺寸计算
```ts
const { height, imgratio, updateImgInfo } = useImgInfo(imgUrl, selector, immediate?)
```
## Stores
### useConfigStore - 系统配置
| 属性/方法 | 说明 |
|-----------|------|
| navHeight | 导航栏高度(rpx) |
| windowHeight | 窗口高度 |
| screenHeight | 屏幕高度 |
| safeAreaInsets | 安全区域 { top, right, bottom, left } |
| menuButtonInfo | 胶囊按钮信息 |
| XClientType | 客户端类型:h5/wechat/miniProgram/app |
| getNavHeight() | 初始化导航栏高度 |
| setXClientType() | 初始化客户端类型 |
| getMenuButtonInfo() | 初始化胶囊信息 |
### useTabbarStore - 底部导航
| 属性 | 说明 |
|------|------|
| tabbarItemHeight | tabbar 项高度 |
| tabbarHeight | tabbar 总高度(含安全区域) |
| tabbarList | tabbar 配置列表 |
### useThemeStore - 主题
| 属性/方法 | 说明 |
|-----------|------|
| themeStyle | 主题 CSS 变量对象 |
| hexToRgba(hex, alpha) | 颜色转换 |
默认主题变量:`--theme-color`, `--accent`, `--bg`, `--text`, `--text-muted`
## 自定义组件
### my-layout - 页面布局
```vue
内容
```
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| title | string | "" | 导航栏标题(有值则显示 navbar) |
| tabbarIndex | number | -1 | tabbar 索引(>=0 显示 tabbar) |
| needSafeTop | boolean | false | 是否需要顶部安全区域 |
| needSafeBottom | boolean | true | 是否需要底部安全区域 |
| safeTopBgColor | string | #fff | 顶部安全区背景色 |
| background | string | #fff | 导航栏背景色 |
| color | string | #000 | 导航栏文字颜色 |
| borderBottom | boolean | false | 导航栏底部边框 |
| customBack | boolean | false | 自定义返回事件 |
事件:`@back`
### my-navbar - 导航栏
```vue
```
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| title | string | "" | 标题 |
| background | string | #fff | 背景色 |
| color | string | #000 | 文字颜色 |
| showLeft | boolean | true | 显示左侧返回 |
| customBack | boolean | false | 自定义返回事件 |
| borderBottom | boolean | false | 底部边框 |
插槽:`left`, `title`, `right`
事件:`@back`
### my-image - 图片
```vue
```
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| src | string | 必填 | 图片地址 |
| mode | string | "" | 裁剪模式 |
| preview | boolean | false | 点击预览大图 |
事件:`@load`, `@error`
### my-lazy-image - 懒加载图片
```vue
```
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| src | string | "" | 图片地址 |
| mode | string | "" | 裁剪模式 |
| threshold | number | 100 | 预加载阈值(px) |
事件:`@load`, `@error`
### my-swiper - 轮播图
```vue
内容
```
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| list | array | [] | 数据列表 |
| height | number/string | 150 | 高度 |
| bottom | number/string | 10 | 指示器距底部距离 |
| autoplay | boolean | true | 自动播放 |
| interval | number | 3000 | 切换间隔(ms) |
| displayMultipleItems | number | 1 | 同时显示数量 |
| previousMargin | string | "0" | 前边距 |
插槽:`default({ item, current })`, `indicator({ current })`
事件:`@change`
## CSS 变量
| 变量 | 说明 |
|------|------|
| --nav-height | 导航栏高度 |
| --safe-top | 顶部安全区域高度 |
| --safe-bottom | 底部安全区域高度 |
| --tabbar-height | tabbar 高度 |
| --theme-color | 主题色 |
| --accent | 强调色 |
| --bg | 背景色 |
| --text | 文字颜色 |
| --text-muted | 次要文字颜色 |
## UnoCSS 快捷方式
```
flex-column, justify-center, align-center, flex1
line1, line2, line3, line4 # 文本截断
```
## 图标使用
基于 UnoCSS + Iconify 的纯 CSS 图标方案,三端兼容。
### 安装图标集
```bash
pnpm add -D @iconify-json/carbon
```
### 使用
```vue
```
### 格式
```
i-{图标集}-{图标名}
```
### 常用图标集
| 包名 | 前缀 | 说明 |
|------|------|------|
| @iconify-json/carbon | i-carbon- | IBM Carbon |
| @iconify-json/mdi | i-mdi- | Material Design |
| @iconify-json/ri | i-ri- | Remix Icon |
| @iconify-json/tabler | i-tabler- | Tabler Icons |
图标浏览:https://icon-sets.iconify.design/
## 条件编译
```ts
// #ifdef H5
// 仅 H5 执行
// #endif
// #ifdef MP-WEIXIN
// 仅微信小程序执行
// #endif
// #ifdef APP-PLUS
// 仅 APP 执行
// #endif
// #ifndef H5
// 非 H5 执行
// #endif
```
## 新增页面
1. 在 `src/pages/` 下创建页面文件夹和 `index.vue`
2. 在 `src/pages.json` 的 pages 数组中添加路径
3. 如需添加 tabbar 页面,同时在 tabBar.list 和 stores/modules/tabbar.ts 中配置
## easycom 组件规则
```json
{
"my-(.*)": "@/components/my/my-$1/my-$1.vue"
}
```
自定义组件:``, ``, ``, ``, ``