area.service.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import { DataSource, Repository } from 'typeorm';
  2. import { AreaEntity, AreaLevel } from './area.entity';
  3. import { CreateAreaInput, UpdateAreaInput } from './area.schema';
  4. import { DisabledStatus } from '@/share/types';
  5. export class AreaService {
  6. private areaRepository: Repository<AreaEntity>;
  7. constructor(private dataSource: DataSource) {
  8. this.areaRepository = this.dataSource.getRepository(AreaEntity);
  9. }
  10. /**
  11. * 创建省市区
  12. */
  13. async create(input: CreateAreaInput): Promise<AreaEntity> {
  14. const area = this.areaRepository.create(input);
  15. return await this.areaRepository.save(area);
  16. }
  17. /**
  18. * 更新省市区
  19. */
  20. async update(id: number, input: UpdateAreaInput): Promise<AreaEntity | null> {
  21. const area = await this.areaRepository.findOne({ where: { id } });
  22. if (!area) {
  23. return null;
  24. }
  25. Object.assign(area, input);
  26. return await this.areaRepository.save(area);
  27. }
  28. /**
  29. * 获取省市区详情
  30. */
  31. async findById(id: number): Promise<AreaEntity | null> {
  32. return await this.areaRepository.findOne({
  33. where: { id },
  34. relations: ['parent', 'children']
  35. });
  36. }
  37. /**
  38. * 获取省市区列表
  39. */
  40. async findAll(params: {
  41. keyword?: string;
  42. level?: AreaLevel;
  43. parentId?: number;
  44. isDisabled?: DisabledStatus;
  45. page?: number;
  46. pageSize?: number;
  47. sortBy?: string;
  48. sortOrder?: 'ASC' | 'DESC';
  49. }): Promise<{ data: AreaEntity[]; total: number }> {
  50. const {
  51. keyword,
  52. level,
  53. parentId,
  54. isDisabled,
  55. page = 1,
  56. pageSize = 20,
  57. sortBy = 'createdAt',
  58. sortOrder = 'DESC'
  59. } = params;
  60. const queryBuilder = this.areaRepository
  61. .createQueryBuilder('area')
  62. .leftJoinAndSelect('area.parent', 'parent')
  63. .leftJoinAndSelect('area.children', 'children')
  64. .where('area.isDeleted = :isDeleted', { isDeleted: 0 });
  65. // 关键词搜索
  66. if (keyword) {
  67. queryBuilder.andWhere('(area.name LIKE :keyword OR area.code LIKE :keyword)', {
  68. keyword: `%${keyword}%`
  69. });
  70. }
  71. // 层级筛选
  72. if (level) {
  73. queryBuilder.andWhere('area.level = :level', { level });
  74. }
  75. // 父级ID筛选
  76. if (parentId !== undefined) {
  77. queryBuilder.andWhere('area.parentId = :parentId', { parentId });
  78. }
  79. // 状态筛选
  80. if (isDisabled !== undefined) {
  81. queryBuilder.andWhere('area.isDisabled = :isDisabled', { isDisabled });
  82. }
  83. // 排序
  84. const orderBy = `area.${sortBy}`;
  85. queryBuilder.orderBy(orderBy, sortOrder);
  86. // 分页
  87. const [data, total] = await queryBuilder
  88. .skip((page - 1) * pageSize)
  89. .take(pageSize)
  90. .getManyAndCount();
  91. return { data, total };
  92. }
  93. /**
  94. * 删除省市区(软删除)
  95. */
  96. async delete(id: number): Promise<boolean> {
  97. const result = await this.areaRepository.update(id, { isDeleted: 1 });
  98. return result.affected !== 0;
  99. }
  100. /**
  101. * 启用/禁用省市区
  102. */
  103. async toggleStatus(id: number, isDisabled: DisabledStatus): Promise<boolean> {
  104. const result = await this.areaRepository.update(id, { isDisabled });
  105. return result.affected !== 0;
  106. }
  107. /**
  108. * 根据层级获取省市区列表
  109. */
  110. async findByLevel(level: AreaLevel): Promise<AreaEntity[]> {
  111. return await this.areaRepository.find({
  112. where: {
  113. level,
  114. isDeleted: 0,
  115. isDisabled: DisabledStatus.ENABLED
  116. },
  117. order: { name: 'ASC' }
  118. });
  119. }
  120. /**
  121. * 根据父级ID获取子级省市区列表
  122. */
  123. async findByParentId(parentId: number): Promise<AreaEntity[]> {
  124. return await this.areaRepository.find({
  125. where: {
  126. parentId,
  127. isDeleted: 0,
  128. isDisabled: DisabledStatus.ENABLED
  129. },
  130. order: { name: 'ASC' }
  131. });
  132. }
  133. /**
  134. * 获取省市区完整路径
  135. */
  136. async getAreaPath(id: number): Promise<AreaEntity[]> {
  137. const path: AreaEntity[] = [];
  138. let currentArea = await this.areaRepository.findOne({
  139. where: { id },
  140. relations: ['parent']
  141. });
  142. while (currentArea) {
  143. path.unshift(currentArea);
  144. if (currentArea.parentId === null || currentArea.parentId === 0) {
  145. break;
  146. }
  147. currentArea = await this.areaRepository.findOne({
  148. where: { id: currentArea.parentId },
  149. relations: ['parent']
  150. });
  151. }
  152. return path;
  153. }
  154. /**
  155. * 获取省份列表
  156. */
  157. async getProvinces(): Promise<AreaEntity[]> {
  158. return await this.findByLevel(AreaLevel.PROVINCE);
  159. }
  160. /**
  161. * 根据省份ID获取城市列表
  162. */
  163. async getCitiesByProvinceId(provinceId: number): Promise<AreaEntity[]> {
  164. return await this.findByParentId(provinceId);
  165. }
  166. /**
  167. * 根据城市ID获取区县列表
  168. */
  169. async getDistrictsByCityId(cityId: number): Promise<AreaEntity[]> {
  170. return await this.findByParentId(cityId);
  171. }
  172. }