schools.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. 'use strict';
  2. // 校区地图:学校列表(JSON 种子 + 运行时),附带运营数据关联统计。
  3. // 本期只有只读接口;新建/编辑/启停在下一增量实现。
  4. const { sendJson } = require('../util.js');
  5. const { loadSchools } = require('../../schools-store.js');
  6. const { createOpsStore } = require('../../ops-store.js');
  7. function namesOf(school) {
  8. return new Set([school.name, ...(school.aliases || [])].map((n) => String(n).trim()).filter(Boolean));
  9. }
  10. function register(app, ctx) {
  11. const opsStore = createOpsStore(ctx.config);
  12. app.get('/api/schools', async ({ res }) => {
  13. const schools = loadSchools();
  14. // 关联运营数据:按学校名(含别名)匹配 ops_shop.school 与 ops_row.school
  15. let shops = [];
  16. let rows = [];
  17. let platformRows = [];
  18. let opsAvailable = false;
  19. try {
  20. const summary = await opsStore.summary();
  21. shops = summary.shops || [];
  22. rows = await opsStore.queryRows({});
  23. platformRows = await opsStore.queryPlatformRows({});
  24. opsAvailable = true;
  25. } catch { /* ops 库不可用:只影响关联字段 */ }
  26. const payload = schools.map((school) => {
  27. const names = namesOf(school);
  28. // 门店口径:人工表的 shop_key 与平台明细的 shopId 取并集
  29. const shopKeys = new Set();
  30. for (const shop of shops) {
  31. if (names.has(String(shop.school || ''))) shopKeys.add(String(shop.key || shop.shopId || ''));
  32. }
  33. for (const row of platformRows) {
  34. if (names.has(String(row.school || ''))) shopKeys.add(String(row.shopId || ''));
  35. }
  36. shopKeys.delete('');
  37. const shopCount = shopKeys.size;
  38. let lastDate = '';
  39. for (const row of rows) {
  40. if (!names.has(String(row.school || ''))) continue;
  41. if (!lastDate || row.date > lastDate) lastDate = row.date;
  42. }
  43. for (const row of platformRows) {
  44. if (!names.has(String(row.school || ''))) continue;
  45. if (!lastDate || row.date > lastDate) lastDate = row.date;
  46. }
  47. return {
  48. ...school,
  49. ops: opsAvailable ? { shopCount, lastDate: lastDate || null } : null,
  50. };
  51. });
  52. sendJson(res, 200, {
  53. schools: payload,
  54. opsAvailable,
  55. enabledCount: payload.filter((s) => s.enabled && s.lng != null).length,
  56. });
  57. });
  58. }
  59. module.exports = { register };