HarmonyOS 6.0+ APP智能快递代收管理系统开发实战:定位追踪与取件提醒落地

一、引言

在当前快递代收场景中,普遍存在管理流程混乱、快递堆放无序、用户取件耗时久、取件提醒不及时、快递状态不透明等痛点,不仅增加了代收点工作人员的管理负担,也降低了用户的取件体验,甚至出现快递丢失、逾期未取、错取等问题。HarmonyOS 6.0+作为面向全场景的分布式操作系统,具备强大的Location Kit定位能力、多端协同优势、分布式消息推送能力以及ArkUI组件的便捷开发特性,能够有效解决上述场景痛点。

本文聚焦智能快递代收管理APP的开发实战,核心目标是基于HarmonyOS 6.0+生态,开发一款集快递登记、实时定位追踪、多端取件提醒、全流程管理于一体的智能代收管理APP,实现快递代收场景的数字化、智能化升级,提升代收点管理效率与用户取件便捷度。

二、核心技术栈解析

本系统开发基于HarmonyOS 6.0+版本,结合多种原生API与组件,构建高效、稳定、便捷的智能快递代收管理能力,核心技术栈如下:

  • HarmonyOS Location Kit:核心用于实现快递员实时位置追踪、代收点位置定位、取件路线规划等功能,支持高精度定位与位置更新监听,适配HarmonyOS多设备定位协同需求。

  • 快递条码/二维码识别API:集成HarmonyOS原生条码识别能力,支持快递面单条码、取件二维码的快速扫描与解析,实现快递信息的自动化录入,提升登记效率。

  • 分布式消息推送API:依托HarmonyOS分布式能力,实现多设备消息协同推送,支持手机通知、智能手表震动提醒等多端取件通知,同时支持短信推送取件码,确保提醒触达率。

  • 本地数据库管理API:采用HarmonyOS原生本地数据库,实现快递信息、用户数据、代收记录等数据的本地存储、查询、更新与删除,保障离线状态下的数据可用性,提升数据访问效率。

  • ArkUI便捷操作组件:基于ArkUI开发框架,选用Button、List、Form、Dialog等便捷组件,构建简洁、易用的APP交互界面,适配手机、平板等多设备显示,提升开发效率与用户操作体验。

三、开发实战

3.1 环境搭建

本系统开发需基于DevEco Studio 5.0+版本,完成HarmonyOS 6.0+开发环境配置、权限申请与数据库初始化,为后续模块开发奠定基础。

3.1.1 开发环境配置

  1. 安装DevEco Studio 5.0+,配置HarmonyOS 6.0+ SDK,勾选Location、Barcode、Push等相关API依赖,确保开发工具支持所需核心能力;

  2. 创建Empty Ability工程,设置工程包名、应用名称,选择API Version 11(对应HarmonyOS 6.0+),配置多设备适配参数,支持手机、智能手表等多端部署;

  3. 导入第三方依赖(如条码识别辅助工具、定位优化工具),配置工程gradle文件,确保依赖包正常加载。

3.1.2 权限申请

系统需申请相机(条码扫描)、定位(位置追踪/导航)、存储(数据库/文件导出)、消息推送等权限,在config.json中配置权限声明,同时在代码中实现动态权限申请,示例代码如下:

TypeScript 复制代码
// 动态权限申请工具类
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';

export class PermissionUtil {
  // 所需权限列表
  private static readonly REQUIRED_PERMISSIONS = [
    'ohos.permission.CAMERA', // 相机权限(条码扫描)
    'ohos.permission.LOCATION', // 定位权限
    'ohos.permission.WRITE_USER_STORAGE', // 存储权限
    'ohos.permission.NOTIFICATION', // 通知权限(消息推送)
    'ohos.permission.SEND_SMS' // 短信权限(取件码推送)
  ];

  // 检查并申请权限
  public static async checkAndRequestPermissions(): Promise<boolean> {
    const atManager = abilityAccessCtrl.createAtManager();
    const bundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_PERMISSIONS);
    const permissions = bundleInfo.permissions;

    for (const permission of this.REQUIRED_PERMISSIONS) {
      const result = await atManager.checkPermission(abilityAccessCtrl.createAtManager().getCallingToken(), permission);
      if (result === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {
        // 申请权限
        const requestResult = await atManager.requestPermissionsFromUser(
          abilityAccessCtrl.createAtManager().getCallingToken(),
          [permission]
        );
        if (requestResult.grantResults[0] !== 0) {
          // 权限申请失败,提示用户
          console.error(`权限${permission}申请失败,影响功能使用`);
          return false;
        }
      }
    }
    return true;
  }
}

// 在Ability的onCreate中调用权限申请
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  super.onCreate(want, launchParam);
  // 申请权限
  PermissionUtil.checkAndRequestPermissions().then((isGranted) => {
    if (isGranted) {
      // 权限申请成功,初始化后续操作
      this.initDatabase();
    } else {
      // 权限申请失败,退出应用或提示
      this.terminateAbility();
    }
  });
}

3.1.3 数据库初始化

