UniApp跨平台深度实战:构建企业级智能巡检系统完整指南 | 移动开发进阶

2026-01-14 0 907
免费资源下载

项目背景:为什么选择UniApp开发企业级应用?

在数字化转型浪潮中,企业需要快速构建跨平台移动应用。传统原生开发成本高、周期长,而UniApp凭借”一次开发,多端发布”的优势,成为企业移动化转型的首选方案。本教程将通过一个完整的智能巡检系统案例,深入讲解UniApp在企业级应用开发中的高级实践。

第一部分:项目架构设计

1.1 系统功能模块

  • 巡检任务管理:任务分配、进度跟踪、异常上报
  • 设备二维码识别:扫码快速获取设备信息
  • 离线数据同步:无网络环境下的数据采集与同步
  • 多媒体记录:拍照、录音、视频录制
  • 实时定位:GPS轨迹记录与电子围栏
  • 数据可视化:巡检数据统计与分析

1.2 项目目录结构设计

smart-inspection/
├── pages/                    # 页面文件
│   ├── login/               # 登录页
│   ├── home/                # 首页
│   ├── task/                # 任务相关页
│   │   ├── list.vue         # 任务列表
│   │   ├── detail.vue       # 任务详情
│   │   └── execute.vue      # 任务执行
│   ├── device/              # 设备管理
│   ├── statistics/          # 统计分析
│   └── profile/             # 个人中心
├── components/              # 公共组件
│   ├── inspection-card/     # 巡检卡片
│   ├── media-uploader/      # 多媒体上传
│   ├── offline-manager/     # 离线管理
│   └── map-tracker/         # 地图轨迹
├── store/                   # Vuex状态管理
│   ├── modules/
│   │   ├── task.js          # 任务模块
│   │   ├── device.js        # 设备模块
│   │   └── user.js          # 用户模块
│   └── index.js
├── api/                     # 接口管理
│   ├── task.js
│   ├── device.js
│   └── upload.js
├── utils/                   # 工具函数
│   ├── storage.js          # 本地存储
│   ├── validator.js        # 表单验证
│   ├── qrcode.js           # 二维码处理
│   └── location.js         # 定位工具
├── static/                  # 静态资源
├── uni_modules/            # 第三方模块
└── manifest.json           # 应用配置

第二部分:核心功能实现

2.1 离线数据管理策略

// utils/offline-manager.js
class OfflineManager {
    constructor() {
        this.dbName = 'inspection_db'
        this.storeName = 'offline_data'
        this.initDB()
    }

    // 初始化IndexedDB
    async initDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open(this.dbName, 1)
            
            request.onupgradeneeded = (event) => {
                const db = event.target.result
                if (!db.objectStoreNames.contains(this.storeName)) {
                    const store = db.createObjectStore(this.storeName, {
                        keyPath: 'id',
                        autoIncrement: true
                    })
                    store.createIndex('sync_status', 'sync_status', { unique: false })
                    store.createIndex('created_at', 'created_at', { unique: false })
                }
            }
            
            request.onsuccess = () => resolve(request.result)
            request.onerror = () => reject(request.error)
        })
    }

    // 保存离线数据
    async saveOfflineData(data) {
        const db = await this.initDB()
        return new Promise((resolve, reject) => {
            const transaction = db.transaction([this.storeName], 'readwrite')
            const store = transaction.objectStore(this.storeName)
            const request = store.add({
                ...data,
                sync_status: 'pending',
                created_at: new Date().getTime(),
                updated_at: new Date().getTime()
            })
            
            request.onsuccess = () => resolve(request.result)
            request.onerror = () => reject(request.error)
        })
    }

    // 同步数据到服务器
    async syncToServer() {
        const pendingData = await this.getPendingData()
        const results = []
        
        for (const item of pendingData) {
            try {
                // 调用API同步
                const response = await uni.request({
                    url: '/api/inspection/sync',
                    method: 'POST',
                    data: item.data
                })
                
                if (response.statusCode === 200) {
                    await this.markAsSynced(item.id)
                    results.push({ id: item.id, success: true })
                }
            } catch (error) {
                console.error('同步失败:', error)
                results.push({ id: item.id, success: false, error })
            }
        }
        
        return results
    }

    // 获取待同步数据
    async getPendingData() {
        const db = await this.initDB()
        return new Promise((resolve, reject) => {
            const transaction = db.transaction([this.storeName], 'readonly')
            const store = transaction.objectStore(this.storeName)
            const index = store.index('sync_status')
            const request = index.getAll('pending')
            
            request.onsuccess = () => resolve(request.result)
            request.onerror = () => reject(request.error)
        })
    }
}

