652 行
29 KiB
HTML
652 行
29 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>骑手状态监控</title>
|
|
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
|
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
|
|
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
|
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
|
<style>
|
|
.page-container {
|
|
padding: 20px;
|
|
background-color: #f5f5f5;
|
|
min-height: 100vh;
|
|
}
|
|
.monitor-header {
|
|
display: flex;
|
|
gap: 20px;
|
|
margin-bottom: 20px;
|
|
}
|
|
.stats-card {
|
|
flex: 1;
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
text-align: center;
|
|
}
|
|
.stats-number {
|
|
font-size: 28px;
|
|
font-weight: bold;
|
|
color: #409EFF;
|
|
margin-bottom: 5px;
|
|
}
|
|
.stats-label {
|
|
color: #666;
|
|
font-size: 14px;
|
|
}
|
|
.monitor-content {
|
|
display: flex;
|
|
gap: 20px;
|
|
}
|
|
.left-panel {
|
|
flex: 2;
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
.right-panel {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
}
|
|
.panel-section {
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
padding: 20px;
|
|
}
|
|
.section-title {
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
margin-bottom: 15px;
|
|
color: #333;
|
|
}
|
|
.rider-map {
|
|
height: 400px;
|
|
background: #f0f0f0;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #666;
|
|
margin-bottom: 20px;
|
|
}
|
|
.status-indicator {
|
|
display: inline-block;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
margin-right: 5px;
|
|
}
|
|
.status-online { background-color: #67C23A; }
|
|
.status-busy { background-color: #E6A23C; }
|
|
.status-offline { background-color: #F56C6C; }
|
|
.rider-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
.rider-info {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.rider-avatar {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
background: #409EFF;
|
|
color: white;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-right: 10px;
|
|
font-size: 12px;
|
|
}
|
|
.real-time-data {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 15px;
|
|
}
|
|
.data-item {
|
|
text-align: center;
|
|
}
|
|
.data-value {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
color: #409EFF;
|
|
}
|
|
.data-label {
|
|
font-size: 12px;
|
|
color: #666;
|
|
margin-top: 5px;
|
|
}
|
|
.search-bar {
|
|
padding: 15px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
.rider-list {
|
|
max-height: 500px;
|
|
overflow-y: auto;
|
|
}
|
|
.action-buttons {
|
|
margin-top: 10px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="app" class="page-container">
|
|
<!-- 监控头部统计 -->
|
|
<div class="monitor-header">
|
|
<div class="stats-card">
|
|
<div class="stats-number">{{ realTimeStats.online_riders || 0 }}</div>
|
|
<div class="stats-label">在线骑手</div>
|
|
</div>
|
|
<div class="stats-card">
|
|
<div class="stats-number">{{ realTimeStats.busy_riders || 0 }}</div>
|
|
<div class="stats-label">配送中</div>
|
|
</div>
|
|
<div class="stats-card">
|
|
<div class="stats-number">{{ realTimeStats.pending_orders || 0 }}</div>
|
|
<div class="stats-label">待配送订单</div>
|
|
</div>
|
|
<div class="stats-card">
|
|
<div class="stats-number">{{ realTimeStats.completed_orders || 0 }}</div>
|
|
<div class="stats-label">今日完成</div>
|
|
</div>
|
|
<div class="stats-card">
|
|
<div class="stats-number">{{ realTimeStats.avg_delivery_time || 0 }}</div>
|
|
<div class="stats-label">平均配送时长(分钟)</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 监控主体内容 -->
|
|
<div class="monitor-content">
|
|
<!-- 左侧地图和列表 -->
|
|
<div class="left-panel">
|
|
<!-- 地图区域 -->
|
|
<div style="padding: 20px;">
|
|
<div class="section-title">骑手分布地图</div>
|
|
<div class="rider-map">
|
|
实时骑手位置地图 ({{ mapData.length }} 个骑手在线)
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 搜索栏 -->
|
|
<div class="search-bar">
|
|
<el-form :inline="true" :model="searchForm">
|
|
<el-form-item>
|
|
<el-input v-model="searchForm.keyword" placeholder="搜索骑手姓名/手机号" clearable style="width: 200px;"></el-input>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-select v-model="searchForm.status" placeholder="工作状态" clearable style="width: 120px;">
|
|
<el-option label="全部" value=""></el-option>
|
|
<el-option label="在线" value="online"></el-option>
|
|
<el-option label="配送中" value="busy"></el-option>
|
|
<el-option label="离线" value="offline"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-select v-model="searchForm.area" placeholder="配送区域" clearable style="width: 120px;">
|
|
<el-option label="全部" value=""></el-option>
|
|
<el-option label="万达商圈" value="1"></el-option>
|
|
<el-option label="清华大学" value="2"></el-option>
|
|
<el-option label="中关村" value="3"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="searchRiders">搜索</el-button>
|
|
<el-button @click="resetSearch">重置</el-button>
|
|
<el-button type="info" @click="exportData">导出</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
|
|
<!-- 骑手列表 -->
|
|
<div class="rider-list">
|
|
<div v-for="rider in riderList" :key="rider.id" class="rider-item">
|
|
<div class="rider-info">
|
|
<div class="rider-avatar">{{ rider.name.charAt(0) }}</div>
|
|
<div>
|
|
<div style="font-weight: bold;">{{ rider.name }}</div>
|
|
<div style="font-size: 12px; color: #666;">{{ rider.phone }}</div>
|
|
</div>
|
|
</div>
|
|
<div style="text-align: center;">
|
|
<div>
|
|
<span :class="'status-indicator status-' + rider.status"></span>
|
|
{{ getStatusText(rider.status) }}
|
|
</div>
|
|
<div style="font-size: 12px; color: #666; margin-top: 2px;">
|
|
{{ rider.area_name }}
|
|
</div>
|
|
</div>
|
|
<div style="text-align: center;">
|
|
<div style="font-weight: bold; color: #409EFF;">{{ rider.today_orders }}</div>
|
|
<div style="font-size: 12px; color: #666;">今日订单</div>
|
|
</div>
|
|
<div style="text-align: center;">
|
|
<div style="font-weight: bold; color: #67C23A;">¥{{ rider.today_income }}</div>
|
|
<div style="font-size: 12px; color: #666;">今日收入</div>
|
|
</div>
|
|
<div>
|
|
<el-button size="mini" @click="viewRiderDetail(rider)">详情</el-button>
|
|
<el-button v-if="rider.status !== 'offline'" size="mini" type="warning" @click="forceOffline(rider)">强制下线</el-button>
|
|
<el-button size="mini" type="primary" @click="sendNotification(rider)">发送通知</el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 分页 -->
|
|
<div style="padding: 20px; text-align: center;">
|
|
<el-pagination
|
|
@current-change="handleCurrentChange"
|
|
:current-page="pagination.page"
|
|
:page-size="pagination.pageSize"
|
|
layout="prev, pager, next"
|
|
:total="pagination.total">
|
|
</el-pagination>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右侧面板 -->
|
|
<div class="right-panel">
|
|
<!-- 实时数据 -->
|
|
<div class="panel-section">
|
|
<div class="section-title">实时数据</div>
|
|
<div class="real-time-data">
|
|
<div class="data-item">
|
|
<div class="data-value">{{ realTimeStats.total_riders || 0 }}</div>
|
|
<div class="data-label">总骑手数</div>
|
|
</div>
|
|
<div class="data-item">
|
|
<div class="data-value">{{ realTimeStats.online_rate || 0 }}%</div>
|
|
<div class="data-label">在线率</div>
|
|
</div>
|
|
<div class="data-item">
|
|
<div class="data-value">{{ realTimeStats.avg_response_time || 0 }}s</div>
|
|
<div class="data-label">平均响应</div>
|
|
</div>
|
|
</div>
|
|
<el-button type="primary" size="small" @click="refreshData" style="width: 100%;">刷新数据</el-button>
|
|
</div>
|
|
|
|
<!-- 异常告警 -->
|
|
<div class="panel-section">
|
|
<div class="section-title">异常告警</div>
|
|
<div v-if="alerts.length === 0" style="text-align: center; color: #999; padding: 20px;">
|
|
暂无异常告警
|
|
</div>
|
|
<div v-else>
|
|
<div v-for="alert in alerts" :key="alert.id" style="margin-bottom: 10px; padding: 10px; background: #fff2f0; border-left: 3px solid #ff4d4f; border-radius: 4px;">
|
|
<div style="font-weight: bold; color: #ff4d4f;">{{ alert.title }}</div>
|
|
<div style="font-size: 12px; color: #666; margin-top: 5px;">{{ alert.content }}</div>
|
|
<div style="font-size: 12px; color: #999; margin-top: 5px;">{{ formatDateTime(alert.time) }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 快速操作 -->
|
|
<div class="panel-section">
|
|
<div class="section-title">快速操作</div>
|
|
<div class="action-buttons">
|
|
<el-button type="primary" size="small" @click="broadcastMessage" style="width: 100%; margin-bottom: 10px;">群发消息</el-button>
|
|
<el-button type="success" size="small" @click="optimizeDispatch" style="width: 100%; margin-bottom: 10px;">优化调度</el-button>
|
|
<el-button type="warning" size="small" @click="emergencyCall" style="width: 100%; margin-bottom: 10px;">紧急呼叫</el-button>
|
|
<el-button type="info" size="small" @click="generateReport" style="width: 100%;">生成报告</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 今日统计 -->
|
|
<div class="panel-section">
|
|
<div class="section-title">今日统计</div>
|
|
<div style="font-size: 14px;">
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
|
<span>订单总数:</span>
|
|
<span style="font-weight: bold; color: #409EFF;">{{ todayStats.total_orders || 0 }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
|
<span>完成订单:</span>
|
|
<span style="font-weight: bold; color: #67C23A;">{{ todayStats.completed_orders || 0 }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
|
<span>取消订单:</span>
|
|
<span style="font-weight: bold; color: #F56C6C;">{{ todayStats.cancelled_orders || 0 }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
|
<span>总收入:</span>
|
|
<span style="font-weight: bold; color: #E6A23C;">¥{{ todayStats.total_income || 0 }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between;">
|
|
<span>完成率:</span>
|
|
<span style="font-weight: bold; color: #409EFF;">{{ todayStats.completion_rate || 0 }}%</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 骑手详情对话框 -->
|
|
<el-dialog title="骑手详情" :visible.sync="detailDialogVisible" width="800px">
|
|
<div v-if="currentRider">
|
|
<el-tabs v-model="activeTab">
|
|
<el-tab-pane label="基本信息" name="basic">
|
|
<el-descriptions :column="2" border>
|
|
<el-descriptions-item label="姓名">{{ currentRider.name }}</el-descriptions-item>
|
|
<el-descriptions-item label="手机号">{{ currentRider.phone }}</el-descriptions-item>
|
|
<el-descriptions-item label="工作状态">
|
|
<span :class="'status-indicator status-' + currentRider.status"></span>
|
|
{{ getStatusText(currentRider.status) }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="配送区域">{{ currentRider.area_name }}</el-descriptions-item>
|
|
<el-descriptions-item label="在线时长">{{ currentRider.online_duration }}</el-descriptions-item>
|
|
<el-descriptions-item label="当前位置">{{ currentRider.current_location }}</el-descriptions-item>
|
|
</el-descriptions>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="今日数据" name="today">
|
|
<div style="display: flex; gap: 20px;">
|
|
<div style="flex: 1;">
|
|
<h4>订单统计</h4>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
|
<span>接单数量:</span>
|
|
<span style="font-weight: bold;">{{ currentRider.today_orders }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
|
<span>完成数量:</span>
|
|
<span style="font-weight: bold; color: #67C23A;">{{ currentRider.completed_orders }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
|
<span>取消数量:</span>
|
|
<span style="font-weight: bold; color: #F56C6C;">{{ currentRider.cancelled_orders }}</span>
|
|
</div>
|
|
</div>
|
|
<div style="flex: 1;">
|
|
<h4>收入统计</h4>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
|
<span>配送费:</span>
|
|
<span style="font-weight: bold;">¥{{ currentRider.delivery_income }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
|
<span>奖励:</span>
|
|
<span style="font-weight: bold; color: #67C23A;">¥{{ currentRider.bonus_income }}</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
|
<span>总收入:</span>
|
|
<span style="font-weight: bold; color: #409EFF;">¥{{ currentRider.today_income }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="轨迹记录" name="track">
|
|
<div style="height: 300px; background: #f0f0f0; border: 1px solid #ddd; border-radius: 4px; display: flex; align-items: center; justify-content: center; color: #666;">
|
|
骑手今日配送轨迹图
|
|
</div>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<!-- 发送通知对话框 -->
|
|
<el-dialog title="发送通知" :visible.sync="notificationDialogVisible" width="500px">
|
|
<el-form :model="notificationForm" :rules="notificationRules" ref="notificationForm" label-width="80px">
|
|
<el-form-item label="通知类型" prop="type">
|
|
<el-select v-model="notificationForm.type" placeholder="请选择" style="width: 100%;">
|
|
<el-option label="系统通知" value="system"></el-option>
|
|
<el-option label="订单提醒" value="order"></el-option>
|
|
<el-option label="紧急通知" value="urgent"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="通知内容" prop="content">
|
|
<el-input type="textarea" v-model="notificationForm.content" placeholder="请输入通知内容" :rows="4"></el-input>
|
|
</el-form-item>
|
|
</el-form>
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button @click="notificationDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="confirmSendNotification">发送</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
|
|
<script>
|
|
new Vue({
|
|
el: '#app',
|
|
data() {
|
|
return {
|
|
realTimeStats: {},
|
|
todayStats: {},
|
|
riderList: [],
|
|
mapData: [],
|
|
alerts: [],
|
|
searchForm: {
|
|
keyword: '',
|
|
status: '',
|
|
area: ''
|
|
},
|
|
pagination: {
|
|
page: 1,
|
|
pageSize: 10,
|
|
total: 0
|
|
},
|
|
detailDialogVisible: false,
|
|
notificationDialogVisible: false,
|
|
currentRider: null,
|
|
activeTab: 'basic',
|
|
notificationForm: {
|
|
type: '',
|
|
content: ''
|
|
},
|
|
notificationRules: {
|
|
type: [
|
|
{ required: true, message: '请选择通知类型', trigger: 'change' }
|
|
],
|
|
content: [
|
|
{ required: true, message: '请输入通知内容', trigger: 'blur' }
|
|
]
|
|
},
|
|
refreshTimer: null
|
|
}
|
|
},
|
|
mounted() {
|
|
this.loadData();
|
|
this.startAutoRefresh();
|
|
},
|
|
beforeDestroy() {
|
|
if (this.refreshTimer) {
|
|
clearInterval(this.refreshTimer);
|
|
}
|
|
},
|
|
methods: {
|
|
loadData() {
|
|
this.loadRealTimeStats();
|
|
this.loadTodayStats();
|
|
this.loadRiderList();
|
|
this.loadAlerts();
|
|
},
|
|
loadRealTimeStats() {
|
|
// 模拟实时统计数据
|
|
this.realTimeStats = {
|
|
online_riders: 45,
|
|
busy_riders: 28,
|
|
pending_orders: 12,
|
|
completed_orders: 156,
|
|
avg_delivery_time: 23,
|
|
total_riders: 68,
|
|
online_rate: 66.2,
|
|
avg_response_time: 15
|
|
};
|
|
},
|
|
loadTodayStats() {
|
|
// 模拟今日统计数据
|
|
this.todayStats = {
|
|
total_orders: 245,
|
|
completed_orders: 198,
|
|
cancelled_orders: 12,
|
|
total_income: 15680,
|
|
completion_rate: 80.8
|
|
};
|
|
},
|
|
loadRiderList() {
|
|
// 模拟骑手列表数据
|
|
this.riderList = [
|
|
{
|
|
id: 1,
|
|
name: '张三',
|
|
phone: '13800138001',
|
|
status: 'online',
|
|
area_name: '万达商圈',
|
|
today_orders: 12,
|
|
today_income: 280,
|
|
online_duration: '6小时30分',
|
|
current_location: '北京市朝阳区万达广场',
|
|
completed_orders: 10,
|
|
cancelled_orders: 1,
|
|
delivery_income: 240,
|
|
bonus_income: 40
|
|
},
|
|
{
|
|
id: 2,
|
|
name: '李四',
|
|
phone: '13800138002',
|
|
status: 'busy',
|
|
area_name: '清华大学',
|
|
today_orders: 8,
|
|
today_income: 195,
|
|
online_duration: '5小时15分',
|
|
current_location: '北京市海淀区清华大学',
|
|
completed_orders: 7,
|
|
cancelled_orders: 0,
|
|
delivery_income: 175,
|
|
bonus_income: 20
|
|
},
|
|
{
|
|
id: 3,
|
|
name: '王五',
|
|
phone: '13800138003',
|
|
status: 'offline',
|
|
area_name: '中关村',
|
|
today_orders: 15,
|
|
today_income: 350,
|
|
online_duration: '8小时45分',
|
|
current_location: '北京市海淀区中关村',
|
|
completed_orders: 14,
|
|
cancelled_orders: 1,
|
|
delivery_income: 300,
|
|
bonus_income: 50
|
|
}
|
|
];
|
|
this.pagination.total = this.riderList.length;
|
|
},
|
|
loadAlerts() {
|
|
// 模拟告警数据
|
|
this.alerts = [
|
|
{
|
|
id: 1,
|
|
title: '骑手张三超时未接单',
|
|
content: '订单#12345已等待15分钟,建议重新分配',
|
|
time: new Date().getTime() - 300000
|
|
},
|
|
{
|
|
id: 2,
|
|
title: '万达商圈订单积压',
|
|
content: '当前有8个订单待配送,建议增加骑手',
|
|
time: new Date().getTime() - 600000
|
|
}
|
|
];
|
|
},
|
|
startAutoRefresh() {
|
|
// 每30秒自动刷新数据
|
|
this.refreshTimer = setInterval(() => {
|
|
this.loadRealTimeStats();
|
|
}, 30000);
|
|
},
|
|
refreshData() {
|
|
this.loadData();
|
|
this.$message.success('数据已刷新');
|
|
},
|
|
searchRiders() {
|
|
// 模拟搜索
|
|
this.loadRiderList();
|
|
},
|
|
resetSearch() {
|
|
this.searchForm = {
|
|
keyword: '',
|
|
status: '',
|
|
area: ''
|
|
};
|
|
this.loadRiderList();
|
|
},
|
|
handleCurrentChange(val) {
|
|
this.pagination.page = val;
|
|
this.loadRiderList();
|
|
},
|
|
viewRiderDetail(rider) {
|
|
this.currentRider = rider;
|
|
this.activeTab = 'basic';
|
|
this.detailDialogVisible = true;
|
|
},
|
|
forceOffline(rider) {
|
|
this.$confirm(`确定要强制 ${rider.name} 下线吗?`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
// 模拟强制下线操作
|
|
rider.status = 'offline';
|
|
this.$message.success('操作成功');
|
|
});
|
|
},
|
|
sendNotification(rider) {
|
|
this.currentRider = rider;
|
|
this.notificationForm = {
|
|
type: '',
|
|
content: ''
|
|
};
|
|
this.notificationDialogVisible = true;
|
|
},
|
|
confirmSendNotification() {
|
|
this.$refs.notificationForm.validate((valid) => {
|
|
if (valid) {
|
|
// 模拟发送通知
|
|
this.$message.success('通知发送成功');
|
|
this.notificationDialogVisible = false;
|
|
}
|
|
});
|
|
},
|
|
broadcastMessage() {
|
|
this.$message.info('群发消息功能');
|
|
},
|
|
optimizeDispatch() {
|
|
this.$message.info('优化调度功能');
|
|
},
|
|
emergencyCall() {
|
|
this.$message.info('紧急呼叫功能');
|
|
},
|
|
generateReport() {
|
|
this.$message.info('生成报告功能');
|
|
},
|
|
exportData() {
|
|
this.$message.success('导出成功');
|
|
},
|
|
getStatusText(status) {
|
|
const statusMap = {
|
|
'online': '在线',
|
|
'busy': '配送中',
|
|
'offline': '离线'
|
|
};
|
|
return statusMap[status] || status;
|
|
},
|
|
formatDateTime(timestamp) {
|
|
if (!timestamp) return '';
|
|
return new Date(timestamp).toLocaleString('zh-CN');
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |