Files
zhinian_manage/lib/services/api_service.dart

449 lines
15 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:math';
import '../models/user.dart';
import '../models/message.dart';
import '../models/event.dart';
import '../models/work_order.dart';
import '../models/order.dart';
class ApiService {
static final ApiService _instance = ApiService._internal();
factory ApiService() => _instance;
ApiService._internal();
final _random = Random();
Future<Map<String, dynamic>> login(String phone, String password) async {
await Future.delayed(const Duration(milliseconds: 800));
if (phone.length != 11) {
throw Exception('手机号格式不正确');
}
if (password.length < 6) {
throw Exception('密码不能少于6位');
}
final isBoss = phone.endsWith('88');
return {
'user': {
'id': 'user_${_random.nextInt(99999)}',
'phone': phone,
'name': isBoss ? '张老板' : '李员工',
'avatar': 'https://api.dicebear.com/7.x/avataaars/svg?seed=$phone',
'role': isBoss ? 'boss' : 'employee',
'token': 'token_${DateTime.now().millisecondsSinceEpoch}',
'hotelName': '智念度假酒店',
'scenicName': '智念风景区',
},
'token': 'mock_token_${DateTime.now().millisecondsSinceEpoch}',
};
}
Future<List<ChatMessage>> getChatHistory() async {
await Future.delayed(const Duration(milliseconds: 500));
return [
ChatMessage(
id: 'msg_1',
content: '您好我是智念AI助手有什么可以帮您的吗',
type: MessageType.markdown,
sender: MessageSender.ai,
timestamp: DateTime.now().subtract(const Duration(minutes: 5)),
),
];
}
Future<ChatMessage> sendMessage(String content) async {
await Future.delayed(const Duration(milliseconds: 1200));
final tableTrigger = RegExp(r'表格|列表|清单|明细');
if (tableTrigger.hasMatch(content)) {
return ChatMessage(
id: 'msg_${DateTime.now().millisecondsSinceEpoch}',
content: _tableReport(),
type: MessageType.markdown,
sender: MessageSender.ai,
timestamp: DateTime.now(),
);
}
final imageTrigger = RegExp(r'图片|照片|图像|实景|环境照|相册');
if (imageTrigger.hasMatch(content)) {
return ChatMessage(
id: 'msg_${DateTime.now().millisecondsSinceEpoch}',
content: _imageGallery(),
type: MessageType.markdown,
sender: MessageSender.ai,
timestamp: DateTime.now(),
);
}
final chartTrigger = RegExp(r'报表|数据|营收|趋势|占比|图表|统计|分析');
if (chartTrigger.hasMatch(content)) {
return ChatMessage(
id: 'msg_${DateTime.now().millisecondsSinceEpoch}',
content: _chartReport(),
type: MessageType.markdown,
sender: MessageSender.ai,
timestamp: DateTime.now(),
);
}
final responses = [
'收到您的消息,我已记录并会尽快处理。\n\n**当前状态**:已受理\n**预计处理时间**2小时内',
'好的,我来帮您查询一下。\n\n| 项目 | 状态 | 时间 |\n|------|------|------|\n| 订单核销 | 已完成 | 10:30 |\n| 工单处理 | 进行中 | 11:00 |',
'感谢您的反馈!根据系统记录,今日共有 **15笔订单** 待处理,**3个工单** 需要跟进。',
'已为您生成今日数据报表:\n\n- 总订单数128笔\n- 核销完成96笔\n- 待处理32笔\n- 退款申请2笔',
'事件已发布成功!\n\n> 事件将在设定的时间自动生效系统会提前30分钟发送提醒。',
];
return ChatMessage(
id: 'msg_${DateTime.now().millisecondsSinceEpoch}',
content: responses[_random.nextInt(responses.length)],
type: MessageType.markdown,
sender: MessageSender.ai,
timestamp: DateTime.now(),
);
}
String _imageGallery() {
return '''### 智念度假酒店 · 环境实景
**大堂吧** — 全息投影 + 智能引导
![大堂](https://picsum.photos/seed/zhinian-lobby/640/360)
**无边泳池** — 山景一线270° 全景视野
![泳池](https://picsum.photos/seed/zhinian-pool/640/360)
**SPA 养生** — 古法中医结合现代理疗
![SPA](https://picsum.photos/seed/zhinian-spa/640/360)
> 提示:可继续询问"客房实景""餐厅照片"查看更多。''';
}
String _tableReport() {
return '''### 今日订单明细
共 **5 条** 待跟进订单:
| 订单号 | 客户 | 商品 | 金额 | 状态 |
|---|---|---|---|---|
| ZN20240507001 | 王先生 | 风景区成人票 ×2 | ¥128 | 🟡 待核销 |
| ZN20240507002 | 李女士 | 豪华套房 ×1 | ¥888 | ⚪ 待支付 |
| ZN20240507003 | 张 family | 亲子套票 ×3 | ¥388 | 🟢 已核销 |
| ZN20240507004 | 陈先生 | SPA 养生套餐 | ¥598 | 🔴 退款中 |
| ZN20240507005 | 赵女士 | 景区+酒店套餐 | ¥1588 | ⚫ 已退款 |
**汇总**
| 维度 | 数值 |
|---|---|
| 订单总数 | 5 |
| 应收金额 | ¥3,590 |
| 已退款 | ¥1,588 |
| 净收入 | ¥2,002 |
> 提示:点击订单行可跳转至详情,或继续询问"图表"查看可视化分析。''';
}
String _chartReport() {
return '''### 今日数据报表
总订单 **128 笔**,核销率 **75%**,环比上周 **+12.4%**。
```chart
type: bar
title: 订单状态分布(笔)
labels: 已核销,待处理,待支付,退款
data: 96,32,18,2
```
```chart
type: line
title: 近7日订单趋势
labels: 周一,周二,周三,周四,周五,周六,周日
data: 88,92,105,98,120,135,128
```
```chart
type: pie
title: 营收构成占比
labels: 客房,餐饮,SPA,门票
data: 58,22,12,8
```
> 提示:可继续询问"工单趋势""营收对比"等查看更多分析。''';
}
Future<List<EventItem>> getEvents() async {
await Future.delayed(const Duration(milliseconds: 600));
return List.generate(8, (index) {
final now = DateTime.now();
return EventItem(
id: 'evt_$index',
entityName: ['大堂吧', '游泳池', '健身房', '餐厅', 'SPA中心', '会议室', '停车场', '花园'][index],
description: '这是关于${_getEntityName(index)}的维护通知,请相关人员注意安排时间。',
images: [],
publishTime: now.subtract(Duration(days: index)),
effectiveTime: now.add(Duration(hours: index * 2)),
endTime: now.add(Duration(hours: index * 2 + 4)),
popupReminder: index % 2 == 0,
status: ['published', 'draft', 'published', 'expired'][index % 4],
creatorName: index % 2 == 0 ? '张老板' : '李员工',
createdAt: now.subtract(Duration(days: index)),
);
});
}
String _getEntityName(int index) {
return ['大堂吧', '游泳池', '健身房', '餐厅', 'SPA中心', '会议室', '停车场', '花园'][index];
}
Future<EventItem> publishEvent(Map<String, dynamic> data) async {
await Future.delayed(const Duration(milliseconds: 800));
return EventItem(
id: 'evt_${DateTime.now().millisecondsSinceEpoch}',
entityName: data['entityName'] ?? '',
description: data['description'] ?? '',
images: List<String>.from(data['images'] ?? []),
publishTime: DateTime.now(),
effectiveTime: data['effectiveTime'] != null ? DateTime.parse(data['effectiveTime']) : null,
endTime: data['endTime'] != null ? DateTime.parse(data['endTime']) : null,
popupReminder: data['popupReminder'] ?? false,
status: 'published',
creatorName: '当前用户',
createdAt: DateTime.now(),
);
}
Future<List<WorkOrder>> getWorkOrders(WorkOrderStatus status) async {
await Future.delayed(const Duration(milliseconds: 600));
final allOrders = [
WorkOrder(
id: 'wo_1',
title: '客房空调维修',
description: '308房间空调制冷效果不佳需要安排维修人员检查。',
status: WorkOrderStatus.pending,
creatorName: '前台小王',
assigneeName: '维修部',
createdAt: DateTime.now().subtract(const Duration(hours: 2)),
priority: 'high',
category: '设备维修',
images: [],
location: '3楼308房间',
),
WorkOrder(
id: 'wo_2',
title: '花园草坪修剪',
description: '后花园草坪需要定期修剪预计耗时2小时。',
status: WorkOrderStatus.processing,
creatorName: '张老板',
assigneeName: '保洁部',
createdAt: DateTime.now().subtract(const Duration(hours: 5)),
priority: 'normal',
category: '环境维护',
images: [],
location: '后花园',
),
WorkOrder(
id: 'wo_3',
title: '餐厅设备清洁',
description: '厨房排风系统需要深度清洁。',
status: WorkOrderStatus.completed,
creatorName: '厨师长',
assigneeName: '保洁部',
createdAt: DateTime.now().subtract(const Duration(days: 1)),
completedAt: DateTime.now().subtract(const Duration(hours: 3)),
priority: 'normal',
category: '清洁',
images: [],
location: '主厨房',
),
WorkOrder(
id: 'wo_4',
title: '游泳池水质检测',
description: '每日例行水质检测PH值和氯含量需要记录。',
status: WorkOrderStatus.pending,
creatorName: '救生员小张',
createdAt: DateTime.now().subtract(const Duration(minutes: 30)),
priority: 'high',
category: '安全检查',
images: [],
location: '游泳池',
),
WorkOrder(
id: 'wo_5',
title: '会议室投影仪调试',
description: '下午有重要会议,需要提前调试投影设备。',
status: WorkOrderStatus.processing,
creatorName: '行政小刘',
assigneeName: '行政部',
createdAt: DateTime.now().subtract(const Duration(hours: 1)),
priority: 'urgent',
category: '设备调试',
images: [],
location: 'A座会议室',
),
];
if (status == WorkOrderStatus.all) return allOrders;
return allOrders.where((o) => o.status == status).toList();
}
Future<WorkOrder> getWorkOrderDetail(String id) async {
await Future.delayed(const Duration(milliseconds: 400));
final orders = await getWorkOrders(WorkOrderStatus.all);
return orders.firstWhere((o) => o.id == id, orElse: () => orders.first);
}
Future<WorkOrder> acceptWorkOrder(String id) async {
await Future.delayed(const Duration(milliseconds: 700));
if (_random.nextInt(20) == 0) {
throw Exception('网络异常,请稍后重试');
}
final order = await getWorkOrderDetail(id);
return order.copyWith(
status: WorkOrderStatus.processing,
assigneeName: order.assigneeName ?? '维修部',
);
}
Future<WorkOrder> transferWorkOrder(String id, String department) async {
await Future.delayed(const Duration(milliseconds: 700));
if (_random.nextInt(20) == 0) {
throw Exception('网络异常,请稍后重试');
}
final order = await getWorkOrderDetail(id);
return order.copyWith(assigneeName: department);
}
Future<WorkOrder> completeWorkOrder(String id) async {
await Future.delayed(const Duration(milliseconds: 700));
if (_random.nextInt(20) == 0) {
throw Exception('网络异常,请稍后重试');
}
final order = await getWorkOrderDetail(id);
return order.copyWith(
status: WorkOrderStatus.completed,
completedAt: DateTime.now(),
);
}
Future<List<OrderItem>> getOrders(OrderStatus status) async {
await Future.delayed(const Duration(milliseconds: 600));
final allOrders = [
OrderItem(
id: 'ord_1',
orderNo: 'ZN20240507001',
customerName: '王先生',
customerPhone: '138****8888',
productName: '智念风景区成人票',
amount: 128.00,
status: OrderStatus.pendingVerification,
createdAt: DateTime.now().subtract(const Duration(hours: 2)),
paidAt: DateTime.now().subtract(const Duration(hours: 2)),
verifyCode: 'VK8823',
quantity: 2,
scenicSpot: '智念风景区',
),
OrderItem(
id: 'ord_2',
orderNo: 'ZN20240507002',
customerName: '李女士',
customerPhone: '139****6666',
productName: '度假酒店豪华套房',
amount: 888.00,
status: OrderStatus.pendingPayment,
createdAt: DateTime.now().subtract(const Duration(minutes: 30)),
quantity: 1,
scenicSpot: '智念度假酒店',
),
OrderItem(
id: 'ord_3',
orderNo: 'ZN20240507003',
customerName: '张 family',
customerPhone: '137****5555',
productName: '家庭亲子套票',
amount: 388.00,
status: OrderStatus.verified,
createdAt: DateTime.now().subtract(const Duration(days: 1)),
paidAt: DateTime.now().subtract(const Duration(days: 1)),
verifiedAt: DateTime.now().subtract(const Duration(hours: 5)),
verifyCode: 'VK9912',
quantity: 3,
scenicSpot: '智念风景区',
),
OrderItem(
id: 'ord_4',
orderNo: 'ZN20240507004',
customerName: '陈先生',
customerPhone: '136****4444',
productName: 'SPA养生套餐',
amount: 598.00,
status: OrderStatus.pendingRefund,
createdAt: DateTime.now().subtract(const Duration(days: 2)),
paidAt: DateTime.now().subtract(const Duration(days: 2)),
verifyCode: 'VK7734',
quantity: 1,
remark: '客户行程变更申请退款',
scenicSpot: '智念度假酒店',
),
OrderItem(
id: 'ord_5',
orderNo: 'ZN20240507005',
customerName: '赵女士',
customerPhone: '135****3333',
productName: '景区门票+酒店套餐',
amount: 1588.00,
status: OrderStatus.refunded,
createdAt: DateTime.now().subtract(const Duration(days: 3)),
paidAt: DateTime.now().subtract(const Duration(days: 3)),
refundedAt: DateTime.now().subtract(const Duration(days: 1)),
verifyCode: 'VK6651',
quantity: 2,
scenicSpot: '智念度假区',
),
];
if (status == OrderStatus.all) return allOrders;
return allOrders.where((o) => o.status == status).toList();
}
Future<OrderItem> getOrderDetail(String id) async {
await Future.delayed(const Duration(milliseconds: 400));
final orders = await getOrders(OrderStatus.all);
return orders.firstWhere((o) => o.id == id, orElse: () => orders.first);
}
Future<OrderItem> verifyOrder(String id) async {
await Future.delayed(const Duration(milliseconds: 600));
final order = await getOrderDetail(id);
return order.copyWith(
status: OrderStatus.verified,
verifiedAt: DateTime.now(),
);
}
Future<OrderItem> scanVerify(String code) async {
await Future.delayed(const Duration(milliseconds: 800));
final orders = await getOrders(OrderStatus.all);
final order = orders.firstWhere(
(o) => o.verifyCode == code || o.orderNo == code,
orElse: () => OrderItem(
id: 'ord_scan_${DateTime.now().millisecondsSinceEpoch}',
orderNo: code,
customerName: '扫码客户',
customerPhone: '138****0000',
productName: '景区门票',
amount: 128.00,
status: OrderStatus.pendingVerification,
createdAt: DateTime.now(),
verifyCode: code,
quantity: 1,
scenicSpot: '智念风景区',
),
);
return order;
}
}
final apiService = ApiService();