export default new OfflineManager()

2.2 智能巡检任务组件



    
        
            
                #{{ task.task_number }}
                {{ task.name }}
            
            
                
            
        
        
        
            
            
                
                {{ task.device_name }}
                ({{ task.device_code }})
            
            
            
            
                
                    {{ item.name }}
                    
                        
                    
                
            
            
            
            
                现场记录
                
            
            
            
            
                
                
            
        
        
        
        
            {{ statusText[task.status] }}
        
    



export default {
    name: 'InspectionCard',
    props: {
        task: {
            type: Object,
            required: true,
            default: () => ({})
        }
    },
    data() {
        return {
            expanded: false,
            statusText: {
                pending: '待执行',
                processing: '进行中',
                completed: '已完成',
                exception: '异常'
            }
        }
    },
    computed: {
        canSubmit() {
            // 检查所有巡检项是否已完成
            return this.task.items.every(item => item.value !== undefined)
        }
    },
    methods: {
        toggleExpand() {
            this.expanded = !this.expanded
        },
        
        handleItemSelect(item, value) {
            this.$emit('item-change', {
                itemId: item.id,
                value: value
            })
        },
        
        async handleSubmit() {
            try {
                // 检查网络状态
                const networkType = await this.checkNetwork()
                
                if (networkType === 'none') {
                    // 离线保存
                    await this.saveOffline()
                    uni.showToast({
                        title: '已保存到本地,网络恢复后自动同步',
                        icon: 'success'
                    })
                } else {
                    // 在线提交
                    await this.submitOnline()
                    uni.showToast({
                        title: '提交成功',
                        icon: 'success'
                    })
                }
                
                this.$emit('submit-success')
            } catch (error) {
                uni.showToast({
                    title: '提交失败',
                    icon: 'error'
                })
            }
        },
        
        handleException() {
            uni.navigateTo({
                url: `/pages/exception/report?taskId=${this.task.id}`
            })
        },
        
        handleMediaUpload(files) {
            this.$emit('media-upload', files)
        }
    }
}

2.3 二维码扫描与设备识别

// pages/device/scan.vue

export default {
    data() {
        return {
            scanResult: null,
            deviceInfo: null,
            scanHistory: []
        }
    },
    
    methods: {
        // 启动扫码
        async startScan() {
            try {
                // 检查相机权限
                const authStatus = await this.checkCameraPermission()
                if (!authStatus) {
                    await this.requestCameraPermission()
                }
                
                // 调用扫码功能
                const result = await uni.scanCode({
                    scanType: ['qrCode'],
                    success: (res) => {
                        this.scanResult = res.result
                        this.processQRCode(res.result)
                    }
                })
                
            } catch (error) {
                console.error('扫码失败:', error)
                uni.showToast({
                    title: '扫码失败,请重试',
                    icon: 'none'
                })
            }
        },
        
        // 处理二维码内容
        async processQRCode(qrContent) {
            try {
                // 解析二维码内容(支持多种格式)
                let deviceCode = ''
                
                if (qrContent.startsWith('device://')) {
                    // 自定义协议格式
                    deviceCode = qrContent.replace('device://', '')
                } else if (qrContent.includes('device_id=')) {
                    // URL参数格式
                    const params = new URLSearchParams(qrContent.split('?')[1])
                    deviceCode = params.get('device_id')
                } else {
                    // 直接设备编码
                    deviceCode = qrContent
                }
                
                // 获取设备信息
                await this.fetchDeviceInfo(deviceCode)
                
                // 记录扫描历史
                this.recordScanHistory(deviceCode)
                
            } catch (error) {
                console.error('解析失败:', error)
            }
        },
        
        // 获取设备详细信息
        async fetchDeviceInfo(deviceCode) {
            // 先尝试从本地缓存获取
            const cachedDevice = this.getCachedDevice(deviceCode)
            if (cachedDevice) {
                this.deviceInfo = cachedDevice
                return
            }
            
            // 从服务器获取
            try {
                const response = await uni.request({
                    url: `/api/device/${deviceCode}/info`,
                    method: 'GET'
                })
                
                if (response.data.code === 200) {
                    this.deviceInfo = response.data.data
                    // 缓存设备信息
                    this.cacheDeviceInfo(response.data.data)
                    
                    // 跳转到设备详情页
                    uni.navigateTo({
                        url: `/pages/device/detail?id=${deviceCode}`
                    })
                }
            } catch (error) {
                // 网络异常时使用离线数据
                const offlineInfo = await this.getOfflineDeviceInfo(deviceCode)
                if (offlineInfo) {
                    this.deviceInfo = offlineInfo
                    uni.showModal({
                        title: '离线模式',
                        content: '当前为离线模式,显示上次缓存的数据',
                        showCancel: false
                    })
                }
            }
        },
        
        // 批量扫码功能
        async batchScan() {
            this.scanHistory = []
            let continueScan = true
            
            while (continueScan) {
                const result = await new Promise((resolve) => {
                    uni.showModal({
                        title: '批量扫码',
                        content: '请扫描下一个设备二维码',
                        confirmText: '继续扫描',
                        cancelText: '完成',
                        success: (res) => {
                            if (res.confirm) {
                                this.startScan().then(resolve)
                            } else {
                                continueScan = false
                                resolve(null)
                            }
                        }
                    })
                })
                
                if (result) {
                    this.scanHistory.push(result)
                }
            }
            
            // 批量处理扫描结果
            await this.processBatchScan()
        }
    }
}

