Skip to content

开发资产:医废全流程追溯系统

← 上一阶段:方案设计 | 下一阶段:系统落地 →


概述

在开发这个场景的过程中,我们沉淀了以下可复用的开发资产:

  1. Cursor Skill - GPS 轨迹验证规则
  2. PROMPT 模板 - 蓝牙设备集成逻辑生成
  3. 实施指南 - 如何快速复现这个场景

这些资产可以帮助快速复用这个场景的开发经验。


1. Cursor Skill:GPS 轨迹验证规则

使用场景

当你需要开发类似的"GPS 轨迹验证/路线验证"场景时,可以使用这个 Skill 让 AI 理解业务规则。

Skill 内容

markdown
# GPS 轨迹验证规则

## 业务场景
医废转运、巡检、配送等场景中,需要验证人员/车辆是否按规定的路线行走,防止违规操作。

## 核心业务规则

### 1. 路线验证规则

**规则一:偏离距离检测**
```typescript
// 计算点到线段的距离
function pointToLineDistance(
  point: { lat: number; lng: number },
  lineStart: { lat: number; lng: number },
  lineEnd: { lat: number; lng: number }
): number {
  // 使用 Haversine 公式计算距离(米)
  const R = 6371000; // 地球半径(米)
  
  const dLat1 = (lineEnd.lat - lineStart.lat) * Math.PI / 180;
  const dLng1 = (lineEnd.lng - lineStart.lng) * Math.PI / 180;
  
  const a = Math.sin(dLat1 / 2) * Math.sin(dLat1 / 2) +
    Math.cos(lineStart.lat * Math.PI / 180) *
    Math.cos(lineEnd.lat * Math.PI / 180) *
    Math.sin(dLng1 / 2) * Math.sin(dLng1 / 2);
  
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  const distance = R * c;
  
  return distance;
}

// 计算点到路线的最近距离
function distanceToRoute(
  point: { lat: number; lng: number },
  route: Array<{ lat: number; lng: number }>
): number {
  let minDistance = Infinity;
  
  for (let i = 0; i < route.length - 1; i++) {
    const distance = pointToLineDistance(
      point,
      route[i],
      route[i + 1]
    );
    minDistance = Math.min(minDistance, distance);
  }
  
  return minDistance;
}

规则二:路线偏离检测

typescript
async function checkRouteDeviation(
  trajectory: Array<{ lat: number; lng: number; time: Date }>,
  plannedRoute: Array<{ lat: number; lng: number }>,
  maxDeviation: number = 50 // 最大允许偏离距离(米)
): Promise<DeviationResult> {
  const deviations = [];
  
  for (const point of trajectory) {
    const distance = distanceToRoute(point, plannedRoute);
    
    if (distance > maxDeviation) {
      deviations.push({
        point,
        distance,
        time: point.time,
        severity: distance > 100 ? 'critical' : 'warning'
      });
    }
  }
  
  return {
    hasDeviation: deviations.length > 0,
    deviations,
    maxDeviation: deviations.length > 0 
      ? Math.max(...deviations.map(d => d.distance))
      : 0,
    shouldAlert: deviations.some(d => d.severity === 'critical')
  };
}

2. 速度验证规则

规则一:速度合理性检测

typescript
function checkSpeedReasonableness(
  trajectory: Array<{ lat: number; lng: number; time: Date }>
): SpeedCheckResult {
  const speeds = [];
  
  for (let i = 1; i < trajectory.length; i++) {
    const point1 = trajectory[i - 1];
    const point2 = trajectory[i];
    
    const distance = calculateDistance(point1, point2);
    const time = (point2.time.getTime() - point1.time.getTime()) / 1000; // 秒
    
    if (time > 0) {
      const speed = (distance / time) * 3.6; // 转换为 km/h
      speeds.push({ speed, time: point2.time });
    }
  }
  
  // 检查异常速度(步行速度应该在 3-6 km/h)
  const abnormalSpeeds = speeds.filter(s => s.speed < 1 || s.speed > 10);
  
  return {
    avgSpeed: speeds.reduce((sum, s) => sum + s.speed, 0) / speeds.length,
    maxSpeed: Math.max(...speeds.map(s => s.speed)),
    minSpeed: Math.min(...speeds.map(s => s.speed)),
    hasAbnormalSpeed: abnormalSpeeds.length > 0,
    abnormalSpeeds
  };
}

规则二:轨迹跳跃检测

typescript
function checkTrajectoryJump(
  trajectory: Array<{ lat: number; lng: number; time: Date }>
): JumpCheckResult {
  const jumps = [];
  
  for (let i = 1; i < trajectory.length; i++) {
    const point1 = trajectory[i - 1];
    const point2 = trajectory[i];
    
    const distance = calculateDistance(point1, point2);
    const time = (point2.time.getTime() - point1.time.getTime()) / 1000; // 秒
    
    // 如果距离超过 100 米且时间少于 10 秒,可能是跳跃
    if (distance > 100 && time < 10) {
      jumps.push({
        from: point1,
        to: point2,
        distance,
        time,
        speed: (distance / time) * 3.6 // km/h
      });
    }
  }
  
  return {
    hasJump: jumps.length > 0,
    jumps,
    isSuspicious: jumps.length > 3 // 超过3次跳跃视为可疑
  };
}

3. 时间窗口验证规则

规则一:时间窗口检测

typescript
async function checkTimeWindow(
  startTime: Date,
  endTime: Date,
  plannedStartTime: Date,
  plannedEndTime: Date,
  timeWindow: number = 30 // 时间窗口(分钟)
): Promise<TimeWindowResult> {
  const actualDuration = (endTime.getTime() - startTime.getTime()) / (1000 * 60); // 分钟
  const plannedDuration = (plannedEndTime.getTime() - plannedStartTime.getTime()) / (1000 * 60);
  
  // 检查开始时间是否在时间窗口内
  const startDeviation = Math.abs(
    (startTime.getTime() - plannedStartTime.getTime()) / (1000 * 60)
  );
  
  // 检查结束时间是否在时间窗口内
  const endDeviation = Math.abs(
    (endTime.getTime() - plannedEndTime.getTime()) / (1000 * 60)
  );
  
  // 检查总时长是否合理
  const durationDeviation = Math.abs(actualDuration - plannedDuration);
  
  return {
    isInTimeWindow: startDeviation <= timeWindow && endDeviation <= timeWindow,
    startDeviation,
    endDeviation,
    durationDeviation,
    isTimeout: startDeviation > timeWindow || endDeviation > timeWindow,
    shouldAlert: durationDeviation > plannedDuration * 0.5 // 超过计划时长的50%
  };
}

4. 停留检测规则

规则一:异常停留检测

typescript
function checkAbnormalStay(
  trajectory: Array<{ lat: number; lng: number; time: Date }>,
  maxStayTime: number = 10 // 最大允许停留时间(分钟)
): StayCheckResult {
  const stays = [];
  let currentStay: { start: Date; location: { lat: number; lng: number }; points: any[] } | null = null;
  
  for (let i = 1; i < trajectory.length; i++) {
    const point1 = trajectory[i - 1];
    const point2 = trajectory[i];
    
    const distance = calculateDistance(point1, point2);
    const time = (point2.time.getTime() - point1.time.getTime()) / (1000 * 60); // 分钟
    
    // 如果距离小于 10 米,视为停留
    if (distance < 10) {
      if (!currentStay) {
        currentStay = {
          start: point1.time,
          location: { lat: point1.lat, lng: point1.lng },
          points: [point1, point2]
        };
      } else {
        currentStay.points.push(point2);
      }
    } else {
      if (currentStay) {
        const stayDuration = (currentStay.points[currentStay.points.length - 1].time.getTime() - 
          currentStay.start.getTime()) / (1000 * 60);
        
        if (stayDuration > maxStayTime) {
          stays.push({
            ...currentStay,
            duration: stayDuration,
            isAbnormal: true
          });
        }
        
        currentStay = null;
      }
    }
  }
  
  return {
    hasAbnormalStay: stays.length > 0,
    stays,
    shouldAlert: stays.some(s => s.duration > maxStayTime * 2)
  };
}

数据模型

GPS 轨迹点(GPSPoint)

typescript
interface GPSPoint {
  lat: number;        // 纬度
  lng: number;        // 经度
  time: Date;         // 时间戳
  accuracy?: number;  // 精度(米)
  speed?: number;     // 速度(km/h)
}

轨迹验证结果(TrajectoryValidationResult)

typescript
interface TrajectoryValidationResult {
  isValid: boolean;
  routeDeviation: DeviationResult;
  speedCheck: SpeedCheckResult;
  jumpCheck: JumpCheckResult;
  timeWindowCheck: TimeWindowResult;
  stayCheck: StayCheckResult;
  violations: Violation[];
}

开发注意事项

  1. GPS 精度处理:GPS 精度有限,需要设置合理的容差范围
  2. 轨迹采样:轨迹点可能过于密集,需要适当采样
  3. 离线处理:网络不好时,轨迹数据需要本地缓存
  4. 电池优化:GPS 定位耗电,需要优化定位频率
  5. 异常处理:GPS 信号丢失、定位失败等情况需要处理

相似场景复用

这个规则可以复用到:

  • 巡检轨迹验证:安保巡检、设备巡检
  • 配送路线验证:外卖配送、物流配送
  • 运输路线监控:医废转运、危险品运输
  • 人员定位追踪:矿山人员定位、施工现场人员定位

### 如何使用这个 Skill

**步骤 1:保存为文件**

将上述内容保存为 `.cursorrules` 文件或在项目中创建 `docs/business-rules/gps-trajectory-validation.md`

**步骤 2:在 Cursor 中引用**

在开发轨迹验证功能时,告诉 AI: "参考 gps-trajectory-validation.md 中的业务规则, 实现 GPS 轨迹验证逻辑"


**步骤 3:AI 会理解并生成代码**

AI 会基于这个规则生成准确的轨迹验证逻辑、路线偏离检测等。

---

## 2. PROMPT 模板:蓝牙设备集成逻辑生成

### 使用场景

当需要快速生成类似的"蓝牙设备集成"代码时,使用这个 PROMPT 模板。

### PROMPT 模板

```text
你是一个硬件集成开发专家。请根据以下需求,生成完整的蓝牙设备集成代码。