采用HarmonyOS原生本地数据库,创建快递信息表、用户表、代收记录表等核心数据表,初始化数据库连接,示例代码如下:

TypeScript 复制代码
// 数据库初始化工具类
import relationalStore from '@ohos.data.relationalStore';

// 数据库名称
const DB_NAME = 'express_management.db';
// 数据库版本
const DB_VERSION = 1;

// 快递信息表结构
const EXPRESS_TABLE = 'express_info';
const CREATE_EXPRESS_TABLE = `CREATE TABLE IF NOT EXISTS ${EXPRESS_TABLE} (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  express_code TEXT UNIQUE NOT NULL, // 快递单号(条码/二维码解析结果)
  recipient TEXT NOT NULL, // 收件人
  courier TEXT, // 快递员
  company TEXT NOT NULL, // 快递公司
  status INTEGER NOT NULL DEFAULT 0, // 状态:0-待取,1-已取,2-拒收
  take_code TEXT NOT NULL, // 取件码
  courier_location TEXT, // 快递员实时位置(JSON格式)
  estimated_time TEXT, // 预计送达时间
  create_time TEXT NOT NULL, // 登记时间
  take_time TEXT, // 取件时间
  over_time INTEGER DEFAULT 0 // 是否逾期:0-未逾期,1-逾期
)`;

// 用户表结构(权限管理)
const USER_TABLE = 'user_info';
const CREATE_USER_TABLE = `CREATE TABLE IF NOT EXISTS ${USER_TABLE} (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE NOT NULL,
  password TEXT NOT NULL,
  role INTEGER NOT NULL DEFAULT 1 // 角色:0-管理员,1-代收员
)`;

export class DatabaseUtil {
  private static rdbStore: relationalStore.RdbStore | null = null;

  // 初始化数据库
  public static async initDatabase(context: Context): Promise<relationalStore.RdbStore> {
    if (this.rdbStore) {
      return this.rdbStore;
    }
    const storeConfig: relationalStore.StoreConfig = {
      name: DB_NAME,
      securityLevel: relationalStore.SecurityLevel.S1
    };
    this.rdbStore = await relationalStore.getRdbStore(context, storeConfig);
    // 创建数据表
    await this.rdbStore.executeSql(CREATE_EXPRESS_TABLE);
    await this.rdbStore.executeSql(CREATE_USER_TABLE);
    // 初始化管理员账号(默认账号:admin,密码:123456)
    const adminCount = await this.rdbStore.queryRowCount(`SELECT * FROM ${USER_TABLE} WHERE username = 'admin'`);
    if (adminCount === 0) {
      await this.rdbStore.insert(USER_TABLE, {
        username: 'admin',
        password: '123456',
        role: 0
      });
    }
    return this.rdbStore;
  }

  // 获取数据库实例
  public static getRdbStore(): relationalStore.RdbStore | null {
    return this.rdbStore;
  }
}

3.2 快递登记模块

本模块实现快递信息的快速录入与状态管理,支持条码/二维码扫描录入与手动补充录入结合,同时实现快递状态的灵活标记,核心功能包括条码扫描、信息补充、状态管理。

3.2.1 条码/二维码扫描录入

集成HarmonyOS原生条码识别API,调用相机扫描快递面单条码/二维码,解析快递单号,自动填充至快递登记表单,示例代码如下:

TypeScript 复制代码
// 条码扫描页面
import barcode from '@ohos.barcode';
import camera from '@ohos.multimedia.camera';

@Entry
@Component
struct BarcodeScanPage {
  private context = getContext(this) as AbilityContext;
  private cameraManager: camera.CameraManager | null = null;
  private barcodeDetector: barcode.BarcodeDetector | null = null;

  build() {
    Column() {
      // 相机预览组件
      CameraPreview()
        .width('100%')
        .height('80%')
        .onReady(async () => {
          // 初始化相机与条码识别器
          this.cameraManager = camera.getCameraManager(this.context);
          this.barcodeDetector = barcode.getBarcodeDetector(this.context);
          // 启动条码识别
          this.startBarcodeDetection();
        })
      
      Text('对准快递面单条码/二维码扫描')
        .fontSize(16)
        .margin({ top: 20 })
    }
  }

  // 启动条码识别
  private async startBarcodeDetection() {
    if (!this.cameraManager || !this.barcodeDetector) return;
    // 配置条码识别参数(支持所有常见条码/二维码格式)
    const detectConfig: barcode.DetectConfig = {
      barcodeTypes: [barcode.BarcodeType.ALL]
    };
    // 监听条码识别结果
    this.barcodeDetector.on('detect', (result: barcode.BarcodeResult[]) => {
      if (result.length > 0) {
        const expressCode = result[0].data; // 解析快递单号
        console.log(`扫描到快递单号:${expressCode}`);
        // 跳转至信息补充页面,传递快递单号
        this.context.navigateForward({
          url: 'pages/ExpressInfoSupplement',
          params: { expressCode: expressCode }
        });
        // 停止识别
        this.barcodeDetector.off('detect');
      }
    });
    // 启动识别
    await this.barcodeDetector.start(detectConfig);
  }