第三部分:高级功能实现

3.1 实时定位与电子围栏

// utils/location-tracker.js
class LocationTracker {
    constructor() {
        this.watchId = null
        this.trackPoints = []
        this.geofences = []
        this.isTracking = false
    }
    
    // 开始轨迹记录
    startTracking(taskId) {
        return new Promise((resolve, reject) => {
            if (this.isTracking) {
                reject(new Error('已经在轨迹记录中'))
                return
            }
            
            // 获取当前位置
            uni.getLocation({
                type: 'wgs84',
                success: (res) => {
                    this.trackPoints = [{
                        latitude: res.latitude,
                        longitude: res.longitude,
                        timestamp: Date.now(),
                        taskId: taskId
                    }]
                    
                    // 开始监听位置变化
                    this.watchId = uni.onLocationChange((res) => {
                        if (res.latitude && res.longitude) {
                            this.addTrackPoint(res, taskId)
                            this.checkGeofence(res)
                        }
                    })
                    
                    this.isTracking = true
                    resolve()
                },
                fail: reject
            })
        })
    }
    
    // 添加轨迹点
    addTrackPoint(location, taskId) {
        const point = {
            latitude: location.latitude,
            longitude: location.longitude,
            timestamp: Date.now(),
            taskId: taskId,
            accuracy: location.accuracy || 0
        }
        
        this.trackPoints.push(point)
        
        // 限制轨迹点数量,避免内存溢出
        if (this.trackPoints.length > 1000) {
            this.trackPoints = this.trackPoints.slice(-500)
        }
        
        // 保存到本地
        this.saveToLocal(point)
    }
    
    // 电子围栏检测
    checkGeofence(currentLocation) {
        this.geofences.forEach(fence => {
            const distance = this.calculateDistance(
                currentLocation.latitude,
                currentLocation.longitude,
                fence.latitude,
                fence.longitude
            )
            
            if (distance <= fence.radius) {
                // 进入电子围栏区域
                if (!fence.entered) {
                    fence.entered = true
                    this.triggerGeofenceEvent('enter', fence)
                }
            } else {
                // 离开电子围栏区域
                if (fence.entered) {
                    fence.entered = false
                    this.triggerGeofenceEvent('exit', fence)
                }
            }
        })
    }
    
    // 计算两点间距离(米)
    calculateDistance(lat1, lon1, lat2, lon2) {
        const R = 6371000 // 地球半径(米)
        const dLat = this.toRad(lat2 - lat1)
        const dLon = this.toRad(lon2 - lon1)
        
        const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                  Math.cos(this.toRad(lat1)) * Math.cos(this.toRad(lat2)) *
                  Math.sin(dLon/2) * Math.sin(dLon/2)
        
        const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
        return R * c
    }
    
