749 lines
15 KiB
Markdown
749 lines
15 KiB
Markdown
# 核心组件文档
|
||
|
||
## 1. 认证组件 (Auth)
|
||
|
||
### 功能描述
|
||
用户认证和权限管理组件,负责登录状态检查、用户信息存储和token管理。
|
||
|
||
### 入参
|
||
```javascript
|
||
// 无直接入参,通过方法调用
|
||
```
|
||
|
||
### 出参
|
||
```javascript
|
||
// 用户信息对象
|
||
{
|
||
isLogin: boolean, // 是否已登录
|
||
token: string, // 访问令牌
|
||
refreshToken: string, // 刷新令牌
|
||
expiresIn: number, // 过期时间
|
||
tokenType: string, // 令牌类型
|
||
userId: string, // 用户ID
|
||
username: string, // 用户名
|
||
avatar: string, // 头像
|
||
loginTime: number, // 登录时间
|
||
isDriver: boolean, // 是否为司机
|
||
driverInfo: object // 司机信息
|
||
}
|
||
```
|
||
|
||
### 调用方式
|
||
```javascript
|
||
import {
|
||
saveUserInfo,
|
||
getUserInfo,
|
||
getToken,
|
||
isLoggedIn,
|
||
isDriver,
|
||
getDriverInfo,
|
||
clearUserInfo,
|
||
logout,
|
||
checkLoginAndRedirect
|
||
} from '../utils/auth.js'
|
||
|
||
// 保存用户信息
|
||
saveUserInfo(userInfo)
|
||
|
||
// 获取用户信息
|
||
const userInfo = getUserInfo()
|
||
|
||
// 检查登录状态
|
||
if (isLoggedIn()) {
|
||
// 已登录逻辑
|
||
}
|
||
|
||
// 检查是否为司机
|
||
if (isDriver()) {
|
||
const driverInfo = getDriverInfo()
|
||
}
|
||
|
||
// 退出登录
|
||
logout()
|
||
|
||
// 检查登录并重定向
|
||
checkLoginAndRedirect()
|
||
```
|
||
|
||
### 数据模型
|
||
```javascript
|
||
// 用户信息模型
|
||
interface UserInfo {
|
||
isLogin: boolean
|
||
token: string
|
||
refreshToken: string
|
||
expiresIn: number
|
||
tokenType: string
|
||
userId: string
|
||
username: string
|
||
avatar: string
|
||
loginTime: number
|
||
isDriver?: boolean
|
||
driverInfo?: DriverInfo
|
||
}
|
||
|
||
// 司机信息模型
|
||
interface DriverInfo {
|
||
id: string
|
||
driverId: string
|
||
name: string
|
||
phone: string
|
||
status: string
|
||
data: {
|
||
id: string
|
||
name: string
|
||
phone: string
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 请求组件 (Request)
|
||
|
||
### 功能描述
|
||
统一的HTTP请求组件,处理API调用、token注入、错误处理和用户凭证过期检测。
|
||
|
||
### 入参
|
||
```javascript
|
||
// GET请求
|
||
get(url: string, params?: object, headers?: object)
|
||
|
||
// POST请求
|
||
post(url: string, data?: object, headers?: object)
|
||
|
||
// PUT请求
|
||
put(url: string, data?: object, headers?: object)
|
||
|
||
// DELETE请求
|
||
del(url: string, data?: object, headers?: object)
|
||
|
||
// 文件上传
|
||
uploadFile(url: string, filePath: string, name?: string, formData?: object, headers?: object)
|
||
```
|
||
|
||
### 出参
|
||
```javascript
|
||
// 标准响应格式
|
||
{
|
||
statusCode: number, // HTTP状态码
|
||
data: object, // 响应数据
|
||
header: object, // 响应头
|
||
errMsg: string // 错误信息
|
||
}
|
||
```
|
||
|
||
### 调用方式
|
||
```javascript
|
||
import { get, post, put, del, uploadFile } from '../utils/request.js'
|
||
|
||
// GET请求
|
||
const response = await get('/api/users', { page: 1, size: 10 })
|
||
|
||
// POST请求
|
||
const result = await post('/api/login', { username: 'user', password: 'pass' })
|
||
|
||
// 文件上传
|
||
const uploadResult = await uploadFile('/api/upload', filePath, 'file', { type: 'image' })
|
||
```
|
||
|
||
### 数据模型
|
||
```javascript
|
||
// 请求配置模型
|
||
interface RequestOptions {
|
||
url: string
|
||
method: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
||
data?: object
|
||
headers?: object
|
||
timeout?: number
|
||
}
|
||
|
||
// 响应模型
|
||
interface ApiResponse {
|
||
statusCode: number
|
||
data: {
|
||
code?: number
|
||
msg?: string
|
||
[key: string]: any
|
||
}
|
||
header: object
|
||
errMsg?: string
|
||
}
|
||
|
||
// 错误模型
|
||
interface ApiError {
|
||
errMsg: string
|
||
statusCode?: number
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 位置组件 (Location)
|
||
|
||
### 功能描述
|
||
地理位置获取和权限管理组件,提供位置获取、权限检查和用户引导功能。
|
||
|
||
### 入参
|
||
```javascript
|
||
// 无直接入参,通过方法调用
|
||
```
|
||
|
||
### 出参
|
||
```javascript
|
||
// 位置信息对象
|
||
{
|
||
latitude: number, // 纬度
|
||
longitude: number, // 经度
|
||
accuracy: number, // 精度
|
||
altitude: number, // 海拔
|
||
speed: number, // 速度
|
||
timestamp: number // 时间戳
|
||
}
|
||
```
|
||
|
||
### 调用方式
|
||
```javascript
|
||
import {
|
||
getCurrentLocation,
|
||
checkLocationPermission,
|
||
requestLocationPermission,
|
||
getLocationWithPermission
|
||
} from '../utils/location.js'
|
||
|
||
// 获取当前位置
|
||
const location = await getCurrentLocation()
|
||
|
||
// 检查定位权限
|
||
const hasPermission = await checkLocationPermission()
|
||
|
||
// 申请定位权限
|
||
const granted = await requestLocationPermission()
|
||
|
||
// 获取位置并处理权限
|
||
const location = await getLocationWithPermission()
|
||
```
|
||
|
||
### 数据模型
|
||
```javascript
|
||
// 位置信息模型
|
||
interface LocationInfo {
|
||
latitude: number
|
||
longitude: number
|
||
accuracy: number
|
||
altitude: number
|
||
speed: number
|
||
timestamp: number
|
||
}
|
||
|
||
// 权限状态
|
||
type PermissionStatus = true | false | undefined
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 字典组件 (Dict)
|
||
|
||
### 功能描述
|
||
数据字典管理组件,提供统一的字典数据获取和管理功能。
|
||
|
||
### 入参
|
||
```javascript
|
||
// 获取单个字典数据
|
||
getDictData(type: string)
|
||
|
||
// 批量获取字典数据
|
||
getMultipleDictData(types: string[])
|
||
|
||
// 根据值获取文本
|
||
getDictText(dictData: DictItem[], value: string)
|
||
|
||
// 根据文本获取值
|
||
getDictValue(dictData: DictItem[], text: string)
|
||
```
|
||
|
||
### 出参
|
||
```javascript
|
||
// 字典数据项
|
||
{
|
||
text: string, // 显示文本
|
||
value: string // 值
|
||
}
|
||
```
|
||
|
||
### 调用方式
|
||
```javascript
|
||
import { getDictData, DICT_TYPES, getDictText, getDictValue } from '../utils/dictUtils.js'
|
||
|
||
// 获取尾挂类型字典
|
||
const carBackTypes = await getDictData(DICT_TYPES.CAR_BACK_TYPE)
|
||
|
||
// 批量获取字典
|
||
const dicts = await getMultipleDictData([
|
||
DICT_TYPES.CAR_TYPE,
|
||
DICT_TYPES.COMPANY_TYPE
|
||
])
|
||
|
||
// 根据值获取文本
|
||
const text = getDictText(carBackTypes, 'flatbed')
|
||
|
||
// 根据文本获取值
|
||
const value = getDictValue(carBackTypes, '平板')
|
||
```
|
||
|
||
### 数据模型
|
||
```javascript
|
||
// 字典项模型
|
||
interface DictItem {
|
||
text: string
|
||
value: string
|
||
}
|
||
|
||
// 字典类型常量
|
||
const DICT_TYPES = {
|
||
CAR_TYPE: 'car_type',
|
||
COMPANY_TYPE: 'company_type',
|
||
CAR_STATUS: 'car_status',
|
||
DRIVER_STATUS: 'driver_status',
|
||
GUFEI_ORDER_STATUS: 'gufei_order_status',
|
||
CAR_BACK_TYPE: 'car_back_type',
|
||
CAR_PACKAGE_TYPE: 'car_package_type',
|
||
GPS_STATUS: 'gps_status'
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 加密组件 (Crypto)
|
||
|
||
### 功能描述
|
||
数据加密组件,提供AES加密功能用于密码加密。
|
||
|
||
### 入参
|
||
```javascript
|
||
aesEncrypt(word: string, keyWord?: string)
|
||
```
|
||
|
||
### 出参
|
||
```javascript
|
||
// 加密后的字符串
|
||
string
|
||
```
|
||
|
||
### 调用方式
|
||
```javascript
|
||
import { aesEncrypt } from '../utils/crypto.js'
|
||
|
||
// 加密密码
|
||
const encryptedPassword = aesEncrypt('123456', 'pigxpigxpigxpigx')
|
||
```
|
||
|
||
### 数据模型
|
||
```javascript
|
||
// 加密参数模型
|
||
interface EncryptOptions {
|
||
word: string // 要加密的内容
|
||
keyWord?: string // 加密密钥,默认: 'pigxpigxpigxpigx'
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. API组件 (API)
|
||
|
||
### 功能描述
|
||
API接口管理组件,统一管理所有后端接口调用。
|
||
|
||
### 入参
|
||
```javascript
|
||
// 认证API
|
||
authAPI.login(data: LoginData)
|
||
|
||
// 订单API
|
||
orderAPI.getWaitOrders(driverId: string)
|
||
orderAPI.createOrder(data: OrderData)
|
||
orderAPI.getTodayTotal()
|
||
|
||
// 车辆API
|
||
carAPI.getCarPage(params: CarPageParams)
|
||
|
||
// 司机API
|
||
driverAPI.getDriverInfo(userId: string)
|
||
|
||
// 文件API
|
||
fileAPI.upload(filePath: string, formData?: object)
|
||
|
||
// 字典API
|
||
dictAPI.getDictData(type: string)
|
||
```
|
||
|
||
### 出参
|
||
```javascript
|
||
// 标准API响应
|
||
{
|
||
statusCode: number,
|
||
data: object
|
||
}
|
||
```
|
||
|
||
### 调用方式
|
||
```javascript
|
||
import { authAPI, orderAPI, carAPI, driverAPI, fileAPI, dictAPI } from '../api/index.js'
|
||
|
||
// 登录
|
||
const loginResult = await authAPI.login({ username: 'user', password: 'pass' })
|
||
|
||
// 获取待完成车次
|
||
const orders = await orderAPI.getWaitOrders('driver123')
|
||
|
||
// 创建订单
|
||
const result = await orderAPI.createOrder(orderData)
|
||
|
||
// 获取今日统计
|
||
const stats = await orderAPI.getTodayTotal()
|
||
|
||
// 获取车辆数据
|
||
const cars = await carAPI.getCarPage({ current: 1, size: 10 })
|
||
|
||
// 获取司机信息
|
||
const driver = await driverAPI.getDriverInfo('user123')
|
||
|
||
// 上传文件
|
||
const uploadResult = await fileAPI.upload(filePath)
|
||
|
||
// 获取字典数据
|
||
const dictData = await dictAPI.getDictData('car_type')
|
||
```
|
||
|
||
### 数据模型
|
||
```javascript
|
||
// 登录数据模型
|
||
interface LoginData {
|
||
username: string
|
||
password: string
|
||
}
|
||
|
||
// 订单数据模型
|
||
interface OrderData {
|
||
driverId: string
|
||
carId: string
|
||
totalWeight: number
|
||
companyId: string
|
||
carBackType: string
|
||
gufeiType: string
|
||
gufeiPackage: string
|
||
localImg: string
|
||
longitude: string
|
||
latitude: string
|
||
}
|
||
|
||
// 车辆分页参数模型
|
||
interface CarPageParams {
|
||
current: number
|
||
size: number
|
||
driverId: string
|
||
companyId: string
|
||
}
|
||
|
||
// 今日统计模型
|
||
interface TodayStats {
|
||
count: number // 收货客户数
|
||
planWeight: number // 预计重量
|
||
realWeight: number // 实际重量
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 车辆表单组件 (CarForm)
|
||
|
||
### 功能描述
|
||
车辆信息录入表单组件,支持照片上传、位置获取和订单提交。
|
||
|
||
### 入参
|
||
```javascript
|
||
// 组件Props
|
||
{
|
||
visible: boolean, // 是否显示
|
||
carData: CarData, // 车辆数据
|
||
companyId: string // 供应商ID
|
||
}
|
||
```
|
||
|
||
### 出参
|
||
```javascript
|
||
// 事件
|
||
{
|
||
submit: (formData) => void, // 表单提交事件
|
||
refresh: () => void // 刷新事件
|
||
}
|
||
```
|
||
|
||
### 调用方式
|
||
```vue
|
||
<template>
|
||
<CarForm
|
||
v-model:visible="showCarForm"
|
||
:car-data="selectedCarData"
|
||
:company-id="scannedCompanyId"
|
||
@submit="handleCarFormSubmit"
|
||
@refresh="handleCarFormRefresh"
|
||
/>
|
||
</template>
|
||
|
||
<script>
|
||
import CarForm from '../components/CarForm.vue'
|
||
|
||
export default {
|
||
components: {
|
||
CarForm
|
||
},
|
||
data() {
|
||
return {
|
||
showCarForm: false,
|
||
selectedCarData: {
|
||
carNum: '',
|
||
carType: '',
|
||
id: '',
|
||
carWeight: '',
|
||
carVolume: ''
|
||
},
|
||
scannedCompanyId: ''
|
||
}
|
||
},
|
||
methods: {
|
||
handleCarFormSubmit(formData) {
|
||
console.log('表单提交:', formData)
|
||
},
|
||
handleCarFormRefresh() {
|
||
console.log('刷新数据')
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
```
|
||
|
||
### 数据模型
|
||
```javascript
|
||
// 车辆数据模型
|
||
interface CarData {
|
||
carNum: string // 车牌号
|
||
carType: string // 车辆类型
|
||
id: string // 车辆ID
|
||
carWeight: string // 车辆重量
|
||
carVolume: string // 车辆容积
|
||
}
|
||
|
||
// 表单数据模型
|
||
interface FormData {
|
||
carNum: string // 车牌号
|
||
carBackType: string // 尾挂类型
|
||
photos: string[] // 照片URL数组
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 使用示例
|
||
|
||
### 完整登录流程
|
||
```javascript
|
||
import { authAPI, driverAPI } from '../api/index.js'
|
||
import { saveUserInfo } from '../utils/auth.js'
|
||
import { aesEncrypt } from '../utils/crypto.js'
|
||
|
||
// 登录处理
|
||
const handleLogin = async (username, password) => {
|
||
try {
|
||
// 加密密码
|
||
const encryptedPassword = aesEncrypt(password)
|
||
|
||
// 调用登录API
|
||
const response = await authAPI.login({
|
||
username,
|
||
password: encryptedPassword
|
||
})
|
||
|
||
if (response.statusCode === 200) {
|
||
// 保存用户信息
|
||
const userInfo = {
|
||
isLogin: true,
|
||
token: response.data.access_token,
|
||
userId: response.data.userId,
|
||
username: username
|
||
}
|
||
|
||
saveUserInfo(userInfo)
|
||
|
||
// 检查是否为司机
|
||
const driverResponse = await driverAPI.getDriverInfo(userInfo.userId)
|
||
if (driverResponse.statusCode === 200) {
|
||
userInfo.isDriver = true
|
||
userInfo.driverInfo = driverResponse.data
|
||
saveUserInfo(userInfo)
|
||
}
|
||
|
||
return true
|
||
}
|
||
} catch (error) {
|
||
console.error('登录失败:', error)
|
||
return false
|
||
}
|
||
}
|
||
```
|
||
|
||
### 完整订单创建流程
|
||
```javascript
|
||
import { orderAPI, fileAPI } from '../api/index.js'
|
||
import { getLocationWithPermission } from '../utils/location.js'
|
||
import { getUserInfo } from '../utils/auth.js'
|
||
|
||
// 创建订单
|
||
const createOrder = async (formData, carData, companyId) => {
|
||
try {
|
||
// 获取位置
|
||
const location = await getLocationWithPermission()
|
||
|
||
// 获取司机信息
|
||
const userInfo = getUserInfo()
|
||
const driverInfo = userInfo.driverInfo.data
|
||
|
||
// 构建订单数据
|
||
const orderData = {
|
||
driverId: driverInfo.id,
|
||
carId: carData.id,
|
||
totalWeight: 1,
|
||
companyId: companyId,
|
||
carBackType: formData.carBackType,
|
||
gufeiType: '',
|
||
gufeiPackage: '',
|
||
localImg: formData.photos.join(','),
|
||
longitude: location.longitude.toString(),
|
||
latitude: location.latitude.toString()
|
||
}
|
||
|
||
// 提交订单
|
||
const response = await orderAPI.createOrder(orderData)
|
||
|
||
if (response.statusCode === 200) {
|
||
console.log('订单创建成功')
|
||
return true
|
||
}
|
||
} catch (error) {
|
||
console.error('订单创建失败:', error)
|
||
return false
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 错误处理
|
||
|
||
### 统一错误处理
|
||
```javascript
|
||
// 用户凭证过期处理
|
||
if (response.data && response.data.code === 1 && response.data.msg === "用户凭证已过期") {
|
||
wx.showModal({
|
||
title: '登录过期',
|
||
content: '您的登录已过期,请重新登录',
|
||
showCancel: false,
|
||
confirmText: '重新登录',
|
||
success: () => {
|
||
// 清除本地存储
|
||
wx.removeStorageSync('userInfo')
|
||
wx.removeStorageSync('isLogin')
|
||
wx.removeStorageSync('token')
|
||
|
||
// 跳转登录页
|
||
wx.navigateTo({
|
||
url: '/pages/login/index'
|
||
})
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
### 网络错误处理
|
||
```javascript
|
||
try {
|
||
const response = await api.getData()
|
||
// 处理成功响应
|
||
} catch (error) {
|
||
if (error.errMsg.includes('timeout')) {
|
||
wx.showToast({
|
||
title: '请求超时',
|
||
icon: 'none'
|
||
})
|
||
} else {
|
||
wx.showToast({
|
||
title: '网络错误',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 10. 调试功能
|
||
|
||
### 开发环境配置
|
||
```javascript
|
||
// 调试环境下的默认账号密码
|
||
if (process.env.NODE_ENV === 'development') {
|
||
loginForm.username = 'driver'
|
||
loginForm.password = '123456'
|
||
console.log('调试环境:已设置默认账号密码')
|
||
}
|
||
```
|
||
|
||
### 日志输出
|
||
```javascript
|
||
// 请求日志
|
||
console.log(`API请求成功: ${method} ${url}`, response)
|
||
|
||
// 调试信息
|
||
console.log('开始获取待完成车次数据,司机ID:', driverId)
|
||
console.log('今日统计API响应:', response)
|
||
console.log('获取位置成功:', location)
|
||
```
|
||
|
||
---
|
||
|
||
## 11. 性能优化
|
||
|
||
### 请求优化
|
||
- 统一请求超时设置
|
||
- 自动token注入
|
||
- 请求去重处理
|
||
|
||
### 缓存策略
|
||
- 用户信息本地存储
|
||
- 字典数据缓存
|
||
- 位置信息缓存
|
||
|
||
### 错误恢复
|
||
- 自动重试机制
|
||
- 降级处理
|
||
- 用户引导
|
||
|
||
---
|
||
|
||
## 12. 安全考虑
|
||
|
||
### 数据加密
|
||
- 密码AES加密
|
||
- 敏感信息保护
|
||
- 传输安全
|
||
|
||
### 权限控制
|
||
- 登录状态检查
|
||
- 角色权限验证
|
||
- 接口访问控制
|
||
|
||
### 数据验证
|
||
- 输入参数验证
|
||
- 响应数据校验
|
||
- 异常数据处理
|