  onDestroy() {
    // 销毁资源
    if (this.barcodeDetector) {
      this.barcodeDetector.stop();
    }
  }
}

3.2.2 手动信息补充与状态标记

用户扫描条码后,跳转至信息补充页面,手动填写收件人、快递员、快递公司等信息,同时提供状态标记按钮,完成快递登记并存储至数据库,核心代码如下:

TypeScript 复制代码
// 快递信息补充页面
import { DatabaseUtil } from '../utils/DatabaseUtil';
import relationalStore from '@ohos.data.relationalStore';

@Entry
@Component
struct ExpressInfoSupplement {
  private expressCode = '';
  private recipientController = new TextInputController();
  private courierController = new TextInputController();
  private companyController = new TextInputController();
  private selectedStatus = 0; // 0-待取(默认),1-已取,2-拒收
  private statusOptions = ['待取', '已取', '拒收'];

  // 页面初始化,接收快递单号
  aboutToAppear() {
    const params = getContext(this).currentAbility?.want?.params;
    if (params && params.expressCode) {
      this.expressCode = params.expressCode;
    }
  }

  // 生成随机取件码(6位数字)
  private generateTakeCode(): string {
    return Math.floor(100000 + Math.random() * 900000).toString();
  }

  // 提交快递信息,完成登记
  private async submitExpressInfo() {
    const recipient = this.recipientController.value.trim();
    const courier = this.courierController.value.trim();
    const company = this.companyController.value.trim();
    if (!recipient || !company) {
      // 提示必填项
      promptAction.showToast({ message: '收件人和快递公司不能为空' });
      return;
    }
    // 获取数据库实例
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) {
      promptAction.showToast({ message: '数据库初始化失败' });
      return;
    }
    // 组装快递信息
    const expressInfo = {
      express_code: this.expressCode,
      recipient: recipient,
      courier: courier,
      company: company,
      status: this.selectedStatus,
      take_code: this.generateTakeCode(),
      courier_location: '',
      estimated_time: '',
      create_time: new Date().toLocaleString(),
      take_time: '',
      over_time: 0
    };
    // 插入数据库
    const insertResult = await rdbStore.insert('express_info', expressInfo);
    if (insertResult > 0) {
      promptAction.showToast({ message: '快递登记成功' });
      // 跳转至快递管理首页
      getContext(this).navigateBack();
    } else {
      promptAction.showToast({ message: '快递登记失败,请重试' });
    }
  }

  build() {
    Column() {
      TextInput({ placeholder: '快递单号(已扫描)', controller: new TextInputController({ text: this.expressCode }) })
        .width('90%')
        .margin({ top: 30, bottom: 15 })
        .enabled(false) // 禁止编辑

      TextInput({ placeholder: '请输入收件人', controller: this.recipientController })
        .width('90%')
        .margin({ bottom: 15 })

      TextInput({ placeholder: '请输入快递员(可选)', controller: this.courierController })
        .width('90%')
        .margin({ bottom: 15 })

      TextInput({ placeholder: '请输入快递公司', controller: this.companyController })
        .width('90%')
        .margin({ bottom: 20 })

      // 快递状态选择
      Text('快递状态')
        .fontSize(16)
        .margin({ bottom: 10 })
      RadioGroup({ selected: this.selectedStatus })
        .width('90%')
        .onChange((value) => {
          this.selectedStatus = value;
        }) {
        ForEach(this.statusOptions, (item, index) => {
          Radio({ value: index.toString(), label: item })
            .fontSize(14)
            .margin({ right: 20 });
        })
      }

      Button('提交登记')
        .width('90%')
        .height(45)
        .margin({ top: 30 })
        .onClick(() => {
          this.submitExpressInfo();
        })
    }
    .width('100%')
    .padding(15)
  }
}

3.3 定位与追踪功能

基于HarmonyOS Location Kit,实现快递员实时位置追踪、预计送达时间预测、代收点位置导航与取件路线规划,核心依托定位监听、位置解析与地图导航能力,提升快递追踪的实时性与便捷度。

3.3.1 快递员实时位置追踪

通过Location Kit获取快递员实时位置,将位置信息(经纬度)存储至数据库,并实时同步至代收点APP与用户端,实现位置可视化追踪,核心代码如下:

TypeScript 复制代码
// 快递员位置追踪工具类
import location from '@ohos.location';
import { DatabaseUtil } from '../utils/DatabaseUtil';
import relationalStore from '@ohos.data.relationalStore';

export class LocationTracker {
  private locationManager: location.LocationManager | null = null;
  private expressCode = ''; // 当前追踪的快递单号

