export-api.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /**
  2. * 数据导出API接口系统
  3. * 支持活动、路线、班次等数据的表格导出功能
  4. */
  5. import activityApiService from './activity-api.js';
  6. import routeApiService from './route-api.js';
  7. import locationApiService from './location-api.js';
  8. import orderApiService from './order-api.js';
  9. class ExportApiService {
  10. constructor() {
  11. this.exportFormats = {
  12. excel: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  13. csv: 'text/csv',
  14. json: 'application/json'
  15. };
  16. }
  17. // 导出活动数据
  18. exportActivities(searchParams = {}, format = 'excel') {
  19. const activityData = activityApiService.exportActivities(searchParams);
  20. const exportData = {
  21. title: '活动数据导出',
  22. headers: [
  23. '活动ID', '活动名称', '活动描述', '开始日期', '结束日期',
  24. '城市', '场馆', '地址', '状态', '组织方', '联系电话', '邮箱', '创建时间'
  25. ],
  26. rows: activityData.activities.map(activity => [
  27. activity.id,
  28. activity.name,
  29. activity.description,
  30. activity.startDate,
  31. activity.endDate,
  32. activity.city,
  33. activity.venue,
  34. activity.address,
  35. activity.status,
  36. activity.organizer,
  37. activity.contact.phone,
  38. activity.contact.email,
  39. activity.createTime
  40. ]),
  41. metadata: {
  42. exportTime: activityData.exportTime,
  43. total: activityData.total,
  44. searchParams: activityData.searchParams
  45. }
  46. };
  47. return this.formatExportData(exportData, format);
  48. }
  49. // 导出路线数据
  50. exportRoutes(searchParams = {}, format = 'excel') {
  51. const routeData = routeApiService.exportRoutes(searchParams);
  52. const exportData = {
  53. title: '路线数据导出',
  54. headers: [
  55. '路线ID', '活动名称', '出发城市', '到达城市', '出发地点', '到达地点',
  56. '距离', '时长', '路线类型', '状态', '班次数量', '创建时间'
  57. ],
  58. rows: routeData.routes.map(route => [
  59. route.id,
  60. route.activityName,
  61. route.fromCity,
  62. route.toCity,
  63. route.fromLocation,
  64. route.toLocation,
  65. route.distance,
  66. route.duration,
  67. this.getRouteTypeName(route.type),
  68. route.status,
  69. route.schedules.length,
  70. route.createTime
  71. ]),
  72. metadata: {
  73. exportTime: routeData.exportTime,
  74. total: routeData.total,
  75. searchParams: routeData.searchParams
  76. }
  77. };
  78. return this.formatExportData(exportData, format);
  79. }
  80. // 导出班次数据
  81. exportSchedules(activityId = null, format = 'excel') {
  82. const routes = routeApiService.getAllRoutes();
  83. let schedules = [];
  84. if (activityId) {
  85. const activityRoutes = routes.filter(route => route.activityId === activityId);
  86. schedules = activityRoutes.flatMap(route =>
  87. route.schedules.map(schedule => ({
  88. ...schedule,
  89. routeId: route.id,
  90. activityName: route.activityName,
  91. fromLocation: route.fromLocation,
  92. toLocation: route.toLocation,
  93. routeType: route.type
  94. }))
  95. );
  96. } else {
  97. schedules = routes.flatMap(route =>
  98. route.schedules.map(schedule => ({
  99. ...schedule,
  100. routeId: route.id,
  101. activityName: route.activityName,
  102. fromLocation: route.fromLocation,
  103. toLocation: route.toLocation,
  104. routeType: route.type
  105. }))
  106. );
  107. }
  108. const exportData = {
  109. title: '班次数据导出',
  110. headers: [
  111. '班次ID', '路线ID', '活动名称', '出发地点', '到达地点', '出发时间',
  112. '到达时间', '总票数', '已售票数', '剩余票数', '票价', '车型',
  113. '司机姓名', '司机电话', '路线类型', '状态', '创建时间'
  114. ],
  115. rows: schedules.map(schedule => [
  116. schedule.id,
  117. schedule.routeId,
  118. schedule.activityName,
  119. schedule.fromLocation,
  120. schedule.toLocation,
  121. schedule.departureTime,
  122. schedule.arrivalTime,
  123. schedule.totalTickets,
  124. schedule.soldTickets,
  125. schedule.remainingTickets,
  126. schedule.price,
  127. schedule.vehicleModel,
  128. schedule.driver.name,
  129. schedule.driver.phone,
  130. this.getRouteTypeName(schedule.routeType),
  131. schedule.status,
  132. schedule.createTime
  133. ]),
  134. metadata: {
  135. exportTime: new Date().toISOString(),
  136. total: schedules.length,
  137. activityId
  138. }
  139. };
  140. return this.formatExportData(exportData, format);
  141. }
  142. // 导出订单数据
  143. exportOrders(searchParams = {}, format = 'excel') {
  144. const orderData = orderApiService.exportOrders(searchParams);
  145. const exportData = {
  146. title: '订单数据导出',
  147. headers: [
  148. '订单号', '活动名称', '出发地', '目的地', '出发时间', '乘客数量',
  149. '总金额', '订单状态', '创建时间', '支付时间', '联系人', '联系电话'
  150. ],
  151. rows: orderData.orders.map(order => [
  152. order.orderNo,
  153. order.activity,
  154. order.schedule.fromLoc,
  155. order.schedule.toLoc,
  156. `${order.schedule.date} ${order.schedule.time}`,
  157. order.passengers.length,
  158. order.totalPrice,
  159. order.status,
  160. order.createTime,
  161. order.paymentTime || '',
  162. order.contactInfo.name,
  163. order.contactInfo.phone
  164. ]),
  165. metadata: {
  166. exportTime: orderData.exportTime,
  167. total: orderData.total,
  168. searchParams: orderData.searchParams
  169. }
  170. };
  171. return this.formatExportData(exportData, format);
  172. }
  173. // 导出地区数据
  174. exportLocations(searchParams = {}, format = 'excel') {
  175. const locationData = locationApiService.exportLocations(searchParams);
  176. const exportData = {
  177. title: '地区数据导出',
  178. headers: [
  179. '地区ID', '地区名称', '地区代码', '层级', '父级ID', '排序', '状态', '创建时间'
  180. ],
  181. rows: locationData.locations.map(location => [
  182. location.id,
  183. location.name,
  184. location.code,
  185. this.getLevelName(location.level),
  186. location.parentId || '',
  187. location.sort,
  188. location.status,
  189. location.createTime
  190. ]),
  191. metadata: {
  192. exportTime: locationData.exportTime,
  193. total: locationData.total,
  194. searchParams: locationData.searchParams
  195. }
  196. };
  197. return this.formatExportData(exportData, format);
  198. }
  199. // 导出综合报表
  200. exportComprehensiveReport(activityId = null, format = 'excel') {
  201. const activities = activityId ?
  202. [activityApiService.getActivityById(activityId)] :
  203. activityApiService.getAllActivities();
  204. const reportData = {
  205. title: '综合数据报表',
  206. sections: []
  207. };
  208. activities.forEach(activity => {
  209. if (!activity) return;
  210. const routes = routeApiService.getRoutesByActivityId(activity.id);
  211. const orders = orderApiService.getAllOrders().filter(order =>
  212. order.activity === activity.name
  213. );
  214. // 活动基本信息
  215. reportData.sections.push({
  216. sectionTitle: `活动:${activity.name}`,
  217. headers: ['项目', '数值'],
  218. rows: [
  219. ['活动ID', activity.id],
  220. ['活动名称', activity.name],
  221. ['开始日期', activity.startDate],
  222. ['结束日期', activity.endDate],
  223. ['城市', activity.city],
  224. ['场馆', activity.venue],
  225. ['状态', activity.status]
  226. ]
  227. });
  228. // 路线统计
  229. reportData.sections.push({
  230. sectionTitle: '路线统计',
  231. headers: ['路线类型', '路线数量', '班次数量', '总票数', '已售票数', '总收入'],
  232. rows: this.getRouteStatistics(routes)
  233. });
  234. // 订单统计
  235. reportData.sections.push({
  236. sectionTitle: '订单统计',
  237. headers: ['订单号', '乘客数量', '金额', '状态', '创建时间'],
  238. rows: orders.map(order => [
  239. order.orderNo,
  240. order.passengers.length,
  241. order.totalPrice,
  242. order.status,
  243. order.createTime
  244. ])
  245. });
  246. });
  247. return this.formatComprehensiveData(reportData, format);
  248. }
  249. // 格式化导出数据
  250. formatExportData(data, format) {
  251. switch (format) {
  252. case 'csv':
  253. return this.formatAsCSV(data);
  254. case 'json':
  255. return this.formatAsJSON(data);
  256. case 'excel':
  257. default:
  258. return this.formatAsExcel(data);
  259. }
  260. }
  261. // 格式化为CSV
  262. formatAsCSV(data) {
  263. const csvContent = [
  264. data.headers.join(','),
  265. ...data.rows.map(row => row.map(cell => `"${cell}"`).join(','))
  266. ].join('\n');
  267. return {
  268. content: csvContent,
  269. mimeType: this.exportFormats.csv,
  270. filename: `${data.title}_${new Date().toISOString().split('T')[0]}.csv`
  271. };
  272. }
  273. // 格式化为JSON
  274. formatAsJSON(data) {
  275. const jsonData = {
  276. title: data.title,
  277. headers: data.headers,
  278. data: data.rows.map(row => {
  279. const obj = {};
  280. data.headers.forEach((header, index) => {
  281. obj[header] = row[index];
  282. });
  283. return obj;
  284. }),
  285. metadata: data.metadata
  286. };
  287. return {
  288. content: JSON.stringify(jsonData, null, 2),
  289. mimeType: this.exportFormats.json,
  290. filename: `${data.title}_${new Date().toISOString().split('T')[0]}.json`
  291. };
  292. }
  293. // 格式化为Excel(模拟)
  294. formatAsExcel(data) {
  295. // 在实际应用中,这里会使用专门的Excel库
  296. // 这里返回一个模拟的Excel数据结构
  297. return {
  298. content: {
  299. title: data.title,
  300. headers: data.headers,
  301. rows: data.rows,
  302. metadata: data.metadata
  303. },
  304. mimeType: this.exportFormats.excel,
  305. filename: `${data.title}_${new Date().toISOString().split('T')[0]}.xlsx`
  306. };
  307. }
  308. // 格式化综合数据
  309. formatComprehensiveData(data, format) {
  310. return {
  311. content: data,
  312. mimeType: this.exportFormats[format],
  313. filename: `${data.title}_${new Date().toISOString().split('T')[0]}.${format}`
  314. };
  315. }
  316. // 获取路线类型名称
  317. getRouteTypeName(type) {
  318. const typeMap = {
  319. 'bus': '大巴拼车',
  320. 'business': '商务车',
  321. 'charter': '包车'
  322. };
  323. return typeMap[type] || type;
  324. }
  325. // 获取层级名称
  326. getLevelName(level) {
  327. const levelMap = {
  328. 'province': '省份',
  329. 'city': '城市',
  330. 'district': '区县'
  331. };
  332. return levelMap[level] || level;
  333. }
  334. // 获取路线统计
  335. getRouteStatistics(routes) {
  336. const stats = {};
  337. routes.forEach(route => {
  338. if (!stats[route.type]) {
  339. stats[route.type] = {
  340. routeCount: 0,
  341. scheduleCount: 0,
  342. totalTickets: 0,
  343. soldTickets: 0,
  344. totalRevenue: 0
  345. };
  346. }
  347. stats[route.type].routeCount++;
  348. stats[route.type].scheduleCount += route.schedules.length;
  349. route.schedules.forEach(schedule => {
  350. stats[route.type].totalTickets += schedule.totalTickets;
  351. stats[route.type].soldTickets += schedule.soldTickets;
  352. stats[route.type].totalRevenue += schedule.soldTickets * schedule.price;
  353. });
  354. });
  355. return Object.keys(stats).map(type => [
  356. this.getRouteTypeName(type),
  357. stats[type].routeCount,
  358. stats[type].scheduleCount,
  359. stats[type].totalTickets,
  360. stats[type].soldTickets,
  361. stats[type].totalRevenue
  362. ]);
  363. }
  364. // 下载文件
  365. downloadFile(exportData) {
  366. // 在实际应用中,这里会触发文件下载
  367. console.log('下载文件:', exportData.filename);
  368. console.log('文件内容:', exportData.content);
  369. // 模拟下载成功
  370. return {
  371. success: true,
  372. filename: exportData.filename,
  373. size: JSON.stringify(exportData.content).length
  374. };
  375. }
  376. }
  377. // 创建单例实例
  378. const exportApiService = new ExportApiService();
  379. export default exportApiService;