web.service.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import { BadRequestException, Injectable } from '@nestjs/common';
  2. import { InjectRepository } from '@nestjs/typeorm';
  3. import { In, LessThan, Like, MoreThan, Repository } from 'typeorm';
  4. import { Menu } from '@/modules/menu/menu.entity';
  5. import { SharedService } from '@/shared/shared.service';
  6. import { Article } from '@/modules/article/article.entity';
  7. import { Category } from '@/modules/category/category.entity';
  8. import { getTopMenuFragment } from '@/common/utils';
  9. import { CustomException, ErrorCode } from '@/common/exceptions/custom.exception';
  10. @Injectable()
  11. export class WebService {
  12. constructor(
  13. @InjectRepository(Menu)
  14. private menuRepo: Repository<Menu>,
  15. @InjectRepository(Article)
  16. private articleRepo: Repository<Article>,
  17. @InjectRepository(Category)
  18. private categoryRepo: Repository<Category>,
  19. private readonly sharedService: SharedService,
  20. ) {}
  21. async findMenuTree(locale?: string): Promise<Menu[]> {
  22. const lang = this.sharedService.handleValidLang(locale);
  23. const menus = await this.menuRepo.find({
  24. where: {
  25. enable: true,
  26. // isPublish: true,
  27. },
  28. order: {
  29. order: 'ASC',
  30. children: {
  31. order: 'ASC',
  32. },
  33. },
  34. relations: {
  35. children: true,
  36. category: true,
  37. translations: true,
  38. },
  39. select: {
  40. category: {
  41. id: true,
  42. title: true,
  43. },
  44. },
  45. });
  46. const allMenus = menus.map((menu) => (menu.translations?.length ? menu.translate(lang) : menu));
  47. // console.log('menus', lang, allMenus);
  48. return this.sharedService.handleTree(allMenus);
  49. }
  50. async findArticleDetail(id: number, locale?: string) {
  51. const lang = this.sharedService.handleValidLang(locale);
  52. const article = await this.articleRepo.findOne({
  53. where: { id, enable: true },
  54. relations: { user: true, translations: true, category: true },
  55. select: {
  56. user: {
  57. id: true,
  58. username: true,
  59. },
  60. category: {
  61. id: true,
  62. title: true,
  63. },
  64. },
  65. });
  66. return article ? article.translate(lang) : false;
  67. }
  68. async setArticleCount(id: number) {
  69. const article = await this.articleRepo.findOne({
  70. where: { id, enable: true },
  71. });
  72. if (!article) {
  73. return false;
  74. }
  75. article.readCount = article.readCount + 1;
  76. // console.log('article', article);
  77. await this.articleRepo.save(article);
  78. return true;
  79. }
  80. async getTopCategory1(id: number) {
  81. let currentCategory = await this.categoryRepo.findOne({
  82. where: { id, enable: true },
  83. relations: { parent: true },
  84. });
  85. if (!currentCategory) {
  86. return null; // 如果分类不存在,返回 null
  87. }
  88. // 递归查找顶层父分类
  89. while (currentCategory.parent) {
  90. currentCategory = await this.categoryRepo.findOne({
  91. where: { id: currentCategory.parent.id, enable: true },
  92. relations: { parent: true },
  93. });
  94. }
  95. console.log('currentCategory', currentCategory);
  96. return currentCategory.id
  97. ? this.categoryRepo.findOne({
  98. where: { id: currentCategory.id, enable: true },
  99. relations: { children: true },
  100. })
  101. : null;
  102. }
  103. async getCategoryTreeAndPath(id: number, locale: string) {
  104. const lang = this.sharedService.handleValidLang(locale);
  105. const categories = await this.categoryRepo.find({
  106. where: { enable: true },
  107. relations: { children: true, translations: true },
  108. });
  109. const data = this.sharedService.handleTree(categories.map((cate) => cate.translate(lang)));
  110. return getTopMenuFragment(data, id);
  111. }
  112. async searchArticles(key: string, locale?: string) {
  113. const lang = this.sharedService.handleValidLang(locale);
  114. const articles = await this.articleRepo.find({
  115. where: [
  116. {
  117. enable: true,
  118. },
  119. {
  120. translations: {
  121. locale: lang,
  122. title: Like(`%${key || ''}%`),
  123. },
  124. },
  125. {
  126. translations: {
  127. locale: lang,
  128. content: Like(`%${key || ''}%`),
  129. },
  130. },
  131. ],
  132. relations: { translations: true },
  133. });
  134. return articles.map((article) => article.translate(lang));
  135. }
  136. async findCateAllChildIds(parentId: number) {
  137. const childIds: number[] = [];
  138. // 递归查找所有子菜单的 id
  139. const findChildren = async (id: number) => {
  140. const children = await this.categoryRepo.find({ where: { parentId: id, enable: true } });
  141. for (const child of children) {
  142. childIds.push(child.id);
  143. await findChildren(child.id); // 递归查找子菜单的子菜单
  144. }
  145. };
  146. await findChildren(parentId);
  147. return childIds;
  148. }
  149. async getArticlesByCate(id: number, locale?: string) {
  150. const lang = this.sharedService.handleValidLang(locale);
  151. // 保留
  152. const category = await this.categoryRepo.findOne({
  153. where: { id: id, enable: true },
  154. relations: { children: true },
  155. });
  156. const ids = await this.findCateAllChildIds(category.id);
  157. // ids.push(category.id);
  158. // console.log('ids', ids);
  159. const articles = await this.articleRepo.find({
  160. where: {
  161. categoryId: id,
  162. enable: true,
  163. },
  164. relations: { translations: true },
  165. order: {
  166. order: 'DESC',
  167. createTime: 'DESC',
  168. },
  169. });
  170. const childArticles = await this.articleRepo.find({
  171. where: {
  172. categoryId: In(ids),
  173. enable: true,
  174. },
  175. relations: { translations: true },
  176. order: {
  177. order: 'DESC',
  178. createTime: 'DESC',
  179. },
  180. });
  181. // console.log('childArticles', childArticles);
  182. return articles.length > 0
  183. ? articles.map((article) => article.translate(lang))
  184. : childArticles.map((article) => article.translate(lang));
  185. }
  186. async getNearArticle(currentId: number, locale?: string) {
  187. const lang = this.sharedService.handleValidLang(locale);
  188. const currentEntity = await this.articleRepo.findOne({
  189. where: { id: currentId, enable: true },
  190. });
  191. if (!currentEntity) {
  192. // throw new CustomException(ErrorCode.ERR_4000, '当前数据不存在');
  193. return [];
  194. }
  195. const prevEntity = await this.articleRepo.findOne({
  196. where: { id: LessThan(currentId), categoryId: currentEntity.categoryId, enable: true },
  197. order: { id: 'DESC' },
  198. relations: { translations: true },
  199. });
  200. const nextEntity = await this.articleRepo.findOne({
  201. where: { id: MoreThan(currentId), categoryId: currentEntity.categoryId, enable: true },
  202. order: { id: 'ASC' },
  203. relations: { translations: true },
  204. });
  205. return [
  206. prevEntity ? prevEntity.translate(lang) : null,
  207. nextEntity ? nextEntity.translate(lang) : null,
  208. ];
  209. }
  210. }