19 KiB
19 KiB
小程序架构文档
版本历史
| 版本 | 日期 | 作者 | 变更说明 |
|---|---|---|---|
| 1.0 | 2024-01-20 | 前端团队 | 初始版本 |
1. 小程序架构概述
1.1 项目背景
本小程序是养殖管理平台的移动端应用,主要面向养殖户和经销商,提供养殖管理、交易管理、数据查看等核心功能。
1.2 架构目标
- 用户体验:流畅的交互体验和快速的页面响应
- 性能优化:小程序包体积控制和运行性能优化
- 可维护性:清晰的代码结构和组件化开发
- 扩展性:支持功能模块的快速扩展
- 稳定性:异常处理和容错机制完善
1.3 技术栈
- 开发框架:微信小程序原生开发
- 开发语言:TypeScript + JavaScript
- UI框架:WeUI + 自定义组件
- 状态管理:MobX + 本地存储
- 网络请求:wx.request + 请求封装
- 图表组件:ECharts for 微信小程序
- 地图服务:腾讯地图 + 微信地图
2. 系统架构设计
2.1 整体架构
┌─────────────────────────────────────────────────────────────┐
│ 视图层 (View) │
│ Pages + Components │
├─────────────────────────────────────────────────────────────┤
│ 逻辑层 (Logic) │
│ Service + Store + Utils │
├─────────────────────────────────────────────────────────────┤
│ 数据层 (Data) │
│ API + Storage + Cache │
├─────────────────────────────────────────────────────────────┤
│ 微信小程序框架 │
│ WeChat Mini Program │
└─────────────────────────────────────────────────────────────┘
2.2 目录结构
mini-program/
├── pages/ # 页面目录
│ ├── index/ # 首页
│ ├── farm/ # 养殖管理
│ ├── trade/ # 交易管理
│ ├── profile/ # 个人中心
│ └── ...
├── components/ # 组件目录
│ ├── common/ # 通用组件
│ ├── business/ # 业务组件
│ └── charts/ # 图表组件
├── services/ # 服务层
│ ├── api/ # API接口
│ ├── auth/ # 认证服务
│ └── storage/ # 存储服务
├── stores/ # 状态管理
│ ├── user.ts # 用户状态
│ ├── farm.ts # 养殖状态
│ └── trade.ts # 交易状态
├── utils/ # 工具函数
│ ├── request.ts # 网络请求
│ ├── validator.ts # 数据验证
│ └── formatter.ts # 数据格式化
├── styles/ # 样式文件
│ ├── common.wxss # 通用样式
│ └── variables.wxss # 样式变量
├── static/ # 静态资源
│ ├── images/ # 图片资源
│ └── icons/ # 图标资源
├── app.ts # 应用入口
├── app.json # 应用配置
├── app.wxss # 全局样式
└── project.config.json # 项目配置
3. 核心模块设计
3.1 用户认证模块
功能: 微信授权登录、用户信息管理、权限控制
核心组件:
- 登录页面: 微信授权登录界面
- 用户信息: 用户资料展示和编辑
- 权限管理: 基于角色的功能权限控制
实现方案:
// 用户认证服务
class AuthService {
// 微信登录
async wxLogin(): Promise<LoginResult> {
const { code } = await wx.login();
const { userInfo } = await wx.getUserProfile({
desc: '用于完善用户资料'
});
return this.apiLogin(code, userInfo);
}
// API登录
async apiLogin(code: string, userInfo: any): Promise<LoginResult> {
const response = await request.post('/auth/wx-login', {
code,
userInfo
});
if (response.success) {
await this.setToken(response.data.token);
await this.setUserInfo(response.data.user);
}
return response;
}
}
3.2 养殖管理模块
功能: 养殖场管理、动物管理、数据统计
核心页面:
- 养殖场列表: 展示用户的养殖场信息
- 养殖场详情: 养殖场详细信息和管理功能
- 动物管理: 动物档案、健康记录、生长数据
- 数据统计: 养殖数据图表和分析报告
状态管理:
// 养殖状态管理
class FarmStore {
@observable farms: Farm[] = [];
@observable currentFarm: Farm | null = null;
@observable animals: Animal[] = [];
@action
async loadFarms() {
const response = await farmService.getFarms();
if (response.success) {
this.farms = response.data;
}
}
@action
async selectFarm(farmId: string) {
const farm = this.farms.find(f => f.id === farmId);
this.currentFarm = farm || null;
if (farm) {
await this.loadAnimals(farmId);
}
}
}
3.3 交易管理模块
功能: 订单管理、支付管理、物流跟踪
核心页面:
- 商品列表: 展示可交易的商品信息
- 订单管理: 订单创建、查看、状态跟踪
- 支付页面: 微信支付集成
- 物流跟踪: 订单物流信息查看
支付集成:
// 支付服务
class PaymentService {
async wxPay(orderId: string): Promise<PaymentResult> {
// 1. 获取支付参数
const payParams = await this.getPayParams(orderId);
// 2. 调起微信支付
return new Promise((resolve, reject) => {
wx.requestPayment({
...payParams,
success: (res) => {
resolve({ success: true, data: res });
},
fail: (err) => {
reject({ success: false, error: err });
}
});
});
}
}
3.4 数据可视化模块
功能: 图表展示、数据分析、报表生成
图表组件:
- 折线图: 展示趋势数据
- 柱状图: 展示对比数据
- 饼图: 展示占比数据
- 仪表盘: 展示关键指标
ECharts集成:
// 图表组件
Component({
properties: {
chartData: Object,
chartType: String
},
data: {
ec: null
},
ready() {
this.initChart();
},
methods: {
initChart() {
this.createSelectorQuery()
.select('#chart')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext('2d');
canvas.width = res[0].width * dpr;
canvas.height = res[0].height * dpr;
ctx.scale(dpr, dpr);
echarts.setCanvasCreator(() => canvas);
const chart = echarts.init(canvas, null, {
width: res[0].width,
height: res[0].height,
devicePixelRatio: dpr
});
chart.setOption(this.getChartOption());
this.setData({ ec: { chart } });
});
}
}
});
4. 网络层设计
4.1 请求封装
// 网络请求封装
class RequestService {
private baseURL = 'https://api.example.com';
private timeout = 10000;
async request(options: RequestOptions): Promise<ApiResponse> {
const token = await storage.getToken();
return new Promise((resolve, reject) => {
wx.request({
url: `${this.baseURL}${options.url}`,
method: options.method || 'GET',
data: options.data,
header: {
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token}` : '',
...options.header
},
timeout: this.timeout,
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data);
} else {
this.handleError(res);
reject(res);
}
},
fail: (err) => {
this.handleError(err);
reject(err);
}
});
});
}
private handleError(error: any) {
console.error('Request error:', error);
// 统一错误处理
if (error.statusCode === 401) {
// Token过期,跳转登录
this.redirectToLogin();
} else if (error.statusCode >= 500) {
// 服务器错误
wx.showToast({
title: '服务器错误,请稍后重试',
icon: 'none'
});
}
}
}
4.2 API接口管理
// API接口定义
class ApiService {
// 用户相关接口
user = {
login: (data: LoginData) => request.post('/auth/login', data),
profile: () => request.get('/user/profile'),
updateProfile: (data: UserProfile) => request.put('/user/profile', data)
};
// 养殖相关接口
farm = {
list: (params: FarmListParams) => request.get('/farms', params),
detail: (id: string) => request.get(`/farms/${id}`),
create: (data: FarmData) => request.post('/farms', data),
update: (id: string, data: FarmData) => request.put(`/farms/${id}`, data)
};
// 交易相关接口
trade = {
orders: (params: OrderListParams) => request.get('/orders', params),
createOrder: (data: OrderData) => request.post('/orders', data),
payOrder: (orderId: string) => request.post(`/orders/${orderId}/pay`)
};
}
5. 数据存储设计
5.1 本地存储策略
// 存储服务
class StorageService {
// 同步存储
setSync(key: string, value: any): void {
try {
wx.setStorageSync(key, JSON.stringify(value));
} catch (error) {
console.error('Storage set error:', error);
}
}
getSync(key: string): any {
try {
const value = wx.getStorageSync(key);
return value ? JSON.parse(value) : null;
} catch (error) {
console.error('Storage get error:', error);
return null;
}
}
// 异步存储
async set(key: string, value: any): Promise<void> {
return new Promise((resolve, reject) => {
wx.setStorage({
key,
data: JSON.stringify(value),
success: resolve,
fail: reject
});
});
}
async get(key: string): Promise<any> {
return new Promise((resolve, reject) => {
wx.getStorage({
key,
success: (res) => {
try {
resolve(JSON.parse(res.data));
} catch (error) {
resolve(res.data);
}
},
fail: () => resolve(null)
});
});
}
}
5.2 缓存管理
// 缓存管理
class CacheService {
private cache = new Map<string, CacheItem>();
private defaultTTL = 5 * 60 * 1000; // 5分钟
set(key: string, value: any, ttl?: number): void {
const expireTime = Date.now() + (ttl || this.defaultTTL);
this.cache.set(key, {
value,
expireTime
});
}
get(key: string): any {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() > item.expireTime) {
this.cache.delete(key);
return null;
}
return item.value;
}
clear(): void {
this.cache.clear();
}
}
6. 组件化设计
6.1 通用组件
// 列表组件
Component({
properties: {
items: Array,
loading: Boolean,
hasMore: Boolean
},
data: {
refreshing: false
},
methods: {
onRefresh() {
this.setData({ refreshing: true });
this.triggerEvent('refresh');
},
onLoadMore() {
if (!this.data.loading && this.data.hasMore) {
this.triggerEvent('loadmore');
}
},
onItemTap(e: any) {
const { item, index } = e.currentTarget.dataset;
this.triggerEvent('itemtap', { item, index });
}
}
});
6.2 业务组件
// 养殖场卡片组件
Component({
properties: {
farm: Object
},
methods: {
onTap() {
const { farm } = this.properties;
wx.navigateTo({
url: `/pages/farm/detail?id=${farm.id}`
});
},
onEdit() {
const { farm } = this.properties;
this.triggerEvent('edit', { farm });
}
}
});
7. 性能优化
7.1 包体积优化
- 代码分包: 使用小程序分包加载
- 图片优化: 使用WebP格式,压缩图片大小
- 代码压缩: 启用代码压缩和混淆
- 按需加载: 组件和页面按需加载
7.2 运行时优化
- 数据预加载: 关键数据提前加载
- 图片懒加载: 长列表图片懒加载
- 防抖节流: 频繁操作防抖节流处理
- 内存管理: 及时清理不用的数据和监听器
7.3 渲染优化
// 长列表优化
Component({
data: {
visibleItems: [],
scrollTop: 0
},
methods: {
onScroll(e: any) {
const { scrollTop } = e.detail;
this.updateVisibleItems(scrollTop);
},
updateVisibleItems(scrollTop: number) {
const itemHeight = 100;
const containerHeight = 600;
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = startIndex + Math.ceil(containerHeight / itemHeight) + 1;
const visibleItems = this.data.allItems.slice(startIndex, endIndex);
this.setData({ visibleItems });
}
}
});
8. 错误处理
8.1 全局错误处理
// 应用级错误处理
App({
onError(error: string) {
console.error('App Error:', error);
// 错误上报
this.reportError(error);
// 用户提示
wx.showToast({
title: '程序出现异常',
icon: 'none'
});
},
onUnhandledRejection(res: any) {
console.error('Unhandled Promise Rejection:', res);
this.reportError(res.reason);
},
reportError(error: any) {
// 上报错误到服务器
wx.request({
url: 'https://api.example.com/errors',
method: 'POST',
data: {
error: error.toString(),
stack: error.stack,
timestamp: Date.now(),
userAgent: wx.getSystemInfoSync()
}
});
}
});
8.2 页面级错误处理
// 页面错误处理
Page({
data: {
error: null,
loading: false
},
async onLoad() {
try {
this.setData({ loading: true });
await this.loadData();
} catch (error) {
this.handleError(error);
} finally {
this.setData({ loading: false });
}
},
handleError(error: any) {
console.error('Page Error:', error);
this.setData({
error: {
message: error.message || '加载失败',
code: error.code
}
});
},
onRetry() {
this.setData({ error: null });
this.onLoad();
}
});
9. 安全设计
9.1 数据安全
- 敏感数据加密: 本地存储敏感数据加密
- 传输安全: HTTPS传输,防止中间人攻击
- 输入验证: 严格验证用户输入数据
9.2 权限控制
// 权限检查
class PermissionService {
async checkPermission(permission: string): Promise<boolean> {
const userInfo = await storage.get('userInfo');
if (!userInfo || !userInfo.permissions) {
return false;
}
return userInfo.permissions.includes(permission);
}
async requirePermission(permission: string): Promise<void> {
const hasPermission = await this.checkPermission(permission);
if (!hasPermission) {
throw new Error('权限不足');
}
}
}
10. 测试策略
10.1 单元测试
// 工具函数测试
describe('Validator', () => {
test('should validate phone number', () => {
expect(validator.isPhone('13800138000')).toBe(true);
expect(validator.isPhone('1380013800')).toBe(false);
});
test('should validate email', () => {
expect(validator.isEmail('test@example.com')).toBe(true);
expect(validator.isEmail('invalid-email')).toBe(false);
});
});
10.2 集成测试
- API测试: 测试与后端API的集成
- 支付测试: 测试微信支付流程
- 授权测试: 测试微信授权登录
10.3 用户体验测试
- 真机测试: 在不同设备上测试
- 网络测试: 测试不同网络环境下的表现
- 性能测试: 测试页面加载和响应性能
11. 发布与运维
11.1 版本管理
- 版本号规范: 遵循语义化版本号
- 发布流程: 开发 → 测试 → 预发布 → 正式发布
- 回滚机制: 支持快速回滚到上一版本
11.2 监控告警
- 性能监控: 监控页面加载时间和API响应时间
- 错误监控: 监控JavaScript错误和API错误
- 用户行为: 统计用户使用行为和路径
11.3 数据统计
// 埋点统计
class AnalyticsService {
track(event: string, properties?: any) {
const data = {
event,
properties: {
...properties,
timestamp: Date.now(),
page: getCurrentPages().pop()?.route
}
};
// 发送统计数据
wx.request({
url: 'https://analytics.example.com/track',
method: 'POST',
data
});
}
trackPageView(page: string) {
this.track('page_view', { page });
}
trackUserAction(action: string, target?: string) {
this.track('user_action', { action, target });
}
}
12. 扩展性设计
12.1 插件化架构
- 功能模块: 支持功能模块的插拔
- 主题系统: 支持多主题切换
- 配置化: 支持功能开关配置
12.2 多端适配
- 响应式设计: 适配不同屏幕尺寸
- 平台兼容: 兼容不同版本的微信客户端
- 设备适配: 适配不同性能的设备
13. 未来规划
13.1 技术升级
- 框架升级: 考虑使用Taro等跨端框架
- TypeScript: 全面使用TypeScript开发
- 组件库: 构建统一的组件库
13.2 功能扩展
- 离线功能: 支持离线数据查看
- 实时通信: 集成WebSocket实时通信
- AI功能: 集成AI智能分析功能