## 业务场景
[描述你的具体场景,例如:蓝牙电子秤自动称重]

## 设备信息
- 设备类型:[例如:蓝牙电子秤]
- 设备型号:[例如:XXX-500]
- 通信协议:[例如:蓝牙 4.0 BLE]
- 数据格式:[例如:JSON / 二进制]

## 功能需求
1. 设备扫描和连接
2. 数据读取和解析
3. 数据验证和处理
4. 异常处理和重连

## 输出要求
1. TypeScript/JavaScript 代码实现
2. 包含完整的设备连接逻辑
3. 包含数据解析逻辑
4. 包含异常处理
5. 包含单元测试用例
6. 包含注释说明

请生成代码。

3. 实施指南

快速复现步骤

如果你需要在新项目中实现类似的场景,按照以下步骤:

步骤 1:需求确认(1 小时)

  • [ ] 确认轨迹验证规则(偏离距离、时间窗口)
  • [ ] 确认硬件设备(PDA、蓝牙秤、GPS)
  • [ ] 确认数据采集频率和精度要求
  • [ ] 确认异常处理规则

步骤 2:数据库设计(30 分钟)

sql
-- 轨迹记录表
CREATE TABLE trajectory_records (
  id VARCHAR(50) PRIMARY KEY,
  record_id VARCHAR(50),  -- 关联记录ID(转运记录、巡检记录等)
  record_type VARCHAR(50),  -- 记录类型
  user_id VARCHAR(50),
  start_time TIMESTAMP,
  end_time TIMESTAMP,
  planned_route JSON,  -- 规定路线
  actual_trajectory JSON,  -- 实际轨迹
  deviation_result JSON,  -- 偏离检测结果
  speed_check_result JSON,  -- 速度检测结果
  violations JSON,  -- 违规记录
  status VARCHAR(20),
  created_at TIMESTAMP
);