  // 初始化位置管理器,开始追踪快递员位置
  public async startTracker(expressCode: string): Promise<void> {
    this.expressCode = expressCode;
    this.locationManager = location.getDefaultLocationManager();
    if (!this.locationManager) {
      throw new Error('位置管理器初始化失败');
    }
    // 检查定位权限(已在环境搭建中申请)
    const isEnabled = await this.locationManager.isLocationEnabled();
    if (!isEnabled) {
      throw new Error('请开启定位功能');
    }
    // 配置定位参数(高精度、10秒更新一次位置)
    const locationRequest: location.LocationRequest = {
      priority: location.LocationRequestPriority.HIGH_ACCURACY,
      interval: 10000, // 位置更新间隔(10秒)
      fastestInterval: 5000, // 最快更新间隔(5秒)
      needAddress: false // 不需要地址信息,仅需经纬度
    };
    // 监听位置更新
    this.locationManager.on('locationChange', locationRequest, async (loc: location.Location) => {
      if (!loc.longitude || !loc.latitude) return;
      // 组装位置信息(JSON格式,便于存储与解析)
      const locationInfo = JSON.stringify({
        longitude: loc.longitude,
        latitude: loc.latitude,
        updateTime: new Date().toLocaleString()
      });
      // 更新数据库中该快递的快递员位置
      const rdbStore = DatabaseUtil.getRdbStore();
      if (rdbStore) {
        const valuesBucket = { courier_location: locationInfo };
        const whereClause = `express_code = '${this.expressCode}'`;
        await rdbStore.update('express_info', valuesBucket, whereClause);
        console.log(`快递员位置更新:${locationInfo}`);
      }
    });
  }

  // 停止位置追踪
  public stopTracker(): void {
    if (this.locationManager) {
      this.locationManager.off('locationChange');
      console.log('位置追踪已停止');
    }
  }

  // 预计送达时间预测(简单实现:基于距离与平均速度)
  public async predictEstimatedTime(expressCode: string): Promise<string> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) return '无法预测';
    // 1. 获取快递员当前位置
    const courierLocResult = await rdbStore.query(`SELECT courier_location FROM express_info WHERE express_code = '${expressCode}'`);
    if (!courierLocResult || courierLocResult.rowCount === 0) return '无法获取快递员位置';
    courierLocResult.goToFirstRow();
    const courierLocStr = courierLocResult.getString(0);
    if (!courierLocStr) return '无法获取快递员位置';
    const courierLoc = JSON.parse(courierLocStr);

    // 2. 获取代收点位置(假设代收点位置已预设,存储在本地)
    const代收点Loc = { longitude: 116.4074, latitude: 39.9042 }; // 示例:北京天安门(实际需替换为代收点真实位置)

    // 3. 计算距离(简化计算:经纬度差值估算)
    const distance = Math.sqrt(
      Math.pow(courierLoc.longitude - 代收点Loc.longitude, 2) +
      Math.pow(courierLoc.latitude - 代收点Loc.latitude, 2)
    ) * 111; // 1度经纬度约等于111公里

    // 4. 假设平均速度为30km/h,计算预计时间(分钟)
    const averageSpeed = 30; // 平均速度(km/h)
    const estimatedHours = distance / averageSpeed;
    const estimatedMinutes = Math.ceil(estimatedHours * 60);

    // 5. 计算预计送达时间
    const now = new Date();
    now.setMinutes(now.getMinutes() + estimatedMinutes);
    return now.toLocaleString();
  }
}

3.3.2 代收点位置导航与路线规划

集成HarmonyOS地图导航能力(可对接第三方地图API或原生地图组件),实现代收点位置定位、取件路线规划与导航功能,核心代码如下:

TypeScript 复制代码
// 导航工具类(对接HarmonyOS原生地图组件)
import map from '@ohos.map';

export class NavigationUtil {
  private mapController: map.MapController | null = null;

  // 初始化地图控制器
  public async initMap(context: Context): Promise<void> {
    this.mapController = map.createMapController(context);
    if (!this.mapController) {
      throw new Error('地图控制器初始化失败');
    }
    // 设置地图显示模式(标准模式)
    await this.mapController.setMapType(map.MapType.STANDARD);
  }

  // 显示代收点位置,并规划取件路线
  public async showPickupRoute(pickupLoc: { longitude: number, latitude: number }): Promise<void> {
    if (!this.mapController) throw new Error('地图控制器未初始化');
    // 1. 获取用户当前位置
    const locationManager = location.getDefaultLocationManager();
    const userLoc = await locationManager.getCurrentLocation();
    if (!userLoc || !userLoc.longitude || !userLoc.latitude) {
      throw new Error('无法获取用户当前位置');
    }

    // 2. 在地图上标记用户位置与代收点位置
    // 用户位置标记
    const userMarker: map.Marker = {
      position: { longitude: userLoc.longitude, latitude: userLoc.latitude },
      title: '我的位置',
      icon: 'resource://rawfile/user_marker.png' // 自定义标记图标
    };
    // 代收点位置标记
    const pickupMarker: map.Marker = {
      position: pickupLoc,
      title: '代收点',
      icon: 'resource://rawfile/pickup_marker.png'
    };
    // 添加标记到地图
    await this.mapController.addMarker(userMarker);
    await this.mapController.addMarker(pickupMarker);

    // 3. 规划取件路线(步行路线)
    const routeRequest: map.RouteRequest = {
      origin: { longitude: userLoc.longitude, latitude: userLoc.latitude },
      destination: pickupLoc,
      routeType: map.RouteType.WALK // 步行路线,可选驾车、公交
    };
    const routeResult = await this.mapController.calculateRoute(routeRequest);
    if (routeResult && routeResult.routes.length > 0) {
      // 绘制路线
      const routeOverlay: map.PolylineOverlay = {
        points: routeResult.routes[0].path,
        color: '#FF0000', // 路线颜色(红色)
        width: 5 // 路线宽度
      };
      await this.mapController.addPolylineOverlay(routeOverlay);
      // 显示路线距离与预计时间
      const routeDistance = routeResult.routes[0].distance / 1000; // 转换为公里
      const routeTime = Math.ceil(routeResult.routes[0].duration / 60); // 转换为分钟
      console.log(`取件路线:${routeDistance}公里,预计${routeTime}分钟`);
    }
  }