    // 停止轨迹记录
    stopTracking() {
        if (this.watchId) {
            uni.offLocationChange(this.watchId)
            this.watchId = null
        }
        
        this.isTracking = false
        
        // 生成轨迹报告
        return this.generateTrackReport()
    }
    
    // 生成轨迹报告
    generateTrackReport() {
        if (this.trackPoints.length === 0) {
            return null
        }
        
        const report = {
            startTime: this.trackPoints[0].timestamp,
            endTime: this.trackPoints[this.trackPoints.length - 1].timestamp,
            totalPoints: this.trackPoints.length,
            totalDistance: this.calculateTotalDistance(),
            averageSpeed: this.calculateAverageSpeed(),
            points: this.trackPoints
        }
        
        return report
    }
}

export default new LocationTracker()

3.2 多端适配与性能优化

// utils/platform-adapter.js
class PlatformAdapter {
    // 获取平台特定配置
    getPlatformConfig() {
        const platform = uni.getSystemInfoSync().platform
        
        const configs = {
            // 微信小程序配置
            'mp-weixin': {
                storageKey: 'wx_inspection_data',
                uploadMaxSize: 10 * 1024 * 1024, // 10MB
                canUseCamera: true,
                canUseLocation: true,
                supportBackgroundAudio: true
            },
            // H5配置
            'h5': {
                storageKey: 'h5_inspection_data',
                uploadMaxSize: 20 * 1024 * 1024, // 20MB
                canUseCamera: navigator.mediaDevices !== undefined,
                canUseLocation: navigator.geolocation !== undefined,
                supportBackgroundAudio: false
            },
            // App配置
            'app': {
                storageKey: 'app_inspection_data',
                uploadMaxSize: 50 * 1024 * 1024, // 50MB
                canUseCamera: true,
                canUseLocation: true,
                supportBackgroundAudio: true,
                canUseNativeFeatures: true
            }
        }
        
        return configs[platform] || configs['h5']
    }
    
    // 平台特定的文件上传
    async platformUpload(file, options = {}) {
        const platform = uni.getSystemInfoSync().platform
        const config = this.getPlatformConfig()
        
        // 检查文件大小
        if (file.size > config.uploadMaxSize) {
            throw new Error(`文件大小不能超过${config.uploadMaxSize / 1024 / 1024}MB`)
        }
        
        switch (platform) {
            case 'mp-weixin':
                return this.weixinUpload(file, options)
            case 'app':
                return this.appUpload(file, options)
            default:
                return this.h5Upload(file, options)
        }
    }
    
    // 微信小程序上传
    async weixinUpload(file, options) {
        return new Promise((resolve, reject) => {
            uni.uploadFile({
                url: options.url,
                filePath: file.path,
                name: 'file',
                formData: options.formData,
                success: resolve,
                fail: reject
            })
        })
    }
    
    // 性能监控
    setupPerformanceMonitor() {
        // 页面加载性能
        uni.onAppRoute((route) => {
            const startTime = Date.now()
            
            route.onReady = () => {
                const loadTime = Date.now() - startTime
                this.reportPerformance('page_load', {
                    page: route.path,
                    loadTime: loadTime
                })
            }
        })
        
        // 内存监控
        if (uni.getSystemInfoSync().platform === 'app') {
            setInterval(() => {
                const memory = this.getMemoryUsage()
                if (memory > 80) {
                    this.triggerMemoryWarning()
                }
            }, 30000)
        }
    }
    
    // 图片压缩(平台特定)
    async compressImage(file, platform) {
        if (platform === 'mp-weixin') {
            // 微信小程序压缩
            return new Promise((resolve) => {
                wx.compressImage({
                    src: file.path,
                    quality: 80,
                    success: resolve
                })
            })
        } else if (platform === 'app') {
            // App端使用原生压缩
            return uni.compressImage({
                src: file.path,
                quality: 80,
                compressedWidth: 1200,
                compressedHeight: 1200
            })
        } else {
            // H5使用canvas压缩
            return this.h5CompressImage(file)
        }
    }
}

export default new PlatformAdapter()

