seed.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. import { AppDataSource } from '@d8d/server/data-source';
  2. import { ActivityEntity } 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. startDate: new Date('2025-10-15T00:00:00Z'),
  133. endDate: new Date('2025-10-15T23:59:59Z'),
  134. venueLocationId: savedLocations[0].id, // 工人体育场
  135. },
  136. {
  137. name: '中超联赛北京国安主场赛事',
  138. description: '北京国安主场赛事',
  139. startDate: new Date('2025-10-15T21:00:00Z'),
  140. endDate: new Date('2025-10-16T02:00:00Z'),
  141. venueLocationId: savedLocations[0].id, // 工人体育场
  142. },
  143. {
  144. name: '周杰伦北京演唱会',
  145. description: '周杰伦北京演唱会专场',
  146. startDate: new Date('2025-11-01T00:00:00Z'),
  147. endDate: new Date('2025-11-01T23:59:59Z'),
  148. venueLocationId: savedLocations[1].id, // 鸟巢
  149. },
  150. {
  151. name: '周杰伦北京演唱会',
  152. description: '周杰伦演唱会',
  153. startDate: new Date('2025-11-01T22:30:00Z'),
  154. endDate: new Date('2025-11-02T01:00:00Z'),
  155. venueLocationId: savedLocations[1].id, // 鸟巢
  156. },
  157. {
  158. name: 'CBA北京首钢主场赛事',
  159. description: '北京首钢主场对阵广东宏远的CBA联赛',
  160. startDate: new Date('2025-10-20T00:00:00Z'),
  161. endDate: new Date('2025-10-20T23:59:59Z'),
  162. venueLocationId: savedLocations[2].id, // 五棵松体育馆
  163. },
  164. {
  165. name: 'CBA北京首钢主场赛事',
  166. description: '北京首钢主场赛事',
  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. travelMode: TravelMode.CARPOOL,
  188. price: 25,
  189. seatCount: 50,
  190. availableSeats: 45,
  191. activityId: savedActivities[0].id,
  192. startLocationId: savedLocations[3].id, // 中关村
  193. endLocationId: savedLocations[0].id, // 工人体育场
  194. },
  195. // 商务车拼车场景
  196. {
  197. name: '国贸-工人体育场专线',
  198. description: '国贸到工人体育场的中超联赛专线',
  199. startPoint: '国贸',
  200. endPoint: '工人体育场',
  201. pickupPoint: '国贸地铁站C口',
  202. dropoffPoint: '工人体育场东门',
  203. departureTime: new Date('2025-10-15T17:45:00Z'),
  204. vehicleType: VehicleType.BUSINESS,
  205. travelMode: TravelMode.CARPOOL,
  206. price: 35,
  207. seatCount: 8,
  208. availableSeats: 6,
  209. activityId: savedActivities[0].id,
  210. startLocationId: savedLocations[4].id, // 国贸
  211. endLocationId: savedLocations[0].id, // 工人体育场
  212. },
  213. // 商务车包车场景
  214. {
  215. name: '望京-工人体育场专线',
  216. description: '望京到工人体育场的中超联赛专线',
  217. startPoint: '望京',
  218. endPoint: '工人体育场',
  219. pickupPoint: '望京地铁站S口',
  220. dropoffPoint: '工人体育场南门',
  221. departureTime: new Date('2025-10-15T18:00:00Z'),
  222. vehicleType: VehicleType.BUSINESS,
  223. travelMode: TravelMode.CHARTER,
  224. price: 150,
  225. seatCount: 8,
  226. availableSeats: 8,
  227. activityId: savedActivities[0].id,
  228. startLocationId: savedLocations[5].id, // 望京
  229. endLocationId: savedLocations[0].id, // 工人体育场
  230. },
  231. // 中超联赛返程路线 - 大巴拼车场景
  232. {
  233. name: '工人体育场-中关村返程专线',
  234. description: '工人体育场到中关村的中超联赛返程专线',
  235. startPoint: '工人体育场',
  236. endPoint: '中关村',
  237. pickupPoint: '工人体育场北门',
  238. dropoffPoint: '中关村地铁站A口',
  239. departureTime: new Date('2025-10-15T22:00:00Z'),
  240. vehicleType: VehicleType.BUS,
  241. travelMode: TravelMode.CARPOOL,
  242. price: 25,
  243. seatCount: 50,
  244. availableSeats: 40,
  245. activityId: savedActivities[1].id,
  246. startLocationId: savedLocations[0].id, // 工人体育场
  247. endLocationId: savedLocations[3].id, // 中关村
  248. },
  249. // 大巴包车场景
  250. {
  251. name: '工人体育场-国贸返程专线',
  252. description: '工人体育场到国贸的中超联赛返程专线',
  253. startPoint: '工人体育场',
  254. endPoint: '国贸',
  255. pickupPoint: '工人体育场东门',
  256. dropoffPoint: '国贸地铁站C口',
  257. departureTime: new Date('2025-10-15T22:15:00Z'),
  258. vehicleType: VehicleType.BUS,
  259. travelMode: TravelMode.CHARTER,
  260. price: 300,
  261. seatCount: 50,
  262. availableSeats: 50,
  263. activityId: savedActivities[1].id,
  264. startLocationId: savedLocations[0].id, // 工人体育场
  265. endLocationId: savedLocations[4].id, // 国贸
  266. },
  267. // 周杰伦演唱会去程路线 - 大巴拼车场景
  268. {
  269. name: '五道口-鸟巢演唱会专线',
  270. description: '五道口到鸟巢的周杰伦演唱会专线',
  271. startPoint: '五道口',
  272. endPoint: '鸟巢',
  273. pickupPoint: '五道口地铁站A口',
  274. dropoffPoint: '鸟巢东门',
  275. departureTime: new Date('2025-11-01T18:00:00Z'),
  276. vehicleType: VehicleType.BUS,
  277. travelMode: TravelMode.CARPOOL,
  278. price: 30,
  279. seatCount: 50,
  280. availableSeats: 48,
  281. activityId: savedActivities[2].id,
  282. startLocationId: savedLocations[6].id, // 五道口
  283. endLocationId: savedLocations[1].id, // 鸟巢
  284. },
  285. // 商务车拼车场景
  286. {
  287. name: '西直门-鸟巢演唱会专线',
  288. description: '西直门到鸟巢的周杰伦演唱会专线',
  289. startPoint: '西直门',
  290. endPoint: '鸟巢',
  291. pickupPoint: '西直门地铁站C口',
  292. dropoffPoint: '鸟巢西门',
  293. departureTime: new Date('2025-11-01T18:15:00Z'),
  294. vehicleType: VehicleType.BUSINESS,
  295. travelMode: TravelMode.CARPOOL,
  296. price: 40,
  297. seatCount: 8,
  298. availableSeats: 6,
  299. activityId: savedActivities[2].id,
  300. startLocationId: savedLocations[7].id, // 西直门
  301. endLocationId: savedLocations[1].id, // 鸟巢
  302. },
  303. // 周杰伦演唱会返程路线 - 大巴拼车场景
  304. {
  305. name: '鸟巢-五道口返程专线',
  306. description: '鸟巢到五道口的周杰伦演唱会返程专线',
  307. startPoint: '鸟巢',
  308. endPoint: '五道口',
  309. pickupPoint: '鸟巢东门',
  310. dropoffPoint: '五道口地铁站A口',
  311. departureTime: new Date('2025-11-01T23:30:00Z'),
  312. vehicleType: VehicleType.BUS,
  313. travelMode: TravelMode.CARPOOL,
  314. price: 30,
  315. seatCount: 50,
  316. availableSeats: 45,
  317. activityId: savedActivities[3].id,
  318. startLocationId: savedLocations[1].id, // 鸟巢
  319. endLocationId: savedLocations[6].id, // 五道口
  320. },
  321. // 商务车包车场景
  322. {
  323. name: '鸟巢-西直门返程专线',
  324. description: '鸟巢到西直门的周杰伦演唱会返程专线',
  325. startPoint: '鸟巢',
  326. endPoint: '西直门',
  327. pickupPoint: '鸟巢西门',
  328. dropoffPoint: '西直门地铁站C口',
  329. departureTime: new Date('2025-11-01T23:45:00Z'),
  330. vehicleType: VehicleType.BUSINESS,
  331. travelMode: TravelMode.CHARTER,
  332. price: 180,
  333. seatCount: 8,
  334. availableSeats: 8,
  335. activityId: savedActivities[3].id,
  336. startLocationId: savedLocations[1].id, // 鸟巢
  337. endLocationId: savedLocations[7].id, // 西直门
  338. },
  339. // CBA赛事去程路线 - 大巴拼车场景
  340. {
  341. name: '朝阳门-五棵松体育馆专线',
  342. description: '朝阳门到五棵松体育馆的CBA赛事专线',
  343. startPoint: '朝阳门',
  344. endPoint: '五棵松体育馆',
  345. pickupPoint: '朝阳门地铁站B口',
  346. dropoffPoint: '五棵松体育馆北门',
  347. departureTime: new Date('2025-10-20T18:30:00Z'),
  348. vehicleType: VehicleType.BUS,
  349. travelMode: TravelMode.CARPOOL,
  350. price: 20,
  351. seatCount: 50,
  352. availableSeats: 46,
  353. activityId: savedActivities[4].id,
  354. startLocationId: savedLocations[8].id, // 朝阳门
  355. endLocationId: savedLocations[2].id, // 五棵松体育馆
  356. },
  357. // CBA赛事返程路线 - 大巴拼车场景
  358. {
  359. name: '五棵松体育馆-朝阳门返程专线',
  360. description: '五棵松体育馆到朝阳门的CBA赛事返程专线',
  361. startPoint: '五棵松体育馆',
  362. endPoint: '朝阳门',
  363. pickupPoint: '五棵松体育馆北门',
  364. dropoffPoint: '朝阳门地铁站B口',
  365. departureTime: new Date('2025-10-20T22:00:00Z'),
  366. vehicleType: VehicleType.BUS,
  367. travelMode: TravelMode.CARPOOL,
  368. price: 20,
  369. seatCount: 50,
  370. availableSeats: 42,
  371. activityId: savedActivities[5].id,
  372. startLocationId: savedLocations[2].id, // 五棵松体育馆
  373. endLocationId: savedLocations[8].id, // 朝阳门
  374. },
  375. ];
  376. // 保存路线数据
  377. const savedRoutes = await routeRepository.save(routes);
  378. console.log(`已创建 ${savedRoutes.length} 条路线`);
  379. // 创建示例乘客数据
  380. console.log('创建乘客数据...');
  381. // 获取现有用户(管理员用户)
  382. const existingUsers = await userRepository.find();
  383. let passengerCount = 0;
  384. if (existingUsers.length === 0) {
  385. console.warn('没有找到用户数据,跳过创建乘客数据');
  386. } else {
  387. const adminUser = existingUsers[0]; // 使用第一个用户(管理员)
  388. const passengers = [
  389. {
  390. userId: adminUser.id,
  391. name: '张三',
  392. idType: IdType.ID_CARD,
  393. idNumber: '110101199001011234',
  394. phone: '13800138001',
  395. isDefault: true
  396. },
  397. {
  398. userId: adminUser.id,
  399. name: '李四',
  400. idType: IdType.ID_CARD,
  401. idNumber: '110101199002022345',
  402. phone: '13800138002',
  403. isDefault: false
  404. },
  405. {
  406. userId: adminUser.id,
  407. name: '王五',
  408. idType: IdType.PASSPORT,
  409. idNumber: 'E12345678',
  410. phone: '13800138003',
  411. isDefault: false
  412. },
  413. {
  414. userId: adminUser.id,
  415. name: '赵六',
  416. idType: IdType.HONG_KONG_MACAO_PASS,
  417. idNumber: 'H123456789',
  418. phone: '13800138004',
  419. isDefault: false
  420. },
  421. {
  422. userId: adminUser.id,
  423. name: '钱七',
  424. idType: IdType.TAIWAN_PASS,
  425. idNumber: 'T123456789',
  426. phone: '13800138005',
  427. isDefault: false
  428. }
  429. ];
  430. // 保存乘客数据
  431. const savedPassengers = await passengerRepository.save(passengers);
  432. passengerCount = savedPassengers.length;
  433. console.log(`已创建 ${passengerCount} 个乘客`);
  434. }
  435. console.log('种子数据创建完成!');
  436. console.log(`总计: 3280+ 个区域, ${savedLocations.length} 个地点, ${savedActivities.length} 个活动, ${savedRoutes.length} 条路线, ${passengerCount} 个乘客`);
  437. } catch (error) {
  438. console.error('创建种子数据时出错:', error);
  439. throw error;
  440. } finally {
  441. // 关闭数据库连接
  442. await AppDataSource.destroy();
  443. console.log('数据库连接已关闭');
  444. }
  445. }
  446. // 运行种子脚本
  447. seed().catch(console.error);