  // 导航到代收点
  public async navigateToPickup(pickupLoc: { longitude: number, latitude: number }): Promise<void> {
    if (!this.mapController) throw new Error('地图控制器未初始化');
    // 启动导航(原生地图导航)
    await this.mapController.startNavigation({
      destination: pickupLoc,
      routeType: map.RouteType.WALK,
      voicePrompt: true // 开启语音提示
    });
  }
}

3.4 取件提醒功能

基于HarmonyOS分布式消息推送API,实现取件码生成与推送、多设备取件提醒、逾期未取提醒,确保用户及时获取取件信息,降低逾期未取率,核心涵盖推送、多设备协同提醒两大能力。

3.4.1 取件码生成与推送

取件码在快递登记时自动生成(6位随机数字),通过分布式消息推送API推送至用户手机通知,同时支持短信推送(针对未安装APP的用户),核心代码如下:

TypeScript 复制代码
// 取件提醒推送工具类
import push from '@ohos.push';
import sms from '@ohos.telephony.sms';
import { DatabaseUtil } from '../utils/DatabaseUtil';

export class ReminderUtil {
  // 推送取件提醒(手机通知+短信)
  public async pushPickupReminder(expressCode: string, recipientPhone: string): Promise<void> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) throw new Error('数据库初始化失败');
    // 1. 获取该快递的取件码、快递公司信息
    const expressResult = await rdbStore.query(`SELECT take_code, company FROM express_info WHERE express_code = '${expressCode}'`);
    if (!expressResult || expressResult.rowCount === 0) throw new Error('未找到该快递信息');
    expressResult.goToFirstRow();
    const takeCode = expressResult.getString(0);
    const company = expressResult.getString(1);
    if (!takeCode) throw new Error('取件码获取失败');

    // 2. 分布式消息推送(手机通知)
    const pushMessage: push.PushMessage = {
      title: '【取件提醒】',
      content: `您有一个${company}快递已到达代收点,取件码:${takeCode},请及时取件~`,
      notificationId: Math.floor(Math.random() * 10000),
      isAutoCancel: true
    };
    // 推送通知到当前设备
    await push.sendPushMessage(pushMessage);
    console.log('取件通知推送成功');

    // 3. 短信推送(可选,针对未安装APP的用户)
    if (recipientPhone) {
      try {
        const smsContent = `【智能代收】您的${company}快递已到代收点,取件码:${takeCode},请尽快前往取件,逾期将收取保管费。`;
        // 发送短信(需申请SEND_SMS权限)
        await sms.sendSms(recipientPhone, smsContent);
        console.log('取件短信推送成功');
      } catch (error) {
        console.error('取件短信推送失败:', error);
      }
    }
  }

  // 多设备取件提醒(手机+智能手表)
  public async multiDeviceReminder(expressCode: string): Promise<void> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) throw new Error('数据库初始化失败');
    // 1. 获取取件码
    const expressResult = await rdbStore.query(`SELECT take_code FROM express_info WHERE express_code = '${expressCode}'`);
    if (!expressResult || expressResult.rowCount === 0) throw new Error('未找到该快递信息');
    expressResult.goToFirstRow();
    const takeCode = expressResult.getString(0);
    if (!takeCode) throw new Error('取件码获取失败');

    // 2. 分布式消息推送(适配多设备)
    const pushMessage: push.PushMessage = {
      title: '【取件提醒】',
      content: `取件码:${takeCode},快递已到代收点`,
      notificationId: Math.floor(Math.random() * 10000),
      isAutoCancel: true,
      multiDevice: true // 开启多设备推送
    };
    await push.sendPushMessage(pushMessage);
    // 智能手表震动提醒(通过分布式能力触发)
    this.triggerWatchVibration();
    console.log('多设备取件提醒推送成功');
  }

  // 触发智能手表震动(简化实现:通过分布式服务调用)
  private async triggerWatchVibration(): Promise<void> {
    // 假设已实现分布式设备管理,获取绑定的智能手表设备
    const deviceManager = getContext(this).deviceManager;
    if (!deviceManager) return;
    const devices = await deviceManager.getConnectedDevices();
    const watchDevices = devices.filter(device => device.deviceType === 'watch');
    if (watchDevices.length === 0) return;
    // 向手表发送震动指令(需手表端APP配合接收)
    const vibrationCommand = { action: 'vibrate', duration: 2000 }; // 震动2秒
    await deviceManager.sendDataToDevice(watchDevices[0].deviceId, vibrationCommand);
  }

  // 逾期未取提醒(每天9:00、18:00推送)
  public async overdueReminder(): Promise<void> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) throw new Error('数据库初始化失败');
    // 1. 查询逾期未取的快递(状态为待取,且超过预计送达时间24小时)
    const now = new Date();
    const overdueTime = new Date(now.getTime() - 24 * 60 * 60 * 1000).toLocaleString();
    const overdueResult = await rdbStore.query(`
      SELECT express_code, recipient, take_code, company FROM express_info 
      WHERE status = 0 AND estimated_time < '${overdueTime}' AND over_time = 0
    `);
    if (!overdueResult || overdueResult.rowCount === 0) return;

    // 2. 批量推送逾期提醒
    while (overdueResult.goToNextRow()) {
      const expressCode = overdueResult.getString(0);
      const recipient = overdueResult.getString(1);
      const takeCode = overdueResult.getString(2);
      const company = overdueResult.getString(3);
      // 推送逾期提醒
      const pushMessage: push.PushMessage = {
        title: '【逾期提醒】',
        content: `尊敬的${recipient},您的${company}快递(取件码:${takeCode})已逾期未取,请尽快前往代收点取件,避免快递丢失!`,
        notificationId: Math.floor(Math.random() * 10000),
        isAutoCancel: true
      };
      await push.sendPushMessage(pushMessage);
      // 更新快递逾期状态
      await rdbStore.update('express_info', { over_time: 1 }, `express_code = '${expressCode}'`);
    }
    console.log('逾期未取提醒推送完成');
  }
}

