statistics.schema.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import { z } from '@hono/zod-openapi';
  2. // 统计项通用Schema
  3. export const StatItemSchema = z.object({
  4. key: z.string().openapi({
  5. description: '统计项键名',
  6. example: '视力残疾'
  7. }),
  8. value: z.number().int().min(0).openapi({
  9. description: '统计数量',
  10. example: 10
  11. }),
  12. percentage: z.number().min(0).max(100).openapi({
  13. description: '占比百分比',
  14. example: 25.5
  15. })
  16. });
  17. // 年龄分组Schema
  18. export const AgeGroupSchema = z.enum(['18-25', '26-35', '36-45', '46+']).openapi({
  19. description: '年龄分组'
  20. });
  21. // 薪资范围分组Schema
  22. export const SalaryRangeSchema = z.enum(['<3000', '3000-5000', '5000-8000', '8000-12000', '12000+']).openapi({
  23. description: '薪资范围分组'
  24. });
  25. // 残疾类型分布响应Schema
  26. export const DisabilityTypeDistributionResponseSchema = z.object({
  27. companyId: z.number().int().positive().openapi({
  28. description: '企业ID',
  29. example: 1
  30. }),
  31. stats: z.array(StatItemSchema).openapi({
  32. description: '残疾类型分布统计'
  33. }),
  34. total: z.number().int().min(0).openapi({
  35. description: '总人数',
  36. example: 100
  37. })
  38. });
  39. // 性别分布响应Schema
  40. export const GenderDistributionResponseSchema = z.object({
  41. companyId: z.number().int().positive().openapi({
  42. description: '企业ID',
  43. example: 1
  44. }),
  45. stats: z.array(StatItemSchema).openapi({
  46. description: '性别分布统计'
  47. }),
  48. total: z.number().int().min(0).openapi({
  49. description: '总人数',
  50. example: 100
  51. })
  52. });
  53. // 年龄分布响应Schema
  54. export const AgeDistributionResponseSchema = z.object({
  55. companyId: z.number().int().positive().openapi({
  56. description: '企业ID',
  57. example: 1
  58. }),
  59. stats: z.array(
  60. StatItemSchema.extend({
  61. key: AgeGroupSchema
  62. })
  63. ).openapi({
  64. description: '年龄分布统计'
  65. }),
  66. total: z.number().int().min(0).openapi({
  67. description: '总人数',
  68. example: 100
  69. })
  70. });
  71. // 户籍分布项Schema(省市级)
  72. export const HouseholdStatItemSchema = StatItemSchema.extend({
  73. province: z.string().openapi({
  74. description: '省份',
  75. example: '江苏省'
  76. }),
  77. city: z.string().optional().openapi({
  78. description: '城市',
  79. example: '南京市'
  80. })
  81. });
  82. // 户籍分布响应Schema
  83. export const HouseholdDistributionResponseSchema = z.object({
  84. companyId: z.number().int().positive().openapi({
  85. description: '企业ID',
  86. example: 1
  87. }),
  88. stats: z.array(HouseholdStatItemSchema).openapi({
  89. description: '户籍分布统计'
  90. }),
  91. total: z.number().int().min(0).openapi({
  92. description: '总人数',
  93. example: 100
  94. })
  95. });
  96. // 在职状态分布响应Schema
  97. export const JobStatusDistributionResponseSchema = z.object({
  98. companyId: z.number().int().positive().openapi({
  99. description: '企业ID',
  100. example: 1
  101. }),
  102. stats: z.array(StatItemSchema).openapi({
  103. description: '在职状态分布统计'
  104. }),
  105. total: z.number().int().min(0).openapi({
  106. description: '总人数',
  107. example: 100
  108. })
  109. });
  110. // 薪资分布响应Schema
  111. export const SalaryDistributionResponseSchema = z.object({
  112. companyId: z.number().int().positive().openapi({
  113. description: '企业ID',
  114. example: 1
  115. }),
  116. stats: z.array(
  117. StatItemSchema.extend({
  118. key: SalaryRangeSchema
  119. })
  120. ).openapi({
  121. description: '薪资分布统计'
  122. }),
  123. total: z.number().int().min(0).openapi({
  124. description: '总人数',
  125. example: 100
  126. })
  127. });
  128. // ============== 统计卡片相关 Schema ==============
  129. // 简化版本:只返回当前统计数据,不包含历史对比数据
  130. // 在职人数统计响应Schema(简化版)
  131. export const EmploymentCountResponseSchema = z.object({
  132. companyId: z.number().int().positive().openapi({
  133. description: '企业ID',
  134. example: 1
  135. }),
  136. count: z.number().int().min(0).openapi({
  137. description: '在职人数',
  138. example: 24
  139. })
  140. });
  141. // 平均薪资统计响应Schema(简化版)
  142. export const AverageSalaryResponseSchema = z.object({
  143. companyId: z.number().int().positive().openapi({
  144. description: '企业ID',
  145. example: 1
  146. }),
  147. average: z.number().min(0).openapi({
  148. description: '平均薪资',
  149. example: 4650
  150. })
  151. });
  152. // 在职率统计响应Schema(简化版)
  153. export const EmploymentRateResponseSchema = z.object({
  154. companyId: z.number().int().positive().openapi({
  155. description: '企业ID',
  156. example: 1
  157. }),
  158. rate: z.number().min(0).max(100).openapi({
  159. description: '在职率(百分比)',
  160. example: 92
  161. })
  162. });
  163. // ============== 查询参数 Schema ==============
  164. // 年月查询参数Schema(用于筛选特定年月的统计数据)
  165. export const YearMonthQuerySchema = z.object({
  166. year: z.coerce.number().int().min(2020).max(2030).optional().openapi({
  167. description: '年份(可选,默认为当前年份)',
  168. example: 2026
  169. }),
  170. month: z.coerce.number().int().min(1).max(12).optional().openapi({
  171. description: '月份(可选,默认为当前月份)',
  172. example: 1
  173. })
  174. });
  175. // 通用查询参数Schema(已移除companyId,企业ID强制从认证token获取)
  176. export const StatisticsQuerySchema = z.object({});
  177. // 企业统计查询参数Schema(简化版:无查询参数,只返回当前数据)
  178. export const EnterpriseStatisticsQuerySchema = z.object({});
  179. // 类型定义
  180. export type StatItem = z.infer<typeof StatItemSchema>;
  181. export type AgeGroup = z.infer<typeof AgeGroupSchema>;
  182. export type SalaryRange = z.infer<typeof SalaryRangeSchema>;
  183. export type DisabilityTypeDistributionResponse = z.infer<typeof DisabilityTypeDistributionResponseSchema>;
  184. export type GenderDistributionResponse = z.infer<typeof GenderDistributionResponseSchema>;
  185. export type AgeDistributionResponse = z.infer<typeof AgeDistributionResponseSchema>;
  186. export type HouseholdStatItem = z.infer<typeof HouseholdStatItemSchema>;
  187. export type HouseholdDistributionResponse = z.infer<typeof HouseholdDistributionResponseSchema>;
  188. export type JobStatusDistributionResponse = z.infer<typeof JobStatusDistributionResponseSchema>;
  189. export type SalaryDistributionResponse = z.infer<typeof SalaryDistributionResponseSchema>;
  190. export type StatisticsQuery = z.infer<typeof StatisticsQuerySchema>;
  191. export type YearMonthQuery = z.infer<typeof YearMonthQuerySchema>;
  192. export type EmploymentCountResponse = z.infer<typeof EmploymentCountResponseSchema>;
  193. export type AverageSalaryResponse = z.infer<typeof AverageSalaryResponseSchema>;
  194. export type EmploymentRateResponse = z.infer<typeof EmploymentRateResponseSchema>;