tree.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import { OpenAPIHono } from '@hono/zod-openapi';
  2. import { createRoute, z } from '@hono/zod-openapi';
  3. import { authMiddleware } from '@d8d/auth-module';
  4. import { AreaService } from '../../modules/areas/area.service';
  5. import { AreaLevel } from '../../modules/areas/area.entity';
  6. // 获取完整树形结构
  7. const getAreaTreeRoute = createRoute({
  8. method: 'get',
  9. path: '/tree',
  10. description: '获取完整的省市区树形结构',
  11. tags: ['省市区管理'],
  12. middleware: [authMiddleware],
  13. responses: {
  14. 200: {
  15. description: '成功获取树形结构',
  16. content: {
  17. 'application/json': {
  18. schema: z.object({
  19. success: z.boolean(),
  20. data: z.array(z.object({
  21. id: z.number(),
  22. parentId: z.number().nullable(),
  23. name: z.string(),
  24. level: z.number(),
  25. code: z.string(),
  26. isDisabled: z.number(),
  27. children: z.array(z.any()).optional()
  28. }))
  29. })
  30. }
  31. }
  32. },
  33. 500: {
  34. description: '服务器错误',
  35. content: {
  36. 'application/json': {
  37. schema: z.object({
  38. success: z.boolean(),
  39. error: z.string()
  40. })
  41. }
  42. }
  43. }
  44. }
  45. });
  46. // 根据层级获取树形结构
  47. const getAreaTreeByLevelRoute = createRoute({
  48. method: 'get',
  49. path: '/tree/level/{level}',
  50. description: '根据层级获取树形结构',
  51. tags: ['省市区管理'],
  52. middleware: [authMiddleware],
  53. request: {
  54. params: z.object({
  55. level: z.coerce.number().min(1).max(3)
  56. })
  57. },
  58. responses: {
  59. 200: {
  60. description: '成功获取层级树形结构',
  61. content: {
  62. 'application/json': {
  63. schema: z.object({
  64. success: z.boolean(),
  65. data: z.array(z.object({
  66. id: z.number(),
  67. parentId: z.number().nullable(),
  68. name: z.string(),
  69. level: z.number(),
  70. code: z.string(),
  71. isDisabled: z.number(),
  72. children: z.array(z.any()).optional()
  73. }))
  74. })
  75. }
  76. }
  77. },
  78. 500: {
  79. description: '服务器错误',
  80. content: {
  81. 'application/json': {
  82. schema: z.object({
  83. success: z.boolean(),
  84. error: z.string()
  85. })
  86. }
  87. }
  88. }
  89. }
  90. });
  91. // 获取子树
  92. const getSubTreeRoute = createRoute({
  93. method: 'get',
  94. path: '/tree/{id}',
  95. description: '获取指定节点的子树',
  96. tags: ['省市区管理'],
  97. middleware: [authMiddleware],
  98. request: {
  99. params: z.object({
  100. id: z.coerce.number().positive('区域ID必须为正整数')
  101. })
  102. },
  103. responses: {
  104. 200: {
  105. description: '成功获取子树',
  106. content: {
  107. 'application/json': {
  108. schema: z.object({
  109. success: z.boolean(),
  110. data: z.object({
  111. id: z.number(),
  112. parentId: z.number().nullable(),
  113. name: z.string(),
  114. level: z.number(),
  115. code: z.string(),
  116. isDisabled: z.number(),
  117. children: z.array(z.any()).optional()
  118. }).nullable()
  119. })
  120. }
  121. }
  122. },
  123. 404: {
  124. description: '区域不存在',
  125. content: {
  126. 'application/json': {
  127. schema: z.object({
  128. success: z.boolean(),
  129. error: z.string()
  130. })
  131. }
  132. }
  133. },
  134. 500: {
  135. description: '服务器错误',
  136. content: {
  137. 'application/json': {
  138. schema: z.object({
  139. success: z.boolean(),
  140. error: z.string()
  141. })
  142. }
  143. }
  144. }
  145. }
  146. });
  147. // 获取区域路径
  148. const getAreaPathRoute = createRoute({
  149. method: 'get',
  150. path: '/path/{id}',
  151. description: '获取区域路径(从根节点到当前节点)',
  152. tags: ['省市区管理'],
  153. middleware: [authMiddleware],
  154. request: {
  155. params: z.object({
  156. id: z.coerce.number().positive('区域ID必须为正整数')
  157. })
  158. },
  159. responses: {
  160. 200: {
  161. description: '成功获取区域路径',
  162. content: {
  163. 'application/json': {
  164. schema: z.object({
  165. success: z.boolean(),
  166. data: z.array(z.object({
  167. id: z.number(),
  168. parentId: z.number().nullable(),
  169. name: z.string(),
  170. level: z.number(),
  171. code: z.string(),
  172. isDisabled: z.number()
  173. }))
  174. })
  175. }
  176. }
  177. },
  178. 404: {
  179. description: '区域不存在',
  180. content: {
  181. 'application/json': {
  182. schema: z.object({
  183. success: z.boolean(),
  184. error: z.string()
  185. })
  186. }
  187. }
  188. },
  189. 500: {
  190. description: '服务器错误',
  191. content: {
  192. 'application/json': {
  193. schema: z.object({
  194. success: z.boolean(),
  195. error: z.string()
  196. })
  197. }
  198. }
  199. }
  200. }
  201. });
  202. const app = new OpenAPIHono()
  203. // 注册路由 - 使用链式结构
  204. .openapi(getAreaTreeRoute, async (c) => {
  205. const areaService = new AreaService(c.var.dataSource);
  206. try {
  207. const treeData = await areaService.getAreaTree();
  208. return c.json({
  209. success: true,
  210. data: treeData
  211. }, 200);
  212. } catch (error) {
  213. console.error('获取省市区树形结构失败:', error);
  214. return c.json({
  215. success: false,
  216. error: '获取省市区树形结构失败'
  217. }, 500);
  218. }
  219. })
  220. .openapi(getAreaTreeByLevelRoute, async (c) => {
  221. const areaService = new AreaService(c.var.dataSource);
  222. try {
  223. const { level } = c.req.valid('param');
  224. const treeData = await areaService.getAreaTreeByLevel(level);
  225. return c.json({
  226. success: true,
  227. data: treeData
  228. }, 200);
  229. } catch (error) {
  230. console.error('获取层级树形结构失败:', error);
  231. return c.json({
  232. success: false,
  233. error: '获取层级树形结构失败'
  234. }, 500);
  235. }
  236. })
  237. .openapi(getSubTreeRoute, async (c) => {
  238. const areaService = new AreaService(c.var.dataSource);
  239. try {
  240. const { id } = c.req.valid('param');
  241. const subTree = await areaService.getSubTree(id);
  242. if (!subTree) {
  243. return c.json({
  244. success: false,
  245. error: '区域不存在'
  246. }, 404);
  247. }
  248. return c.json({
  249. success: true,
  250. data: subTree
  251. }, 200);
  252. } catch (error) {
  253. console.error('获取子树失败:', error);
  254. return c.json({
  255. success: false,
  256. error: '获取子树失败'
  257. }, 500);
  258. }
  259. })
  260. .openapi(getAreaPathRoute, async (c) => {
  261. const areaService = new AreaService(c.var.dataSource);
  262. try {
  263. const { id } = c.req.valid('param');
  264. const path = await areaService.getAreaPath(id);
  265. if (path.length === 0) {
  266. return c.json({
  267. success: false,
  268. error: '区域不存在'
  269. }, 404);
  270. }
  271. return c.json({
  272. success: true,
  273. data: path
  274. }, 200);
  275. } catch (error) {
  276. console.error('获取区域路径失败:', error);
  277. return c.json({
  278. success: false,
  279. error: '获取区域路径失败'
  280. }, 500);
  281. }
  282. });
  283. export default app;