3.5 管理功能开发

本模块面向代收点管理员与代收员,实现快递分类统计、代收记录查询与导出、用户权限管理、投诉反馈等功能,提升代收点管理效率,规范操作流程。

3.5.1 快递分类统计与记录查询导出

基于数据库查询,实现按快递公司、快递状态的分类统计,支持代收记录的模糊查询与Excel导出,核心代码如下:

TypeScript 复制代码
// 快递管理工具类
import relationalStore from '@ohos.data.relationalStore';
import { DatabaseUtil } from '../utils/DatabaseUtil';
import fileio from '@ohos.fileio';
import exceljs from 'exceljs'; // 假设导入Excel处理第三方依赖

export class ExpressManagerUtil {
  // 快递分类统计(按快递公司/状态)
  public async expressStatistics(): Promise<{ companyStats: any[], statusStats: any[] }> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) throw new Error('数据库初始化失败');

    // 1. 按快递公司统计
    const companyResult = await rdbStore.query(`
      SELECT company, COUNT(*) as count FROM express_info GROUP BY company
    `);
    const companyStats = [];
    if (companyResult && companyResult.rowCount > 0) {
      while (companyResult.goToNextRow()) {
        companyStats.push({
          company: companyResult.getString(0),
          count: companyResult.getNumber(1)
        });
      }
    }

    // 2. 按快递状态统计
    const statusResult = await rdbStore.query(`
      SELECT status, COUNT(*) as count FROM express_info GROUP BY status
    `);
    const statusStats = [];
    const statusMap = { 0: '待取', 1: '已取', 2: '拒收' };
    if (statusResult && statusResult.rowCount > 0) {
      while (statusResult.goToNextRow()) {
        const status = statusResult.getNumber(0);
        statusStats.push({
          status: statusMap[status] || '未知',
          count: statusResult.getNumber(1)
        });
      }
    }

    return { companyStats, statusStats };
  }

  // 代收记录查询(支持模糊查询,按快递单号/收件人)
  public async queryExpressRecords(keyword: string): Promise<any[]> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) throw new Error('数据库初始化失败');
    const whereClause = `express_code LIKE '%${keyword}%' OR recipient LIKE '%${keyword}%'`;
    const queryResult = await rdbStore.query(`
      SELECT * FROM express_info WHERE ${whereClause} ORDER BY create_time DESC
    `);
    const records = [];
    if (queryResult && queryResult.rowCount > 0) {
      while (queryResult.goToNextRow()) {
        records.push({
          id: queryResult.getNumber(0),
          expressCode: queryResult.getString(1),
          recipient: queryResult.getString(2),
          courier: queryResult.getString(3),
          company: queryResult.getString(4),
          status: queryResult.getNumber(5),
          takeCode: queryResult.getString(6),
          createTime: queryResult.getString(9),
          takeTime: queryResult.getString(10)
        });
      }
    }
    return records;
  }

  // 代收记录导出(Excel格式)
  public async exportExpressRecords(records: any[]): Promise<string> {
    // 1. 创建Excel工作簿
    const workbook = new exceljs.Workbook();
    const worksheet = workbook.addWorksheet('代收记录');

    // 2. 设置表头
    worksheet.columns = [
      { header: '序号', key: 'id', width: 8 },
      { header: '快递单号', key: 'expressCode', width: 20 },
      { header: '收件人', key: 'recipient', width: 15 },
      { header: '快递员', key: 'courier', width: 15 },
      { header: '快递公司', key: 'company', width: 15 },
      { header: '快递状态', key: 'status', width: 10 },
      { header: '取件码', key: 'takeCode', width: 10 },
      { header: '登记时间', key: 'createTime', width: 20 },
      { header: '取件时间', key: 'takeTime', width: 20 }
    ];

    // 3. 填充数据
    const statusMap = { 0: '待取', 1: '已取', 2: '拒收' };
    records.forEach((record, index) => {
      worksheet.addRow({
        id: index + 1,
        expressCode: record.expressCode,
        recipient: record.recipient,
        courier: record.courier || '-',
        company: record.company,
        status: statusMap[record.status] || '未知',
        takeCode: record.takeCode,
        createTime: record.createTime,
        takeTime: record.takeTime || '-'
      });
    });

    // 4. 保存Excel文件至本地存储
    const filePath = `${fileio.getExternalStoragePath()}/express_records.xlsx`;
    const buffer = await workbook.xlsx.writeBuffer();
    await fileio.writeFile(filePath, buffer);

    return filePath; // 返回文件路径,供用户下载/分享
  }
}

