dashboard-scope.util.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import type { GroupChatDto } from '../../apps/pc/qiwe/services/groups.service.js';
  2. import type { CommunityDto } from '../../apps/pc/qiwe/services/community.service.js';
  3. /** 上海城市范围默认门店编码 */
  4. export const SHANGHAI_STORE_CODE = 'SH001';
  5. /** 从小区地址解析上海区级名称,如「上海市黄浦区…」→「黄浦区」 */
  6. export function parseShanghaiDistrict(address: string): string | null {
  7. if (!address || !address.includes('上海')) return null;
  8. const m = address.match(/上海市([^市区县]+[市区县])/);
  9. return m?.[1] ?? null;
  10. }
  11. export function isShanghaiAddress(address: string): boolean {
  12. return Boolean(address && address.includes('上海'));
  13. }
  14. export interface CommunityDistrictIndex {
  15. byCommunityId: Map<string, string>;
  16. districts: string[];
  17. }
  18. export function buildCommunityDistrictIndex(communities: CommunityDto[]): CommunityDistrictIndex {
  19. const byCommunityId = new Map<string, string>();
  20. const districtSet = new Set<string>();
  21. for (const c of communities) {
  22. const district = parseShanghaiDistrict(c.address) || '其他';
  23. byCommunityId.set(c.id, district);
  24. if (isShanghaiAddress(c.address)) {
  25. districtSet.add(district);
  26. }
  27. }
  28. const districts = Array.from(districtSet).sort((a, b) => {
  29. if (a === '其他') return 1;
  30. if (b === '其他') return -1;
  31. return a.localeCompare(b, 'zh-CN');
  32. });
  33. return { byCommunityId, districts };
  34. }
  35. export function filterGroupsForDashboardScope(
  36. groups: GroupChatDto[],
  37. scope: {
  38. level: string;
  39. storeId?: string;
  40. shanghaiStoreId?: string;
  41. district?: string;
  42. roomId?: string;
  43. storeIds?: string[];
  44. communityIndex?: CommunityDistrictIndex;
  45. },
  46. ): GroupChatDto[] {
  47. if (scope.level === 'group' && scope.roomId) {
  48. return groups.filter((g) => g.roomId === scope.roomId);
  49. }
  50. let result = groups;
  51. if (scope.level === 'city' && scope.shanghaiStoreId) {
  52. const idx = scope.communityIndex;
  53. result = result.filter((g) => {
  54. if (!g.storeId || g.storeId === scope.shanghaiStoreId) return true;
  55. if (g.communityId && idx?.byCommunityId.has(g.communityId)) {
  56. const comm = idx.byCommunityId.get(g.communityId)!;
  57. return comm !== '其他';
  58. }
  59. return false;
  60. });
  61. } else if (scope.level === 'global') {
  62. // 全局:全部群(含未绑定门店的企微同步群)
  63. result = groups;
  64. } else if (scope.level === 'region' && scope.storeIds?.length) {
  65. const allowed = new Set(scope.storeIds);
  66. result = result.filter((g) => !g.storeId || allowed.has(g.storeId));
  67. } else if (scope.level === 'store' && scope.storeId) {
  68. // 门店:匹配门店 ID,或未绑定门店的群(企微同步常见)
  69. result = result.filter((g) => !g.storeId || g.storeId === scope.storeId);
  70. }
  71. if (scope.level === 'district' && scope.district && scope.communityIndex) {
  72. const idx = scope.communityIndex;
  73. if (scope.shanghaiStoreId) {
  74. result = result.filter((g) => {
  75. if (!g.storeId || g.storeId === scope.shanghaiStoreId) return true;
  76. if (g.communityId && idx.byCommunityId.has(g.communityId)) {
  77. return idx.byCommunityId.get(g.communityId)! !== '其他';
  78. }
  79. return false;
  80. });
  81. }
  82. result = result.filter((g) => {
  83. if (!g.communityId) return scope.district === '未分区';
  84. const d = idx.byCommunityId.get(g.communityId) || '未分区';
  85. return d === scope.district;
  86. });
  87. }
  88. return result;
  89. }