seed.ts 17 KB

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