3.5.2 用户权限管理与投诉反馈

实现管理员与代收员的角色区分,管理员拥有全部操作权限,代收员仅拥有快递登记、取件标记等基础权限;同时提供投诉反馈入口,收集用户意见,核心代码如下:

TypeScript 复制代码
// 用户权限管理工具类
import { DatabaseUtil } from '../utils/DatabaseUtil';
import relationalStore from '@ohos.data.relationalStore';

// 角色枚举
export enum UserRole {
  ADMIN = 0, // 管理员
  COLLECTOR = 1 // 代收员
}

export class UserManagerUtil {
  // 用户登录验证
  public async userLogin(username: string, password: string): Promise<{ success: boolean, role?: UserRole, message: string }> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) return { success: false, message: '数据库初始化失败' };
    // 查询用户信息
    const userResult = await rdbStore.query(`
      SELECT role FROM user_info WHERE username = '${username}' AND password = '${password}'
    `);
    if (!userResult || userResult.rowCount === 0) {
      return { success: false, message: '用户名或密码错误' };
    }
    userResult.goToFirstRow();
    const role = userResult.getNumber(0) as UserRole;
    return { success: true, role: role, message: '登录成功' };
  }

  // 添加代收员账号(仅管理员可操作)
  public async addCollector(username: string, password: string, adminUsername: string): Promise<string> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) return '数据库初始化失败';
    // 验证管理员权限
    const adminResult = await rdbStore.query(`
      SELECT role FROM user_info WHERE username = '${adminUsername}' AND role = ${UserRole.ADMIN}
    `);
    if (!adminResult || adminResult.rowCount === 0) {
      return '无管理员权限,无法添加代收员';
    }
    // 检查用户名是否已存在
    const userCount = await rdbStore.queryRowCount(`SELECT * FROM user_info WHERE username = '${username}'`);
    if (userCount > 0) {
      return '用户名已存在,请更换用户名';
    }
    // 添加代收员(角色为1)
    await rdbStore.insert('user_info', {
      username: username,
      password: password,
      role: UserRole.COLLECTOR
    });
    return '代收员添加成功';
  }

  // 投诉反馈提交
  public async submitFeedback(feedbackInfo: { username: string, content: string, phone?: string }): Promise<string> {
    const rdbStore = DatabaseUtil.getRdbStore();
    if (!rdbStore) return '数据库初始化失败';
    // 检查反馈表是否存在,不存在则创建
    await rdbStore.executeSql(`
      CREATE TABLE IF NOT EXISTS feedback (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT NOT NULL,
        content TEXT NOT NULL,
        phone TEXT,
        create_time TEXT NOT NULL
      )
    `);
    // 插入反馈信息
    await rdbStore.insert('feedback', {
      username: feedbackInfo.username,
      content: feedbackInfo.content,
      phone: feedbackInfo.phone || '',
      create_time: new Date().toLocaleString()
    });
    return '投诉反馈提交成功,我们将尽快处理';
  }
}

3.6 性能优化

