route-api.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /**
  2. * 路线和班次管理API接口系统
  3. * 支持路线、班次的增删改查、票价管理、班次发布
  4. */
  5. class RouteApiService {
  6. constructor() {
  7. this.listeners = []; // 数据变化监听器
  8. this.initRouteData();
  9. }
  10. // 初始化路线数据
  11. initRouteData() {
  12. const routes = this.getAllRoutes();
  13. if (routes.length === 0) {
  14. const sampleRoutes = [
  15. {
  16. id: 'route_001',
  17. activityId: 'activity_001',
  18. activityName: '北京春季音乐节',
  19. fromCity: '北京',
  20. toCity: '北京',
  21. fromLocation: '北京东直门地铁站A口',
  22. toLocation: '北京国家体育场(鸟巢)',
  23. distance: '15公里',
  24. duration: '约1小时',
  25. type: 'bus', // bus, business, charter
  26. status: 'active', // active, inactive, draft
  27. createTime: '2024-01-15 10:00:00',
  28. updateTime: '2024-01-15 10:00:00',
  29. schedules: [
  30. {
  31. id: 'schedule_001',
  32. departureTime: '08:00',
  33. arrivalTime: '09:00',
  34. totalTickets: 50,
  35. soldTickets: 12,
  36. remainingTickets: 38,
  37. price: 15,
  38. vehicleModel: '宇通大巴',
  39. driver: {
  40. id: 'driver_001',
  41. name: '张师傅',
  42. phone: '13800138001'
  43. },
  44. status: 'active',
  45. createTime: '2024-01-15 10:00:00'
  46. },
  47. {
  48. id: 'schedule_002',
  49. departureTime: '09:30',
  50. arrivalTime: '10:30',
  51. totalTickets: 50,
  52. soldTickets: 8,
  53. remainingTickets: 42,
  54. price: 15,
  55. vehicleModel: '宇通大巴',
  56. driver: {
  57. id: 'driver_002',
  58. name: '李师傅',
  59. phone: '13800138002'
  60. },
  61. status: 'active',
  62. createTime: '2024-01-15 10:00:00'
  63. }
  64. ]
  65. },
  66. {
  67. id: 'route_002',
  68. activityId: 'activity_001',
  69. activityName: '北京春季音乐节',
  70. fromCity: '北京',
  71. toCity: '北京',
  72. fromLocation: '北京朝阳区',
  73. toLocation: '北京国家体育场(鸟巢)',
  74. distance: '20公里',
  75. duration: '约1.5小时',
  76. type: 'business',
  77. status: 'active',
  78. createTime: '2024-01-15 10:00:00',
  79. updateTime: '2024-01-15 10:00:00',
  80. schedules: [
  81. {
  82. id: 'schedule_003',
  83. departureTime: '08:00',
  84. arrivalTime: '09:30',
  85. totalTickets: 20,
  86. soldTickets: 5,
  87. remainingTickets: 15,
  88. price: 35,
  89. vehicleModel: '奔驰V级商务车',
  90. driver: {
  91. id: 'driver_003',
  92. name: '王师傅',
  93. phone: '13800138003'
  94. },
  95. status: 'active',
  96. createTime: '2024-01-15 10:00:00'
  97. }
  98. ]
  99. },
  100. {
  101. id: 'route_003',
  102. activityId: 'activity_001',
  103. activityName: '北京春季音乐节',
  104. fromCity: '北京',
  105. toCity: '北京',
  106. fromLocation: '指定地点接送',
  107. toLocation: '北京国家体育场(鸟巢)',
  108. distance: '25公里',
  109. duration: '约2小时',
  110. type: 'charter',
  111. status: 'active',
  112. createTime: '2024-01-15 10:00:00',
  113. updateTime: '2024-01-15 10:00:00',
  114. schedules: [
  115. {
  116. id: 'schedule_004',
  117. departureTime: '任意时间',
  118. arrivalTime: '根据需求',
  119. totalTickets: 6,
  120. soldTickets: 1,
  121. remainingTickets: 5,
  122. price: 800,
  123. vehicleModel: '奔驰V级商务车',
  124. driver: {
  125. id: 'driver_004',
  126. name: '赵师傅',
  127. phone: '13800138004'
  128. },
  129. status: 'active',
  130. createTime: '2024-01-15 10:00:00'
  131. }
  132. ]
  133. }
  134. ];
  135. this.saveRoutes(sampleRoutes);
  136. }
  137. }
  138. // 获取所有路线
  139. getAllRoutes() {
  140. try {
  141. return wx.getStorageSync('routes') || [];
  142. } catch (error) {
  143. console.error('获取路线数据失败:', error);
  144. return [];
  145. }
  146. }
  147. // 保存路线数据
  148. saveRoutes(routes) {
  149. try {
  150. wx.setStorageSync('routes', routes);
  151. this.notifyListeners(routes);
  152. return true;
  153. } catch (error) {
  154. console.error('保存路线数据失败:', error);
  155. return false;
  156. }
  157. }
  158. // 根据ID获取路线
  159. getRouteById(routeId) {
  160. const routes = this.getAllRoutes();
  161. return routes.find(route => route.id === routeId);
  162. }
  163. // 根据活动ID获取路线
  164. getRoutesByActivityId(activityId) {
  165. const routes = this.getAllRoutes();
  166. return routes.filter(route => route.activityId === activityId);
  167. }
  168. // 创建路线
  169. createRoute(routeData) {
  170. const routes = this.getAllRoutes();
  171. const newRoute = {
  172. ...routeData,
  173. id: this.generateRouteId(),
  174. createTime: new Date().toISOString().replace('T', ' ').substring(0, 19),
  175. updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19),
  176. status: routeData.status || 'active',
  177. schedules: routeData.schedules || []
  178. };
  179. routes.push(newRoute);
  180. this.saveRoutes(routes);
  181. return newRoute;
  182. }
  183. // 更新路线
  184. updateRoute(routeId, updateData) {
  185. const routes = this.getAllRoutes();
  186. const routeIndex = routes.findIndex(route => route.id === routeId);
  187. if (routeIndex === -1) {
  188. throw new Error('路线不存在');
  189. }
  190. routes[routeIndex] = {
  191. ...routes[routeIndex],
  192. ...updateData,
  193. updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19)
  194. };
  195. this.saveRoutes(routes);
  196. return routes[routeIndex];
  197. }
  198. // 删除路线
  199. deleteRoute(routeId) {
  200. const routes = this.getAllRoutes();
  201. const filteredRoutes = routes.filter(route => route.id !== routeId);
  202. if (filteredRoutes.length === routes.length) {
  203. throw new Error('路线不存在');
  204. }
  205. this.saveRoutes(filteredRoutes);
  206. return true;
  207. }
  208. // 添加班次
  209. addSchedule(routeId, scheduleData) {
  210. const routes = this.getAllRoutes();
  211. const routeIndex = routes.findIndex(route => route.id === routeId);
  212. if (routeIndex === -1) {
  213. throw new Error('路线不存在');
  214. }
  215. const newSchedule = {
  216. ...scheduleData,
  217. id: this.generateScheduleId(),
  218. createTime: new Date().toISOString().replace('T', ' ').substring(0, 19),
  219. status: scheduleData.status || 'active'
  220. };
  221. routes[routeIndex].schedules.push(newSchedule);
  222. routes[routeIndex].updateTime = new Date().toISOString().replace('T', ' ').substring(0, 19);
  223. this.saveRoutes(routes);
  224. return newSchedule;
  225. }
  226. // 更新班次
  227. updateSchedule(routeId, scheduleId, updateData) {
  228. const routes = this.getAllRoutes();
  229. const routeIndex = routes.findIndex(route => route.id === routeId);
  230. if (routeIndex === -1) {
  231. throw new Error('路线不存在');
  232. }
  233. const scheduleIndex = routes[routeIndex].schedules.findIndex(schedule => schedule.id === scheduleId);
  234. if (scheduleIndex === -1) {
  235. throw new Error('班次不存在');
  236. }
  237. routes[routeIndex].schedules[scheduleIndex] = {
  238. ...routes[routeIndex].schedules[scheduleIndex],
  239. ...updateData
  240. };
  241. routes[routeIndex].updateTime = new Date().toISOString().replace('T', ' ').substring(0, 19);
  242. this.saveRoutes(routes);
  243. return routes[routeIndex].schedules[scheduleIndex];
  244. }
  245. // 删除班次
  246. deleteSchedule(routeId, scheduleId) {
  247. const routes = this.getAllRoutes();
  248. const routeIndex = routes.findIndex(route => route.id === routeId);
  249. if (routeIndex === -1) {
  250. throw new Error('路线不存在');
  251. }
  252. const scheduleIndex = routes[routeIndex].schedules.findIndex(schedule => schedule.id === scheduleId);
  253. if (scheduleIndex === -1) {
  254. throw new Error('班次不存在');
  255. }
  256. routes[routeIndex].schedules.splice(scheduleIndex, 1);
  257. routes[routeIndex].updateTime = new Date().toISOString().replace('T', ' ').substring(0, 19);
  258. this.saveRoutes(routes);
  259. return true;
  260. }
  261. // 搜索路线
  262. searchRoutes(searchParams) {
  263. const routes = this.getAllRoutes();
  264. let filteredRoutes = [...routes];
  265. // 按活动ID搜索
  266. if (searchParams.activityId) {
  267. filteredRoutes = filteredRoutes.filter(route =>
  268. route.activityId === searchParams.activityId
  269. );
  270. }
  271. // 按路线类型搜索
  272. if (searchParams.type) {
  273. filteredRoutes = filteredRoutes.filter(route =>
  274. route.type === searchParams.type
  275. );
  276. }
  277. // 按出发城市搜索
  278. if (searchParams.fromCity) {
  279. filteredRoutes = filteredRoutes.filter(route =>
  280. route.fromCity.includes(searchParams.fromCity)
  281. );
  282. }
  283. // 按到达城市搜索
  284. if (searchParams.toCity) {
  285. filteredRoutes = filteredRoutes.filter(route =>
  286. route.toCity.includes(searchParams.toCity)
  287. );
  288. }
  289. // 按状态搜索
  290. if (searchParams.status) {
  291. filteredRoutes = filteredRoutes.filter(route =>
  292. route.status === searchParams.status
  293. );
  294. }
  295. // 排序
  296. const sortBy = searchParams.sortBy || 'createTime';
  297. const sortOrder = searchParams.sortOrder || 'desc';
  298. filteredRoutes.sort((a, b) => {
  299. let aValue = a[sortBy];
  300. let bValue = b[sortBy];
  301. if (sortBy === 'createTime' || sortBy === 'updateTime') {
  302. aValue = new Date(aValue);
  303. bValue = new Date(bValue);
  304. }
  305. if (sortOrder === 'asc') {
  306. return aValue > bValue ? 1 : -1;
  307. } else {
  308. return aValue < bValue ? 1 : -1;
  309. }
  310. });
  311. return {
  312. routes: filteredRoutes,
  313. total: filteredRoutes.length,
  314. page: searchParams.page || 1,
  315. pageSize: searchParams.pageSize || 20
  316. };
  317. }
  318. // 获取路线统计信息
  319. getRouteStatistics() {
  320. const routes = this.getAllRoutes();
  321. const stats = {
  322. total: routes.length,
  323. byType: {},
  324. byStatus: {},
  325. byActivity: {},
  326. totalSchedules: 0,
  327. totalTickets: 0,
  328. soldTickets: 0
  329. };
  330. routes.forEach(route => {
  331. // 按类型统计
  332. stats.byType[route.type] = (stats.byType[route.type] || 0) + 1;
  333. // 按状态统计
  334. stats.byStatus[route.status] = (stats.byStatus[route.status] || 0) + 1;
  335. // 按活动统计
  336. stats.byActivity[route.activityId] = (stats.byActivity[route.activityId] || 0) + 1;
  337. // 班次统计
  338. stats.totalSchedules += route.schedules.length;
  339. route.schedules.forEach(schedule => {
  340. stats.totalTickets += schedule.totalTickets;
  341. stats.soldTickets += schedule.soldTickets;
  342. });
  343. });
  344. return stats;
  345. }
  346. // 批量更新路线状态
  347. batchUpdateRouteStatus(routeIds, status) {
  348. const routes = this.getAllRoutes();
  349. const updatedRoutes = routes.map(route => {
  350. if (routeIds.includes(route.id)) {
  351. return {
  352. ...route,
  353. status,
  354. updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19)
  355. };
  356. }
  357. return route;
  358. });
  359. this.saveRoutes(updatedRoutes);
  360. return true;
  361. }
  362. // 导出路线数据
  363. exportRoutes(searchParams = {}) {
  364. const result = this.searchRoutes(searchParams);
  365. return {
  366. routes: result.routes,
  367. exportTime: new Date().toISOString(),
  368. total: result.total,
  369. searchParams
  370. };
  371. }
  372. // 生成路线ID
  373. generateRouteId() {
  374. const timestamp = Date.now();
  375. const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
  376. return `route_${timestamp}_${random}`;
  377. }
  378. // 生成班次ID
  379. generateScheduleId() {
  380. const timestamp = Date.now();
  381. const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
  382. return `schedule_${timestamp}_${random}`;
  383. }
  384. // 监听器管理
  385. addListener(callback) {
  386. this.listeners.push(callback);
  387. }
  388. removeListener(callback) {
  389. const index = this.listeners.indexOf(callback);
  390. if (index > -1) {
  391. this.listeners.splice(index, 1);
  392. }
  393. }
  394. notifyListeners(routes) {
  395. this.listeners.forEach(callback => {
  396. try {
  397. callback(routes);
  398. } catch (error) {
  399. console.error('路线数据监听器回调执行失败:', error);
  400. }
  401. });
  402. }
  403. // 同步路线数据
  404. syncRouteData() {
  405. const routes = this.getAllRoutes();
  406. this.notifyListeners(routes);
  407. return routes;
  408. }
  409. }
  410. // 创建单例实例
  411. const routeApiService = new RouteApiService();
  412. export default routeApiService;