seed.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. import { AppDataSource } from '../src/server/data-source.js';
  2. import { ActivityEntity, ActivityType } from '../src/server/modules/activities/activity.entity.js';
  3. import { RouteEntity } from '../src/server/modules/routes/route.entity.js';
  4. import { VehicleType } from '../src/server/modules/routes/route.schema.js';
  5. import { LocationEntity } from '../src/server/modules/locations/location.entity.js';
  6. import fs from 'fs';
  7. async function seed() {
  8. console.log('开始创建种子数据...');
  9. try {
  10. // 初始化数据库连接
  11. await AppDataSource.initialize();
  12. console.log('数据库连接已建立');
  13. // 获取Repository
  14. const activityRepository = AppDataSource.getRepository(ActivityEntity);
  15. const routeRepository = AppDataSource.getRepository(RouteEntity);
  16. const locationRepository = AppDataSource.getRepository(LocationEntity);
  17. // 清空现有数据
  18. await routeRepository.createQueryBuilder().delete().execute();
  19. await activityRepository.createQueryBuilder().delete().execute();
  20. await locationRepository.createQueryBuilder().delete().execute();
  21. console.log('已清空现有数据');
  22. // 导入省市区数据
  23. console.log('导入省市区数据...');
  24. const areaSqlPath = './scripts/area_data_init.sql';
  25. if (fs.existsSync(areaSqlPath)) {
  26. const areaSql = fs.readFileSync(areaSqlPath, 'utf-8');
  27. await AppDataSource.query(areaSql);
  28. console.log('省市区数据导入完成');
  29. } else {
  30. console.warn('省市区SQL文件不存在,跳过导入');
  31. }
  32. // 创建示例地点数据
  33. console.log('创建地点数据...');
  34. const locations = [
  35. // 北京地点
  36. {
  37. name: '工人体育场',
  38. provinceId: 1, // 北京市
  39. cityId: 34, // 市辖区 (北京市的市级行政区)
  40. districtId: 40, // 朝阳区
  41. address: '北京市朝阳区工人体育场北路',
  42. latitude: 39.929986,
  43. longitude: 116.447221,
  44. },
  45. {
  46. name: '鸟巢',
  47. provinceId: 1, // 北京市
  48. cityId: 34, // 市辖区 (北京市的市级行政区)
  49. districtId: 40, // 朝阳区
  50. address: '北京市朝阳区国家体育场南路1号',
  51. latitude: 39.992894,
  52. longitude: 116.396284,
  53. },
  54. {
  55. name: '五棵松体育馆',
  56. provinceId: 1, // 北京市
  57. cityId: 34, // 市辖区 (北京市的市级行政区)
  58. districtId: 43, // 海淀区
  59. address: '北京市海淀区复兴路69号',
  60. latitude: 39.9042,
  61. longitude: 116.2734,
  62. },
  63. {
  64. name: '中关村',
  65. provinceId: 1, // 北京市
  66. cityId: 34, // 市辖区 (北京市的市级行政区)
  67. districtId: 43, // 海淀区
  68. address: '北京市海淀区中关村大街',
  69. latitude: 39.9836,
  70. longitude: 116.3184,
  71. },
  72. {
  73. name: '国贸',
  74. provinceId: 1, // 北京市
  75. cityId: 34, // 市辖区 (北京市的市级行政区)
  76. districtId: 40, // 朝阳区
  77. address: '北京市朝阳区建国门外大街1号',
  78. latitude: 39.9092,
  79. longitude: 116.4558,
  80. },
  81. {
  82. name: '望京',
  83. provinceId: 1, // 北京市
  84. cityId: 34, // 市辖区 (北京市的市级行政区)
  85. districtId: 40, // 朝阳区
  86. address: '北京市朝阳区望京街道',
  87. latitude: 39.9895,
  88. longitude: 116.4815,
  89. },
  90. {
  91. name: '五道口',
  92. provinceId: 1, // 北京市
  93. cityId: 34, // 市辖区 (北京市的市级行政区)
  94. districtId: 43, // 海淀区
  95. address: '北京市海淀区五道口',
  96. latitude: 39.9969,
  97. longitude: 116.3375,
  98. },
  99. {
  100. name: '西直门',
  101. provinceId: 1, // 北京市
  102. cityId: 34, // 市辖区 (北京市的市级行政区)
  103. districtId: 37, // 西城区
  104. address: '北京市西城区西直门外大街',
  105. latitude: 39.9416,
  106. longitude: 116.3556,
  107. },
  108. {
  109. name: '朝阳门',
  110. provinceId: 1, // 北京市
  111. cityId: 34, // 市辖区 (北京市的市级行政区)
  112. districtId: 40, // 朝阳区
  113. address: '北京市朝阳区朝阳门外大街',
  114. latitude: 39.9244,
  115. longitude: 116.4342,
  116. },
  117. ];
  118. // 保存地点数据
  119. const savedLocations = await locationRepository.save(locations);
  120. console.log(`已创建 ${savedLocations.length} 个地点`);
  121. // 创建示例活动数据 - 赛事和演唱会相关
  122. const activities = [
  123. {
  124. name: '中超联赛北京国安主场赛事',
  125. description: '北京国安主场对阵上海申花的中超联赛',
  126. type: ActivityType.DEPARTURE,
  127. startDate: new Date('2025-10-15T00:00:00Z'),
  128. endDate: new Date('2025-10-15T23:59:59Z'),
  129. venueLocationId: savedLocations[0].id, // 工人体育场
  130. },
  131. {
  132. name: '中超联赛北京国安主场赛事返程',
  133. description: '北京国安主场赛事结束后的返程服务',
  134. type: ActivityType.RETURN,
  135. startDate: new Date('2025-10-15T21:00:00Z'),
  136. endDate: new Date('2025-10-16T02:00:00Z'),
  137. venueLocationId: savedLocations[0].id, // 工人体育场
  138. },
  139. {
  140. name: '周杰伦北京演唱会',
  141. description: '周杰伦北京演唱会专场',
  142. type: ActivityType.DEPARTURE,
  143. startDate: new Date('2025-11-01T00:00:00Z'),
  144. endDate: new Date('2025-11-01T23:59:59Z'),
  145. venueLocationId: savedLocations[1].id, // 鸟巢
  146. },
  147. {
  148. name: '周杰伦北京演唱会返程',
  149. description: '周杰伦演唱会结束后的返程服务',
  150. type: ActivityType.RETURN,
  151. startDate: new Date('2025-11-01T22:30:00Z'),
  152. endDate: new Date('2025-11-02T01:00:00Z'),
  153. venueLocationId: savedLocations[1].id, // 鸟巢
  154. },
  155. {
  156. name: 'CBA北京首钢主场赛事',
  157. description: '北京首钢主场对阵广东宏远的CBA联赛',
  158. type: ActivityType.DEPARTURE,
  159. startDate: new Date('2025-10-20T00:00:00Z'),
  160. endDate: new Date('2025-10-20T23:59:59Z'),
  161. venueLocationId: savedLocations[2].id, // 五棵松体育馆
  162. },
  163. {
  164. name: 'CBA北京首钢主场赛事返程',
  165. description: '北京首钢主场赛事结束后的返程服务',
  166. type: ActivityType.RETURN,
  167. startDate: new Date('2025-10-20T21:30:00Z'),
  168. endDate: new Date('2025-10-21T00:30:00Z'),
  169. venueLocationId: savedLocations[2].id, // 五棵松体育馆
  170. },
  171. ];
  172. // 保存活动数据
  173. const savedActivities = await activityRepository.save(activities);
  174. console.log(`已创建 ${savedActivities.length} 个活动`);
  175. // 创建示例路线数据 - 赛事和演唱会相关
  176. const routes = [
  177. // 中超联赛去程路线
  178. {
  179. name: '中关村-工人体育场专线',
  180. description: '中关村到工人体育场的中超联赛专线',
  181. startPoint: '中关村',
  182. endPoint: '工人体育场',
  183. pickupPoint: '中关村地铁站A口',
  184. dropoffPoint: '工人体育场北门',
  185. departureTime: new Date('2025-10-15T17:30:00Z'),
  186. vehicleType: VehicleType.BUS,
  187. price: 25,
  188. seatCount: 50,
  189. availableSeats: 45,
  190. activityId: savedActivities[0].id,
  191. startLocationId: savedLocations[3].id, // 中关村
  192. endLocationId: savedLocations[0].id, // 工人体育场
  193. },
  194. {
  195. name: '国贸-工人体育场专线',
  196. description: '国贸到工人体育场的中超联赛专线',
  197. startPoint: '国贸',
  198. endPoint: '工人体育场',
  199. pickupPoint: '国贸地铁站C口',
  200. dropoffPoint: '工人体育场东门',
  201. departureTime: new Date('2025-10-15T17:45:00Z'),
  202. vehicleType: VehicleType.MINIBUS,
  203. price: 20,
  204. seatCount: 30,
  205. availableSeats: 28,
  206. activityId: savedActivities[0].id,
  207. startLocationId: savedLocations[4].id, // 国贸
  208. endLocationId: savedLocations[0].id, // 工人体育场
  209. },
  210. {
  211. name: '望京-工人体育场专线',
  212. description: '望京到工人体育场的中超联赛专线',
  213. startPoint: '望京',
  214. endPoint: '工人体育场',
  215. pickupPoint: '望京地铁站S口',
  216. dropoffPoint: '工人体育场南门',
  217. departureTime: new Date('2025-10-15T18:00:00Z'),
  218. vehicleType: VehicleType.CAR,
  219. price: 35,
  220. seatCount: 15,
  221. availableSeats: 12,
  222. activityId: savedActivities[0].id,
  223. startLocationId: savedLocations[5].id, // 望京
  224. endLocationId: savedLocations[0].id, // 工人体育场
  225. },
  226. // 中超联赛返程路线
  227. {
  228. name: '工人体育场-中关村返程专线',
  229. description: '工人体育场到中关村的中超联赛返程专线',
  230. startPoint: '工人体育场',
  231. endPoint: '中关村',
  232. pickupPoint: '工人体育场北门',
  233. dropoffPoint: '中关村地铁站A口',
  234. departureTime: new Date('2025-10-15T22:00:00Z'),
  235. vehicleType: VehicleType.BUS,
  236. price: 25,
  237. seatCount: 50,
  238. availableSeats: 40,
  239. activityId: savedActivities[1].id,
  240. startLocationId: savedLocations[0].id, // 工人体育场
  241. endLocationId: savedLocations[3].id, // 中关村
  242. },
  243. {
  244. name: '工人体育场-国贸返程专线',
  245. description: '工人体育场到国贸的中超联赛返程专线',
  246. startPoint: '工人体育场',
  247. endPoint: '国贸',
  248. pickupPoint: '工人体育场东门',
  249. dropoffPoint: '国贸地铁站C口',
  250. departureTime: new Date('2025-10-15T22:15:00Z'),
  251. vehicleType: VehicleType.MINIBUS,
  252. price: 20,
  253. seatCount: 30,
  254. availableSeats: 25,
  255. activityId: savedActivities[1].id,
  256. startLocationId: savedLocations[0].id, // 工人体育场
  257. endLocationId: savedLocations[4].id, // 国贸
  258. },
  259. // 周杰伦演唱会去程路线
  260. {
  261. name: '五道口-鸟巢演唱会专线',
  262. description: '五道口到鸟巢的周杰伦演唱会专线',
  263. startPoint: '五道口',
  264. endPoint: '鸟巢',
  265. pickupPoint: '五道口地铁站A口',
  266. dropoffPoint: '鸟巢东门',
  267. departureTime: new Date('2025-11-01T18:00:00Z'),
  268. vehicleType: VehicleType.BUS,
  269. price: 30,
  270. seatCount: 50,
  271. availableSeats: 48,
  272. activityId: savedActivities[2].id,
  273. startLocationId: savedLocations[6].id, // 五道口
  274. endLocationId: savedLocations[1].id, // 鸟巢
  275. },
  276. {
  277. name: '西直门-鸟巢演唱会专线',
  278. description: '西直门到鸟巢的周杰伦演唱会专线',
  279. startPoint: '西直门',
  280. endPoint: '鸟巢',
  281. pickupPoint: '西直门地铁站C口',
  282. dropoffPoint: '鸟巢西门',
  283. departureTime: new Date('2025-11-01T18:15:00Z'),
  284. vehicleType: VehicleType.MINIBUS,
  285. price: 25,
  286. seatCount: 30,
  287. availableSeats: 28,
  288. activityId: savedActivities[2].id,
  289. startLocationId: savedLocations[7].id, // 西直门
  290. endLocationId: savedLocations[1].id, // 鸟巢
  291. },
  292. // 周杰伦演唱会返程路线
  293. {
  294. name: '鸟巢-五道口返程专线',
  295. description: '鸟巢到五道口的周杰伦演唱会返程专线',
  296. startPoint: '鸟巢',
  297. endPoint: '五道口',
  298. pickupPoint: '鸟巢东门',
  299. dropoffPoint: '五道口地铁站A口',
  300. departureTime: new Date('2025-11-01T23:30:00Z'),
  301. vehicleType: VehicleType.BUS,
  302. price: 30,
  303. seatCount: 50,
  304. availableSeats: 45,
  305. activityId: savedActivities[3].id,
  306. startLocationId: savedLocations[1].id, // 鸟巢
  307. endLocationId: savedLocations[6].id, // 五道口
  308. },
  309. {
  310. name: '鸟巢-西直门返程专线',
  311. description: '鸟巢到西直门的周杰伦演唱会返程专线',
  312. startPoint: '鸟巢',
  313. endPoint: '西直门',
  314. pickupPoint: '鸟巢西门',
  315. dropoffPoint: '西直门地铁站C口',
  316. departureTime: new Date('2025-11-01T23:45:00Z'),
  317. vehicleType: VehicleType.MINIBUS,
  318. price: 25,
  319. seatCount: 30,
  320. availableSeats: 26,
  321. activityId: savedActivities[3].id,
  322. startLocationId: savedLocations[1].id, // 鸟巢
  323. endLocationId: savedLocations[7].id, // 西直门
  324. },
  325. // CBA赛事去程路线
  326. {
  327. name: '朝阳门-五棵松体育馆专线',
  328. description: '朝阳门到五棵松体育馆的CBA赛事专线',
  329. startPoint: '朝阳门',
  330. endPoint: '五棵松体育馆',
  331. pickupPoint: '朝阳门地铁站B口',
  332. dropoffPoint: '五棵松体育馆北门',
  333. departureTime: new Date('2025-10-20T18:30:00Z'),
  334. vehicleType: VehicleType.BUS,
  335. price: 20,
  336. seatCount: 50,
  337. availableSeats: 46,
  338. activityId: savedActivities[4].id,
  339. startLocationId: savedLocations[8].id, // 朝阳门
  340. endLocationId: savedLocations[2].id, // 五棵松体育馆
  341. },
  342. // CBA赛事返程路线
  343. {
  344. name: '五棵松体育馆-朝阳门返程专线',
  345. description: '五棵松体育馆到朝阳门的CBA赛事返程专线',
  346. startPoint: '五棵松体育馆',
  347. endPoint: '朝阳门',
  348. pickupPoint: '五棵松体育馆北门',
  349. dropoffPoint: '朝阳门地铁站B口',
  350. departureTime: new Date('2025-10-20T22:00:00Z'),
  351. vehicleType: VehicleType.BUS,
  352. price: 20,
  353. seatCount: 50,
  354. availableSeats: 42,
  355. activityId: savedActivities[5].id,
  356. startLocationId: savedLocations[2].id, // 五棵松体育馆
  357. endLocationId: savedLocations[8].id, // 朝阳门
  358. },
  359. ];
  360. // 保存路线数据
  361. const savedRoutes = await routeRepository.save(routes);
  362. console.log(`已创建 ${savedRoutes.length} 条路线`);
  363. console.log('种子数据创建完成!');
  364. console.log(`总计: 3280+ 个区域, ${savedLocations.length} 个地点, ${savedActivities.length} 个活动, ${savedRoutes.length} 条路线`);
  365. } catch (error) {
  366. console.error('创建种子数据时出错:', error);
  367. throw error;
  368. } finally {
  369. // 关闭数据库连接
  370. await AppDataSource.destroy();
  371. console.log('数据库连接已关闭');
  372. }
  373. }
  374. // 运行种子脚本
  375. seed().catch(console.error);