seed.ts 17 KB

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