一、引言
在当前快递代收场景中,普遍存在管理流程混乱、快递堆放无序、用户取件耗时久、取件提醒不及时、快递状态不透明等痛点,不仅增加了代收点工作人员的管理负担,也降低了用户的取件体验,甚至出现快递丢失、逾期未取、错取等问题。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 开发环境配置
-
安装DevEco Studio 5.0+,配置HarmonyOS 6.0+ SDK,勾选Location、Barcode、Push等相关API依赖,确保开发工具支持所需核心能力;
-
创建Empty Ability工程,设置工程包名、应用名称,选择API Version 11(对应HarmonyOS 6.0+),配置多设备适配参数,支持手机、智能手表等多端部署;
-
导入第三方依赖(如条码识别辅助工具、定位优化工具),配置工程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生活服务生态的发展趋势,未来可从以下几个方向对系统进行拓展与优化:
-
社区团购联动:整合社区团购功能,实现快递代收与团购自提一体化管理,代收点可同时作为团购自提点,提升代收点营收,为用户提供一站式生活服务。
-
快递包装回收:添加快递包装回收登记功能,用户取件时可自愿提交快递包装,系统记录回收信息并给予用户小额奖励(如优惠券),助力绿色环保。