-- GPS 轨迹点表
CREATE TABLE gps_points (
  id VARCHAR(50) PRIMARY KEY,
  trajectory_id VARCHAR(50),
  lat DECIMAL(10,6),
  lng DECIMAL(10,6),
  time TIMESTAMP,
  accuracy DECIMAL(5,2),
  speed DECIMAL(5,2),
  created_at TIMESTAMP,
  INDEX idx_trajectory_time (trajectory_id, time)
);

步骤 3:开发轨迹验证(3 小时)

使用上述 Cursor Skill,快速生成轨迹验证逻辑代码。

步骤 4:开发硬件集成(3 小时)

使用 PROMPT 模板生成蓝牙设备集成代码。

步骤 5:集成通知(1 小时)

  • 微信公众号模板消息
  • 企业微信机器人
  • 短信通知(备用)

步骤 6:测试(2 小时)

  • 轨迹验证测试
  • 硬件集成测试
  • 异常处理测试
  • 边界值测试

总开发时间:约 10-12 小时

关键代码片段

后端 API 示例:

typescript
// POST /api/trajectories/validate
router.post('/validate', async (req, res) => {
  const { trajectoryId, plannedRoute } = req.body;
  
  // 1. 获取轨迹数据
  const trajectory = await getTrajectory(trajectoryId);
  
  // 2. 验证路线偏离
  const deviationResult = await checkRouteDeviation(
    trajectory.points,
    plannedRoute,
    50 // 最大允许偏离 50 米
  );
  
  // 3. 验证速度合理性
  const speedCheck = checkSpeedReasonableness(trajectory.points);
  
  // 4. 验证轨迹跳跃
  const jumpCheck = checkTrajectoryJump(trajectory.points);
  
  // 5. 验证时间窗口
  const timeWindowCheck = await checkTimeWindow(
    trajectory.startTime,
    trajectory.endTime,
    plannedRoute.startTime,
    plannedRoute.endTime
  );
  
  // 6. 验证异常停留
  const stayCheck = checkAbnormalStay(trajectory.points, 10);
  
  // 7. 汇总验证结果
  const validationResult = {
    isValid: !deviationResult.shouldAlert && 
             !speedCheck.hasAbnormalSpeed &&
             !jumpCheck.isSuspicious &&
             timeWindowCheck.isInTimeWindow &&
             !stayCheck.shouldAlert,
    deviationResult,
    speedCheck,
    jumpCheck,
    timeWindowCheck,
    stayCheck,
    violations: []
  };
  
  // 8. 如果有违规,记录并通知
  if (!validationResult.isValid) {
    await recordViolations(trajectoryId, validationResult);
    await notifyAdmin({
      type: 'TRAJECTORY_VIOLATION',
      trajectoryId,
      violations: validationResult.violations
    });
  }
  
  res.json({ success: true, result: validationResult });
});

下一步

查看 系统落地 → 了解这个场景在完整系统中的实现。


相关链接

基于 AI 辅助开发,快速、灵活、可靠