针对系统核心功能的性能瓶颈,从条码识别、定位追踪、消息推送、并发操作四个维度进行优化,确保APP运行流畅、响应迅速,适配多用户并发使用场景。

  • 条码识别速度优化:预处理相机预览画面(降低分辨率、灰度化),减少识别计算量;缓存常见快递条码格式,优先匹配高频条码类型;优化条码识别API调用参数,缩短识别响应时间,将识别速度从500ms优化至200ms以内。

  • 定位追踪实时性提升:根据快递员距离代收点的距离动态调整定位更新间隔(远距离10秒/次,近距离5秒/次);采用定位缓存策略,避免频繁调用Location Kit;优化位置数据传输格式,减少数据量,提升同步效率。

  • 消息推送效率优化:批量处理取件提醒与逾期提醒,减少推送API调用次数;优先使用分布式消息推送(比短信推送更高效),短信推送作为备用方案;优化推送消息队列,避免消息拥堵,确保提醒及时性。

  • 多用户并发操作稳定性保障:采用数据库事务机制,避免并发插入/更新导致的数据错乱;添加并发锁,限制同一时间操作同一快递信息的用户数量;优化数据库查询语句,添加索引(快递单号、收件人字段),提升查询速度;定期清理数据库冗余数据,释放存储资源。

3.7 测试与验证

通过多场景、多维度测试,验证系统各功能的可用性、准确性与稳定性,确保APP能够满足代收点实际使用需求,测试内容如下:

3.7.1 功能测试

  • 条码识别准确性测试:选取100个不同快递公司、不同清晰度(清晰、模糊、褶皱)的快递面单条码/二维码,进行扫描测试,识别准确率需达到98%以上;测试不同光线环境(强光、弱光、室内、室外)下的识别效果,确保识别稳定性。

  • 定位追踪精度测试:模拟快递员配送路线,测试不同场景(市区、郊区、室内)下的定位精度,要求定位误差不超过5米;测试位置更新的实时性,确保位置同步延迟不超过3秒。

  • 提醒功能及时性测试:模拟快递到达代收点场景,测试取件提醒的推送延迟(要求不超过10秒);测试多设备提醒的同步性(手机通知与手表震动同步触发);测试逾期未取提醒的准确性,确保逾期24小时后正常推送。

3.7.2 场景测试

选取3个不同规模的代收点(社区代收点、校园代收点、写字楼代收点),进行为期15天的实际使用场景测试,模拟多用户并发操作(最多50人同时操作),测试系统的稳定性;收集代收点工作人员与用户的使用反馈,优化操作流程与功能体验。

3.7.3 性能测试

测试条码识别速度、定位更新速度、消息推送延迟、数据库查询速度等性能指标,确保满足实际使用需求;测试APP在长时间运行(连续72小时)后的稳定性,避免出现闪退、卡顿、数据丢失等问题。

四、总结与展望

4.1 开发总结

本文基于HarmonyOS 6.0+生态,完成了智能快递代收管理APP的开发实战,围绕快递登记、定位追踪、取件提醒、管理功能四大核心模块,整合Location Kit、条码识别、分布式推送等核心技术,解决了快递代收场景下管理混乱、取件不便、追踪不及时等痛点。

开发过程中,重点实现了条码/二维码快速扫描录入、快递员实时位置追踪、多设备取件提醒、快递分类统计等实用功能,通过性能优化与多场景测试,确保了APP的稳定性、实时性与易用性,能够有效提升代收点管理效率,改善用户取件体验。同时,依托HarmonyOS 6.0+的多端协同优势,实现了手机、智能手表等多设备的无缝联动,拓展了应用的使用场景。

4.2 未来展望

结合HarmonyOS生活服务生态的发展趋势,未来可从以下几个方向对系统进行拓展与优化:

  • 社区团购联动:整合社区团购功能,实现快递代收与团购自提一体化管理,代收点可同时作为团购自提点,提升代收点营收,为用户提供一站式生活服务。

  • 快递包装回收:添加快递包装回收登记功能,用户取件时可自愿提交快递包装,系统记录回收信息并给予用户小额奖励(如优惠券),助力绿色环保。

相关推荐
九.九5 小时前
ops-transformer:AI 处理器上的高性能 Transformer 算子库
人工智能·深度学习·transformer
春日见5 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
偷吃的耗子6 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
Faker66363aaa7 小时前
【深度学习】YOLO11-BiFPN多肉植物检测分类模型,从0到1实现植物识别系统,附完整代码与教程_1
人工智能·深度学习·分类
大江东去浪淘尽千古风流人物9 小时前
【SLAM】Hydra-Foundations 层次化空间感知:机器人如何像人类一样理解3D环境
深度学习·算法·3d·机器人·概率论·slam
小刘的大模型笔记10 小时前
大模型微调参数设置 —— 从入门到精通的调参指南
人工智能·深度学习·机器学习
LaughingZhu10 小时前
Product Hunt 每日热榜 | 2026-02-10
人工智能·经验分享·深度学习·神经网络·产品运营
艺杯羹10 小时前
Git版本控制深度复盘:从入门到精通的完整指南
git·wpf·版本控制·git学习·git复盘
千里马也想飞10 小时前
公共管理新题解:信息化条件下文化治理类论文,如何用AI把“大空题目”做成“落地案例库”?(附三级提纲+指令包)
人工智能·深度学习·机器学习·论文笔记
软件算法开发11 小时前
基于鲸鱼优化的LSTM深度学习网络模型(WOA-LSTM)的一维时间序列预测算法matlab仿真
深度学习·lstm·鲸鱼优化·一维时间序列预测·woa-lstm