第四部分:打包部署与优化

4.1 多端发布配置

// manifest.json 关键配置
{
    "name": "智能巡检系统",
    "appid": "__UNI__XXXXXX",
    "description": "企业级智能巡检解决方案",
    
    /* 小程序配置 */
    "mp-weixin": {
        "appid": "wx1234567890",
        "setting": {
            "urlCheck": false,
            "es6": true,
            "postcss": true,
            "minified": true
        },
        "usingComponents": true,
        "permission": {
            "scope.userLocation": {
                "desc": "用于记录巡检轨迹和位置签到"
            }
        },
        "requiredPrivateInfos": ["getLocation", "chooseLocation"]
    },
    
    /* App配置 */
    "app": {
        "distribute": {
            "android": {
                "permissions": [
                    "",
                    "",
                    ""
                ],
                "abiFilters": ["armeabi-v7a", "arm64-v8a"]
            },
            "ios": {
                "UIRequiresFullScreen": false,
                "privacyDescription": {
                    "NSLocationWhenInUseUsageDescription": "用于记录巡检轨迹",
                    "NSCameraUsageDescription": "用于拍摄设备照片",
                    "NSMicrophoneUsageDescription": "用于录制现场语音"
                }
            }
        }
    },
    
    /* H5配置 */
    "h5": {
        "title": "智能巡检系统",
        "router": {
            "mode": "hash"
        },
        "publicPath": "./",
        "template": "template.h5.html",
        "optimization": {
            "treeShaking": {
                "enable": true
            }
        }
    }
}

4.2 性能优化策略

  • 代码分割:使用uni-app的分包加载机制
  • 图片优化:实现懒加载和WebP格式支持
  • 数据缓存:合理使用本地存储和内存缓存
  • 请求合并:批量处理API请求减少网络开销
  • 组件异步加载:使用defineAsyncComponent延迟加载
  • 渲染优化:避免不必要的重新渲染

总结与展望

通过本实战教程,我们完整构建了一个企业级智能巡检系统,涵盖了从项目架构设计到具体功能实现的全过程。关键收获:

  1. 架构设计:合理的目录结构和模块划分是项目成功的基础
  2. 离线能力:IndexedDB和本地存储保障了无网络环境下的可用性
  3. 多端适配:平台适配器模式有效解决了多端差异问题
  4. 性能优化:从代码层面到运行时的全方位优化策略
  5. 可维护性:组件化开发和状态管理提升了代码质量

UniApp在企业级应用开发中展现出强大的生产力,结合Vue3的Composition API和TypeScript,可以构建出更加健壮和可维护的跨平台应用。

// 交互增强脚本
document.addEventListener(‘DOMContentLoaded’, function() {
// 代码块语法高亮和复制功能
const codeBlocks = document.querySelectorAll(‘pre code’);
codeBlocks.forEach(block => {
// 添加复制按钮
const copyBtn = document.createElement(‘button’);
copyBtn.textContent = ‘复制’;
copyBtn.className = ‘copy-btn’;
copyBtn.onclick = function() {
navigator.clipboard.writeText(block.textContent).then(() => {
const original = copyBtn.textContent;
copyBtn.textContent = ‘已复制’;
setTimeout(() => {
copyBtn.textContent = original;
}, 2000);
});
};

const pre = block.parentElement;
pre.style.position = ‘relative’;
pre.appendChild(copyBtn);
});

// 平台切换演示
const platformDemo = document.createElement(‘div’);
platformDemo.innerHTML = `

平台适配演示

`;
document.querySelector(‘.feature’).appendChild(platformDemo);
});

function showPlatformInfo() {
const info = {
userAgent: navigator.userAgent,
platform: navigator.platform,
isWechat: /MicroMessenger/i.test(navigator.userAgent),
isMobile: /Mobile/i.test(navigator.userAgent)
};

document.getElementById(‘platformInfo’).innerHTML = `

${JSON.stringify(info, null, 2)}

`;
}

UniApp跨平台深度实战:构建企业级智能巡检系统完整指南 | 移动开发进阶
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 uniapp UniApp跨平台深度实战:构建企业级智能巡检系统完整指南 | 移动开发进阶 https://www.taomawang.com/web/uniapp/1532.html

常见问题

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务