Commit 10e0ac6c6aeade8c283300c5dbcf4e7c26c1dc56
1 parent
12d64309
优化工资查询和用户列表接口功能
1. 工资查询接口优化: - 修改所有9个薪酬服务的员工工资查询接口 - 只能查询已锁定且未确认的工资(IsLocked=1 && EmployeeConfirmStatus!=1) - 员工确认工资后无法再次查看 - 更新接口注释说明新的查询逻辑 2. 用户列表接口增强: - 添加门店ID(mdid)搜索功能 - 添加岗位(gw)搜索功能 - 添加启用状态(enabledMark)筛选功能 - 支持组合搜索(门店ID+岗位+状态) 3. 文档和测试: - 新增员工工资查询接口逻辑梳理文档 - 新增用户列表搜索功能测试脚本
Showing
14 changed files
with
674 additions
and
19 deletions
docs/员工工资查询接口逻辑梳理.md
0 → 100644
| 1 | +# 员工工资查询接口逻辑梳理 | |
| 2 | + | |
| 3 | +## 📋 概述 | |
| 4 | + | |
| 5 | +所有薪酬服务都提供了根据员工ID和月份查询工资的接口,供员工查看自己的工资条。本文档梳理了所有薪酬服务中的查询逻辑。 | |
| 6 | + | |
| 7 | +--- | |
| 8 | + | |
| 9 | +## 🔍 接口列表 | |
| 10 | + | |
| 11 | +### 1. 健康师工资查询 | |
| 12 | +- **服务**: `LqSalaryService` | |
| 13 | +- **路由**: `GET /api/Extend/lqsalary/query-by-employee` | |
| 14 | +- **方法**: `GetSalaryByEmployee` | |
| 15 | +- **返回类型**: `HealthCoachSalaryOutput` | |
| 16 | +- **数据表**: `lq_salary_statistics` | |
| 17 | + | |
| 18 | +### 2. 店长工资查询 | |
| 19 | +- **服务**: `LqStoreManagerSalaryService` | |
| 20 | +- **路由**: `GET /api/Extend/lqstoremanagersalary/query-by-employee` | |
| 21 | +- **方法**: `GetSalaryByEmployee` | |
| 22 | +- **返回类型**: `StoreManagerSalaryOutput` | |
| 23 | +- **数据表**: `lq_store_manager_salary_statistics` | |
| 24 | + | |
| 25 | +### 3. 主任工资查询 | |
| 26 | +- **服务**: `LqDirectorSalaryService` | |
| 27 | +- **路由**: `GET /api/Extend/lqdirectorsalary/query-by-employee` | |
| 28 | +- **方法**: `GetSalaryByEmployee` | |
| 29 | +- **返回类型**: `DirectorSalaryOutput` | |
| 30 | +- **数据表**: `lq_director_salary_statistics` | |
| 31 | + | |
| 32 | +### 4. 店助工资查询 | |
| 33 | +- **服务**: `LqAssistantSalaryService` | |
| 34 | +- **路由**: `GET /api/Extend/lqassistantsalary/query-by-employee` | |
| 35 | +- **方法**: `GetSalaryByEmployee` | |
| 36 | +- **返回类型**: `AssistantSalaryOutput` | |
| 37 | +- **数据表**: `lq_assistant_salary_statistics` | |
| 38 | + | |
| 39 | +### 5. 事业部总经理/经理工资查询 | |
| 40 | +- **服务**: `LqBusinessUnitManagerSalaryService` | |
| 41 | +- **路由**: `GET /api/Extend/lqbusinessunitmanagersalary/query-by-employee` | |
| 42 | +- **方法**: `GetSalaryByEmployee` | |
| 43 | +- **返回类型**: `BusinessUnitManagerSalaryOutput` | |
| 44 | +- **数据表**: `lq_business_unit_manager_salary_statistics` | |
| 45 | + | |
| 46 | +### 6. 科技部老师工资查询 | |
| 47 | +- **服务**: `LqTechTeacherSalaryService` | |
| 48 | +- **路由**: `GET /api/Extend/lqtechteachersalary/query-by-employee` | |
| 49 | +- **方法**: `GetSalaryByEmployee` | |
| 50 | +- **返回类型**: `TechTeacherSalaryOutput` | |
| 51 | +- **数据表**: `lq_tech_teacher_salary_statistics` | |
| 52 | + | |
| 53 | +### 7. 科技部总经理工资查询 | |
| 54 | +- **服务**: `LqTechGeneralManagerSalaryService` | |
| 55 | +- **路由**: `GET /api/Extend/lqtechgeneralmanagersalary/query-by-employee` | |
| 56 | +- **方法**: `GetSalaryByEmployee` | |
| 57 | +- **返回类型**: `TechGeneralManagerSalaryOutput` | |
| 58 | +- **数据表**: `lq_tech_general_manager_salary_statistics` | |
| 59 | + | |
| 60 | +### 8. 大项目主管工资查询 | |
| 61 | +- **服务**: `LqMajorProjectDirectorSalaryService` | |
| 62 | +- **路由**: `GET /api/Extend/lqmajorprojectdirectorsalary/query-by-employee` | |
| 63 | +- **方法**: `GetSalaryByEmployee` | |
| 64 | +- **返回类型**: `MajorProjectDirectorSalaryOutput` | |
| 65 | +- **数据表**: `lq_major_project_director_salary_statistics` | |
| 66 | + | |
| 67 | +### 9. 大项目部老师工资查询 | |
| 68 | +- **服务**: `LqMajorProjectTeacherSalaryService` | |
| 69 | +- **路由**: `GET /api/Extend/lqmajorprojectteachersalary/query-by-employee` | |
| 70 | +- **方法**: `GetSalaryByEmployee` | |
| 71 | +- **返回类型**: `MajorProjectTeacherSalaryOutput` | |
| 72 | +- **数据表**: `lq_major_project_teacher_salary_statistics` | |
| 73 | + | |
| 74 | +--- | |
| 75 | + | |
| 76 | +## 📝 统一查询逻辑 | |
| 77 | + | |
| 78 | +### 输入参数 | |
| 79 | + | |
| 80 | +所有接口都使用相同的输入参数类:`SalaryQueryByEmployeeInput` | |
| 81 | + | |
| 82 | +```csharp | |
| 83 | +public class SalaryQueryByEmployeeInput | |
| 84 | +{ | |
| 85 | + /// <summary> | |
| 86 | + /// 年份 | |
| 87 | + /// </summary> | |
| 88 | + public int Year { get; set; } | |
| 89 | + | |
| 90 | + /// <summary> | |
| 91 | + /// 月份 | |
| 92 | + /// </summary> | |
| 93 | + public int Month { get; set; } | |
| 94 | + | |
| 95 | + /// <summary> | |
| 96 | + /// 员工ID | |
| 97 | + /// </summary> | |
| 98 | + public string EmployeeId { get; set; } | |
| 99 | +} | |
| 100 | +``` | |
| 101 | + | |
| 102 | +### 查询条件 | |
| 103 | + | |
| 104 | +所有接口的查询条件都相同: | |
| 105 | + | |
| 106 | +```csharp | |
| 107 | +.Where(x => | |
| 108 | + x.StatisticsMonth == monthStr // 统计月份匹配 | |
| 109 | + && x.EmployeeId == input.EmployeeId // 员工ID匹配 | |
| 110 | + && x.IsLocked == 1 // 只查询已锁定的工资 | |
| 111 | + && x.EmployeeConfirmStatus != 1 // 只查询未确认的工资 | |
| 112 | +) | |
| 113 | +``` | |
| 114 | + | |
| 115 | +**关键点**: | |
| 116 | +- ✅ **只查询已锁定的工资**:`IsLocked == 1` | |
| 117 | +- ✅ **只查询未确认的工资**:`EmployeeConfirmStatus != 1`(已确认的工资无法查询) | |
| 118 | +- ✅ **员工ID匹配**:`EmployeeId == input.EmployeeId` | |
| 119 | +- ✅ **月份匹配**:`StatisticsMonth == monthStr`(格式:YYYYMM) | |
| 120 | + | |
| 121 | +**重要说明**: | |
| 122 | +- 员工只能查看**已锁定但未确认**的工资记录 | |
| 123 | +- 一旦员工确认工资后(`EmployeeConfirmStatus = 1`),该工资记录将无法通过此接口查询 | |
| 124 | +- 这个设计确保员工在确认工资后,无法再次查看已确认的工资记录 | |
| 125 | + | |
| 126 | +### 参数验证 | |
| 127 | + | |
| 128 | +所有接口都进行相同的参数验证: | |
| 129 | + | |
| 130 | +```csharp | |
| 131 | +// 1. 验证年份和月份 | |
| 132 | +if (input.Year <= 0 || input.Month <= 0 || input.Month > 12) | |
| 133 | +{ | |
| 134 | + throw NCCException.Oh("年份和月份参数不正确"); | |
| 135 | +} | |
| 136 | + | |
| 137 | +// 2. 验证员工ID | |
| 138 | +if (string.IsNullOrWhiteSpace(input.EmployeeId)) | |
| 139 | +{ | |
| 140 | + throw NCCException.Oh("员工ID不能为空"); | |
| 141 | +} | |
| 142 | + | |
| 143 | +// 3. 格式化月份 | |
| 144 | +var monthStr = $"{input.Year}{input.Month:D2}"; // 例如:202512 | |
| 145 | +``` | |
| 146 | + | |
| 147 | +### 查询结果处理 | |
| 148 | + | |
| 149 | +```csharp | |
| 150 | +// 查询工资记录 | |
| 151 | +var salary = await _db.Queryable<SalaryStatisticsEntity>() | |
| 152 | + .Where(x => x.StatisticsMonth == monthStr | |
| 153 | + && x.EmployeeId == input.EmployeeId | |
| 154 | + && x.IsLocked == 1) | |
| 155 | + .Select(x => new SalaryOutput { /* 字段映射 */ }) | |
| 156 | + .FirstAsync(); | |
| 157 | + | |
| 158 | +// 如果未找到,抛出异常 | |
| 159 | +if (salary == null) | |
| 160 | +{ | |
| 161 | + throw NCCException.Oh($"未找到员工{input.EmployeeId}在{input.Year}年{input.Month}月的工资记录"); | |
| 162 | +} | |
| 163 | + | |
| 164 | +return salary; | |
| 165 | +``` | |
| 166 | + | |
| 167 | +--- | |
| 168 | + | |
| 169 | +## 🔐 安全机制 | |
| 170 | + | |
| 171 | +### 1. 锁定机制 | |
| 172 | +- **只查询已锁定的工资**:`IsLocked == 1` | |
| 173 | +- **目的**:确保员工只能查看已完成的工资数据,避免查看未完成计算的工资 | |
| 174 | +- **业务逻辑**:工资计算完成后,管理员需要先锁定工资,员工才能查看 | |
| 175 | + | |
| 176 | +### 1.1 确认状态限制 | |
| 177 | +- **只查询未确认的工资**:`EmployeeConfirmStatus != 1` | |
| 178 | +- **目的**:员工确认工资后,该工资记录将无法再次查询 | |
| 179 | +- **业务逻辑**: | |
| 180 | + 1. 工资计算完成 → 管理员锁定(`IsLocked = 1`) | |
| 181 | + 2. 员工可以查看工资(`IsLocked = 1` 且 `EmployeeConfirmStatus != 1`) | |
| 182 | + 3. 员工确认工资(`EmployeeConfirmStatus = 1`) | |
| 183 | + 4. 确认后无法再次查询(`EmployeeConfirmStatus = 1` 的记录被排除) | |
| 184 | + | |
| 185 | +### 2. 员工ID匹配 | |
| 186 | +- **精确匹配**:`EmployeeId == input.EmployeeId` | |
| 187 | +- **目的**:确保员工只能查看自己的工资,不能查看其他员工的工资 | |
| 188 | +- **实现方式**: | |
| 189 | + - 后端:通过SQL查询条件 `EmployeeId == input.EmployeeId` 实现精确匹配 | |
| 190 | + - 前端:从本地存储获取当前登录用户的ID,自动填充到查询参数中 | |
| 191 | + | |
| 192 | +### 3. 月份限制 | |
| 193 | +- **格式验证**:月份必须在 1-12 之间 | |
| 194 | +- **目的**:确保查询参数的有效性 | |
| 195 | + | |
| 196 | +### 4. 权限验证说明 | |
| 197 | + | |
| 198 | +#### 当前实现 | |
| 199 | +- **后端**:接口**没有**验证当前登录用户,只通过 `EmployeeId` 参数查询 | |
| 200 | +- **前端**:从 `uni.getStorageSync('userInfo')` 获取用户ID,自动填充到查询参数 | |
| 201 | +- **安全依赖**:依赖前端确保传入的 `EmployeeId` 是当前登录用户的ID | |
| 202 | + | |
| 203 | +#### 潜在安全问题 | |
| 204 | +- **风险**:如果前端被篡改,可能会查询到其他员工的工资 | |
| 205 | +- **现状**:目前通过SQL查询条件 `EmployeeId == input.EmployeeId` 实现精确匹配,但**没有验证** `input.EmployeeId` 是否与当前登录用户ID一致 | |
| 206 | + | |
| 207 | +#### 建议改进 | |
| 208 | +可以在后端增加权限验证,确保员工只能查询自己的工资: | |
| 209 | + | |
| 210 | +```csharp | |
| 211 | +// 获取当前登录用户ID | |
| 212 | +var currentUserId = _userManager.UserId; | |
| 213 | + | |
| 214 | +// 验证:员工只能查询自己的工资 | |
| 215 | +if (input.EmployeeId != currentUserId && !_userManager.IsAdministrator) | |
| 216 | +{ | |
| 217 | + throw NCCException.Oh("您只能查询自己的工资记录"); | |
| 218 | +} | |
| 219 | +``` | |
| 220 | + | |
| 221 | +**注意**:管理员可能需要查询所有员工的工资,所以需要判断 `IsAdministrator` | |
| 222 | + | |
| 223 | +--- | |
| 224 | + | |
| 225 | +## 📊 数据流程 | |
| 226 | + | |
| 227 | +### 查询流程 | |
| 228 | + | |
| 229 | +``` | |
| 230 | +1. 接收请求参数(Year, Month, EmployeeId) | |
| 231 | + ↓ | |
| 232 | +2. 参数验证 | |
| 233 | + - 年份和月份有效性检查 | |
| 234 | + - 员工ID非空检查 | |
| 235 | + ↓ | |
| 236 | +3. 格式化月份(YYYYMM格式) | |
| 237 | + ↓ | |
| 238 | +4. 查询数据库 | |
| 239 | + - 条件:StatisticsMonth == monthStr | |
| 240 | + - 条件:EmployeeId == input.EmployeeId | |
| 241 | + - 条件:IsLocked == 1(已锁定) | |
| 242 | + - 条件:EmployeeConfirmStatus != 1(未确认) | |
| 243 | + ↓ | |
| 244 | +5. 数据映射(Entity → Output DTO) | |
| 245 | + ↓ | |
| 246 | +6. 结果验证 | |
| 247 | + - 如果未找到,抛出异常 | |
| 248 | + ↓ | |
| 249 | +7. 返回工资记录 | |
| 250 | +``` | |
| 251 | + | |
| 252 | +### 数据表结构 | |
| 253 | + | |
| 254 | +每个薪酬服务对应一个工资统计表: | |
| 255 | + | |
| 256 | +| 服务 | 数据表 | 主键字段 | 员工ID字段 | 月份字段 | 锁定字段 | | |
| 257 | +|------|--------|---------|-----------|---------|---------| | |
| 258 | +| 健康师 | `lq_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 259 | +| 店长 | `lq_store_manager_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 260 | +| 主任 | `lq_director_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 261 | +| 店助 | `lq_assistant_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 262 | +| 事业部总经理/经理 | `lq_business_unit_manager_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 263 | +| 科技部老师 | `lq_tech_teacher_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 264 | +| 科技部总经理 | `lq_tech_general_manager_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 265 | +| 大项目主管 | `lq_major_project_director_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 266 | +| 大项目部老师 | `lq_major_project_teacher_salary_statistics` | `F_Id` | `F_EmployeeId` | `F_StatisticsMonth` | `F_IsLocked` | | |
| 267 | + | |
| 268 | +--- | |
| 269 | + | |
| 270 | +## 🔄 与其他功能的关系 | |
| 271 | + | |
| 272 | +### 1. 工资计算 | |
| 273 | +- **关系**:查询接口依赖工资计算接口生成的数据 | |
| 274 | +- **流程**:先执行计算接口(`calculate/*`),生成工资记录,然后才能查询 | |
| 275 | + | |
| 276 | +### 2. 工资锁定 | |
| 277 | +- **关系**:查询接口只返回已锁定的工资 | |
| 278 | +- **流程**:工资计算完成后,需要锁定(`IsLocked = 1`),员工才能查看 | |
| 279 | + | |
| 280 | +### 3. 员工确认 | |
| 281 | +- **关系**:查询接口返回的数据包含确认状态(`EmployeeConfirmStatus`) | |
| 282 | +- **流程**:员工查看工资后,可以确认工资条 | |
| 283 | + | |
| 284 | +--- | |
| 285 | + | |
| 286 | +## ⚠️ 注意事项 | |
| 287 | + | |
| 288 | +### 1. 锁定状态 | |
| 289 | +- **必须锁定**:只有已锁定的工资才能被员工查询 | |
| 290 | +- **未锁定处理**:如果工资未锁定,查询接口会返回404错误 | |
| 291 | + | |
| 292 | +### 1.1 确认状态 | |
| 293 | +- **必须未确认**:只有未确认的工资才能被员工查询 | |
| 294 | +- **已确认处理**:如果工资已确认(`EmployeeConfirmStatus = 1`),查询接口会返回404错误 | |
| 295 | +- **业务含义**:员工确认工资后,该工资记录将无法再次查询,确保数据安全 | |
| 296 | + | |
| 297 | +### 2. 员工ID匹配 | |
| 298 | +- **精确匹配**:必须使用正确的员工ID | |
| 299 | +- **安全考虑**:接口不验证当前登录用户,需要前端或中间件确保员工只能查询自己的工资 | |
| 300 | + | |
| 301 | +### 3. 月份格式 | |
| 302 | +- **格式要求**:月份必须格式化为 YYYYMM(如:202512) | |
| 303 | +- **验证**:月份必须在 1-12 之间 | |
| 304 | + | |
| 305 | +### 4. 数据完整性 | |
| 306 | +- **字段映射**:每个服务的Output DTO字段可能不同 | |
| 307 | +- **空值处理**:如果未找到记录,返回404错误 | |
| 308 | + | |
| 309 | +--- | |
| 310 | + | |
| 311 | +## 📋 接口调用示例 | |
| 312 | + | |
| 313 | +### 健康师工资查询 | |
| 314 | +```http | |
| 315 | +GET /api/Extend/lqsalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 316 | +``` | |
| 317 | + | |
| 318 | +### 店长工资查询 | |
| 319 | +```http | |
| 320 | +GET /api/Extend/lqstoremanagersalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 321 | +``` | |
| 322 | + | |
| 323 | +### 主任工资查询 | |
| 324 | +```http | |
| 325 | +GET /api/Extend/lqdirectorsalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 326 | +``` | |
| 327 | + | |
| 328 | +### 店助工资查询 | |
| 329 | +```http | |
| 330 | +GET /api/Extend/lqassistantsalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 331 | +``` | |
| 332 | + | |
| 333 | +### 事业部总经理/经理工资查询 | |
| 334 | +```http | |
| 335 | +GET /api/Extend/lqbusinessunitmanagersalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 336 | +``` | |
| 337 | + | |
| 338 | +### 科技部老师工资查询 | |
| 339 | +```http | |
| 340 | +GET /api/Extend/lqtechteachersalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 341 | +``` | |
| 342 | + | |
| 343 | +### 科技部总经理工资查询 | |
| 344 | +```http | |
| 345 | +GET /api/Extend/lqtechgeneralmanagersalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 346 | +``` | |
| 347 | + | |
| 348 | +### 大项目主管工资查询 | |
| 349 | +```http | |
| 350 | +GET /api/Extend/lqmajorprojectdirectorsalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 351 | +``` | |
| 352 | + | |
| 353 | +### 大项目部老师工资查询 | |
| 354 | +```http | |
| 355 | +GET /api/Extend/lqmajorprojectteachersalary/query-by-employee?Year=2025&Month=12&EmployeeId=员工ID | |
| 356 | +``` | |
| 357 | + | |
| 358 | +--- | |
| 359 | + | |
| 360 | +## 🔍 代码实现对比 | |
| 361 | + | |
| 362 | +### 共同点 | |
| 363 | + | |
| 364 | +所有服务的查询逻辑都相同: | |
| 365 | + | |
| 366 | +1. **参数验证**:年份、月份、员工ID验证 | |
| 367 | +2. **月份格式化**:`$"{input.Year}{input.Month:D2}"` | |
| 368 | +3. **查询条件**:`StatisticsMonth == monthStr && EmployeeId == input.EmployeeId && IsLocked == 1` | |
| 369 | +4. **异常处理**:未找到记录时抛出异常 | |
| 370 | +5. **返回类型**:返回对应的Output DTO | |
| 371 | + | |
| 372 | +### 差异点 | |
| 373 | + | |
| 374 | +1. **数据表不同**:每个服务查询不同的工资统计表 | |
| 375 | +2. **Output DTO不同**:每个服务返回的字段可能不同 | |
| 376 | +3. **字段映射不同**:根据岗位不同,返回的工资字段不同 | |
| 377 | + | |
| 378 | +--- | |
| 379 | + | |
| 380 | +## 📝 总结 | |
| 381 | + | |
| 382 | +### 核心逻辑 | |
| 383 | + | |
| 384 | +1. **统一接口**:所有薪酬服务都提供 `query-by-employee` 接口 | |
| 385 | +2. **统一参数**:都使用 `SalaryQueryByEmployeeInput` 作为输入参数 | |
| 386 | +3. **统一条件**:都查询已锁定(`IsLocked == 1`)的工资记录 | |
| 387 | +4. **统一验证**:都进行相同的参数验证和异常处理 | |
| 388 | + | |
| 389 | +### 安全机制 | |
| 390 | + | |
| 391 | +1. **锁定检查**:只查询已锁定的工资 | |
| 392 | +2. **员工匹配**:精确匹配员工ID | |
| 393 | +3. **参数验证**:验证年份、月份、员工ID的有效性 | |
| 394 | + | |
| 395 | +### 使用场景 | |
| 396 | + | |
| 397 | +1. **员工查看工资条**:员工通过小程序或PC端查看自己的工资 | |
| 398 | +2. **工资确认**:员工查看工资后,可以确认工资条 | |
| 399 | +3. **历史查询**:员工可以查询历史月份的工资记录 | |
| 400 | + | |
| 401 | +--- | |
| 402 | + | |
| 403 | +**文档版本**: v1.0 | |
| 404 | +**创建日期**: 2026-01-09 | |
| 405 | +**适用范围**: 所有薪酬服务的员工工资查询接口 | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqAssistantSalaryService.cs
| ... | ... | @@ -124,8 +124,12 @@ namespace NCC.Extend |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | 126 | /// <summary> |
| 127 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 127 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 128 | 128 | /// </summary> |
| 129 | + /// <remarks> | |
| 130 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 131 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 132 | + /// </remarks> | |
| 129 | 133 | [HttpGet("query-by-employee")] |
| 130 | 134 | public async Task<AssistantSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 131 | 135 | { |
| ... | ... | @@ -135,7 +139,7 @@ namespace NCC.Extend |
| 135 | 139 | throw NCCException.Oh("员工ID不能为空"); |
| 136 | 140 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 137 | 141 | var salary = await _db.Queryable<LqAssistantSalaryStatisticsEntity>() |
| 138 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 142 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 139 | 143 | .Select(x => new AssistantSalaryOutput |
| 140 | 144 | { |
| 141 | 145 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqBusinessUnitManagerSalaryService.cs
| ... | ... | @@ -132,8 +132,12 @@ namespace NCC.Extend |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | /// <summary> |
| 135 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 135 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 136 | 136 | /// </summary> |
| 137 | + /// <remarks> | |
| 138 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 139 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 140 | + /// </remarks> | |
| 137 | 141 | [HttpGet("query-by-employee")] |
| 138 | 142 | public async Task<BusinessUnitManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 139 | 143 | { |
| ... | ... | @@ -143,7 +147,7 @@ namespace NCC.Extend |
| 143 | 147 | throw NCCException.Oh("员工ID不能为空"); |
| 144 | 148 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 145 | 149 | var salary = await _db.Queryable<LqBusinessUnitManagerSalaryStatisticsEntity>() |
| 146 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 150 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 147 | 151 | .Select(x => new BusinessUnitManagerSalaryOutput |
| 148 | 152 | { |
| 149 | 153 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqDirectorSalaryService.cs
| ... | ... | @@ -154,8 +154,12 @@ namespace NCC.Extend |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | /// <summary> |
| 157 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 157 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 158 | 158 | /// </summary> |
| 159 | + /// <remarks> | |
| 160 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 161 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 162 | + /// </remarks> | |
| 159 | 163 | [HttpGet("query-by-employee")] |
| 160 | 164 | public async Task<DirectorSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 161 | 165 | { |
| ... | ... | @@ -165,7 +169,7 @@ namespace NCC.Extend |
| 165 | 169 | throw NCCException.Oh("员工ID不能为空"); |
| 166 | 170 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 167 | 171 | var salary = await _db.Queryable<LqDirectorSalaryStatisticsEntity>() |
| 168 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 172 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 169 | 173 | .Select(x => new DirectorSalaryOutput |
| 170 | 174 | { |
| 171 | 175 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqMajorProjectDirectorSalaryService.cs
| ... | ... | @@ -127,8 +127,12 @@ namespace NCC.Extend |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | /// <summary> |
| 130 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 130 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 131 | 131 | /// </summary> |
| 132 | + /// <remarks> | |
| 133 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 134 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 135 | + /// </remarks> | |
| 132 | 136 | [HttpGet("query-by-employee")] |
| 133 | 137 | public async Task<MajorProjectDirectorSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 134 | 138 | { |
| ... | ... | @@ -138,7 +142,7 @@ namespace NCC.Extend |
| 138 | 142 | throw NCCException.Oh("员工ID不能为空"); |
| 139 | 143 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 140 | 144 | var salary = await _db.Queryable<LqMajorProjectDirectorSalaryStatisticsEntity>() |
| 141 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 145 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 142 | 146 | .Select(x => new MajorProjectDirectorSalaryOutput |
| 143 | 147 | { |
| 144 | 148 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqMajorProjectTeacherSalaryService.cs
| ... | ... | @@ -142,8 +142,12 @@ namespace NCC.Extend |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | /// <summary> |
| 145 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 145 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 146 | 146 | /// </summary> |
| 147 | + /// <remarks> | |
| 148 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 149 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 150 | + /// </remarks> | |
| 147 | 151 | [HttpGet("query-by-employee")] |
| 148 | 152 | public async Task<MajorProjectTeacherSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 149 | 153 | { |
| ... | ... | @@ -153,7 +157,7 @@ namespace NCC.Extend |
| 153 | 157 | throw NCCException.Oh("员工ID不能为空"); |
| 154 | 158 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 155 | 159 | var salary = await _db.Queryable<LqMajorProjectTeacherSalaryStatisticsEntity>() |
| 156 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 160 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 157 | 161 | .Select(x => new MajorProjectTeacherSalaryOutput |
| 158 | 162 | { |
| 159 | 163 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqSalaryService.cs
| ... | ... | @@ -175,12 +175,13 @@ namespace NCC.Extend |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | /// <summary> |
| 178 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 178 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 179 | 179 | /// </summary> |
| 180 | 180 | /// <remarks> |
| 181 | 181 | /// 根据年份、月份和员工ID查询对应员工的工资记录 |
| 182 | 182 | /// |
| 183 | - /// **重要**:此接口只能查询已锁定(IsLocked=1)的工资记录 | |
| 183 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 184 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 184 | 185 | /// |
| 185 | 186 | /// 示例请求: |
| 186 | 187 | /// ``` |
| ... | ... | @@ -212,7 +213,7 @@ namespace NCC.Extend |
| 212 | 213 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 213 | 214 | |
| 214 | 215 | var salary = await _db.Queryable<LqSalaryStatisticsEntity>() |
| 215 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 216 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 216 | 217 | .Select(x => new HealthCoachSalaryOutput |
| 217 | 218 | { |
| 218 | 219 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqStoreManagerSalaryService.cs
| ... | ... | @@ -133,8 +133,12 @@ namespace NCC.Extend |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | 135 | /// <summary> |
| 136 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 136 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 137 | 137 | /// </summary> |
| 138 | + /// <remarks> | |
| 139 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 140 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 141 | + /// </remarks> | |
| 138 | 142 | [HttpGet("query-by-employee")] |
| 139 | 143 | public async Task<StoreManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 140 | 144 | { |
| ... | ... | @@ -144,7 +148,7 @@ namespace NCC.Extend |
| 144 | 148 | throw NCCException.Oh("员工ID不能为空"); |
| 145 | 149 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 146 | 150 | var salary = await _db.Queryable<LqStoreManagerSalaryStatisticsEntity>() |
| 147 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 151 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 148 | 152 | .Select(x => new StoreManagerSalaryOutput |
| 149 | 153 | { |
| 150 | 154 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqTechGeneralManagerSalaryService.cs
| ... | ... | @@ -131,8 +131,12 @@ namespace NCC.Extend |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | /// <summary> |
| 134 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 134 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 135 | 135 | /// </summary> |
| 136 | + /// <remarks> | |
| 137 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 138 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 139 | + /// </remarks> | |
| 136 | 140 | [HttpGet("query-by-employee")] |
| 137 | 141 | public async Task<TechGeneralManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 138 | 142 | { |
| ... | ... | @@ -142,7 +146,7 @@ namespace NCC.Extend |
| 142 | 146 | throw NCCException.Oh("员工ID不能为空"); |
| 143 | 147 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 144 | 148 | var salary = await _db.Queryable<LqTechGeneralManagerSalaryStatisticsEntity>() |
| 145 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 149 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 146 | 150 | .Select(x => new TechGeneralManagerSalaryOutput |
| 147 | 151 | { |
| 148 | 152 | Id = x.Id, | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqTechTeacherSalaryService.cs
| ... | ... | @@ -146,8 +146,12 @@ namespace NCC.Extend |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | /// <summary> |
| 149 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | |
| 149 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) | |
| 150 | 150 | /// </summary> |
| 151 | + /// <remarks> | |
| 152 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | |
| 153 | + /// **注意**:已确认的工资记录无法通过此接口查询 | |
| 154 | + /// </remarks> | |
| 151 | 155 | [HttpGet("query-by-employee")] |
| 152 | 156 | public async Task<TechTeacherSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 153 | 157 | { |
| ... | ... | @@ -157,7 +161,7 @@ namespace NCC.Extend |
| 157 | 161 | throw NCCException.Oh("员工ID不能为空"); |
| 158 | 162 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 159 | 163 | var salary = await _db.Queryable<LqTechTeacherSalaryStatisticsEntity>() |
| 160 | - .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1) | |
| 164 | + .Where(x => x.StatisticsMonth == monthStr && x.EmployeeId == input.EmployeeId && x.IsLocked == 1 && x.EmployeeConfirmStatus != 1) | |
| 161 | 165 | .Select(x => new TechTeacherSalaryOutput |
| 162 | 166 | { |
| 163 | 167 | Id = x.Id, | ... | ... |
netcore/src/Modularity/System/NCC.System.Entitys/Dto/Permission/User/UserListQuery.cs
| ... | ... | @@ -13,5 +13,20 @@ namespace NCC.System.Entitys.Dto.Permission.User |
| 13 | 13 | /// 机构ID |
| 14 | 14 | /// </summary> |
| 15 | 15 | public string organizeId { get; set; } |
| 16 | + | |
| 17 | + /// <summary> | |
| 18 | + /// 门店ID(F_MDID) | |
| 19 | + /// </summary> | |
| 20 | + public string mdid { get; set; } | |
| 21 | + | |
| 22 | + /// <summary> | |
| 23 | + /// 岗位(F_GW) | |
| 24 | + /// </summary> | |
| 25 | + public string gw { get; set; } | |
| 26 | + | |
| 27 | + /// <summary> | |
| 28 | + /// 启用状态(0=禁用,1=启用,null=全部) | |
| 29 | + /// </summary> | |
| 30 | + public int? enabledMark { get; set; } | |
| 16 | 31 | } |
| 17 | 32 | } | ... | ... |
netcore/src/Modularity/System/NCC.System/Service/Permission/UsersService.cs
| ... | ... | @@ -136,6 +136,9 @@ namespace NCC.System.Service.Permission |
| 136 | 136 | //组织机构 |
| 137 | 137 | .WhereIF(organizeIds.Any(), u => organizeIds.Contains(SqlFunc.ToString(u.organizeId))) |
| 138 | 138 | .WhereIF(!pageInput.keyword.IsNullOrEmpty(), u => u.account.Contains(pageInput.keyword) || u.realName.Contains(pageInput.keyword)) |
| 139 | + .WhereIF(!input.mdid.IsNullOrEmpty(), u => u.mdid == input.mdid) | |
| 140 | + .WhereIF(!input.gw.IsNullOrEmpty(), u => u.gw == input.gw) | |
| 141 | + .WhereIF(input.enabledMark.HasValue, u => u.enabledMark == input.enabledMark) | |
| 139 | 142 | .Where(a => a.deleteMark == null) |
| 140 | 143 | .OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) |
| 141 | 144 | .ToPagedListAsync(pageInput.currentPage, pageInput.pageSize); | ... | ... |
scripts/sh/test_user_list_search.sh
0 → 100755
| 1 | +#!/bin/bash | |
| 2 | + | |
| 3 | +# 测试用户列表接口 - 门店ID和岗位搜索功能 | |
| 4 | +# 使用方法: ./scripts/sh/test_user_list_search.sh | |
| 5 | + | |
| 6 | +BASE_URL="http://localhost:2011" | |
| 7 | +TOKEN="" | |
| 8 | + | |
| 9 | +echo "==========================================" | |
| 10 | +echo "测试用户列表接口 - 门店ID和岗位搜索" | |
| 11 | +echo "==========================================" | |
| 12 | +echo "" | |
| 13 | + | |
| 14 | +# 1. 登录获取token | |
| 15 | +echo "1. 登录获取token..." | |
| 16 | +LOGIN_RESPONSE=$(curl -s -X POST "${BASE_URL}/api/oauth/Login" \ | |
| 17 | + -H "Content-Type: application/x-www-form-urlencoded" \ | |
| 18 | + -d "account=admin&password=e10adc3949ba59abbe56e057f20f883e") | |
| 19 | + | |
| 20 | +TOKEN=$(echo $LOGIN_RESPONSE | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['token'])" 2>/dev/null) | |
| 21 | + | |
| 22 | +if [ -z "$TOKEN" ]; then | |
| 23 | + echo "❌ 登录失败,无法获取token" | |
| 24 | + exit 1 | |
| 25 | +fi | |
| 26 | + | |
| 27 | +echo "✅ Token获取成功" | |
| 28 | +echo "" | |
| 29 | + | |
| 30 | +# 2. 测试基本查询(无搜索条件) | |
| 31 | +echo "2. 测试基本查询(无搜索条件)..." | |
| 32 | +BASIC_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=5" \ | |
| 33 | + -H "Authorization: ${TOKEN}" \ | |
| 34 | + -H "Content-Type: application/json") | |
| 35 | + | |
| 36 | +echo "$BASIC_RESPONSE" | python3 -m json.tool | head -30 | |
| 37 | +echo "" | |
| 38 | + | |
| 39 | +# 3. 测试岗位搜索(gw=健康师) | |
| 40 | +echo "3. 测试岗位搜索(gw=健康师)..." | |
| 41 | +GW_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=5&gw=健康师" \ | |
| 42 | + -H "Authorization: ${TOKEN}" \ | |
| 43 | + -H "Content-Type: application/json") | |
| 44 | + | |
| 45 | +echo "$GW_RESPONSE" | python3 -m json.tool | head -40 | |
| 46 | +echo "" | |
| 47 | + | |
| 48 | +# 4. 测试门店ID搜索(使用实际的门店ID) | |
| 49 | +echo "4. 测试门店ID搜索..." | |
| 50 | +MDID="1649328471923847168" | |
| 51 | +MDID_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=5&mdid=${MDID}" \ | |
| 52 | + -H "Authorization: ${TOKEN}" \ | |
| 53 | + -H "Content-Type: application/json") | |
| 54 | + | |
| 55 | +echo "$MDID_RESPONSE" | python3 -m json.tool | head -40 | |
| 56 | +echo "" | |
| 57 | + | |
| 58 | +# 5. 测试组合搜索(门店ID + 岗位) | |
| 59 | +echo "5. 测试组合搜索(门店ID + 岗位)..." | |
| 60 | +COMBINED_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=5&mdid=${MDID}&gw=健康师" \ | |
| 61 | + -H "Authorization: ${TOKEN}" \ | |
| 62 | + -H "Content-Type: application/json") | |
| 63 | + | |
| 64 | +echo "$COMBINED_RESPONSE" | python3 -m json.tool | head -40 | |
| 65 | +echo "" | |
| 66 | + | |
| 67 | +# 6. 测试其他岗位 | |
| 68 | +echo "6. 测试其他岗位(gw=店助)..." | |
| 69 | +GW2_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=5&gw=店助" \ | |
| 70 | + -H "Authorization: ${TOKEN}" \ | |
| 71 | + -H "Content-Type: application/json") | |
| 72 | + | |
| 73 | +echo "$GW2_RESPONSE" | python3 -m json.tool | head -40 | |
| 74 | +echo "" | |
| 75 | + | |
| 76 | +echo "==========================================" | |
| 77 | +echo "测试完成" | |
| 78 | +echo "==========================================" | ... | ... |
scripts/sh/test_user_list_status_filter.sh
0 → 100755
| 1 | +#!/bin/bash | |
| 2 | + | |
| 3 | +# 测试用户列表接口 - 状态筛选功能 | |
| 4 | +# 使用方法: ./scripts/sh/test_user_list_status_filter.sh | |
| 5 | + | |
| 6 | +BASE_URL="http://localhost:2011" | |
| 7 | +TOKEN="" | |
| 8 | + | |
| 9 | +echo "==========================================" | |
| 10 | +echo "测试用户列表接口 - 状态筛选功能" | |
| 11 | +echo "==========================================" | |
| 12 | +echo "" | |
| 13 | + | |
| 14 | +# 1. 登录获取token | |
| 15 | +echo "1. 登录获取token..." | |
| 16 | +LOGIN_RESPONSE=$(curl -s -X POST "${BASE_URL}/api/oauth/Login" \ | |
| 17 | + -H "Content-Type: application/x-www-form-urlencoded" \ | |
| 18 | + -d "account=admin&password=e10adc3949ba59abbe56e057f20f883e") | |
| 19 | + | |
| 20 | +TOKEN=$(echo $LOGIN_RESPONSE | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['token'])" 2>/dev/null) | |
| 21 | + | |
| 22 | +if [ -z "$TOKEN" ]; then | |
| 23 | + echo "❌ 登录失败,无法获取token" | |
| 24 | + exit 1 | |
| 25 | +fi | |
| 26 | + | |
| 27 | +echo "✅ Token获取成功" | |
| 28 | +echo "" | |
| 29 | + | |
| 30 | +# 2. 测试查询全部(不筛选状态) | |
| 31 | +echo "2. 测试查询全部(不筛选状态)..." | |
| 32 | +ALL_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=3" \ | |
| 33 | + -H "Authorization: ${TOKEN}" \ | |
| 34 | + -H "Content-Type: application/json") | |
| 35 | + | |
| 36 | +ALL_TOTAL=$(echo "$ALL_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['pagination']['total'])" 2>/dev/null) | |
| 37 | +echo " 总记录数: ${ALL_TOTAL}" | |
| 38 | +echo "" | |
| 39 | + | |
| 40 | +# 3. 测试查询启用状态(enabledMark=1) | |
| 41 | +echo "3. 测试查询启用状态(enabledMark=1)..." | |
| 42 | +ENABLED_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=3&enabledMark=1" \ | |
| 43 | + -H "Authorization: ${TOKEN}" \ | |
| 44 | + -H "Content-Type: application/json") | |
| 45 | + | |
| 46 | +ENABLED_TOTAL=$(echo "$ENABLED_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['pagination']['total'])" 2>/dev/null) | |
| 47 | +echo " 总记录数: ${ENABLED_TOTAL}" | |
| 48 | +echo "$ENABLED_RESPONSE" | python3 -m json.tool | grep -A 10 '"list"' | head -20 | |
| 49 | +echo "" | |
| 50 | + | |
| 51 | +# 4. 测试查询禁用状态(enabledMark=0) | |
| 52 | +echo "4. 测试查询禁用状态(enabledMark=0)..." | |
| 53 | +DISABLED_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=3&enabledMark=0" \ | |
| 54 | + -H "Authorization: ${TOKEN}" \ | |
| 55 | + -H "Content-Type: application/json") | |
| 56 | + | |
| 57 | +DISABLED_TOTAL=$(echo "$DISABLED_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['pagination']['total'])" 2>/dev/null) | |
| 58 | +echo " 总记录数: ${DISABLED_TOTAL}" | |
| 59 | +echo "$DISABLED_RESPONSE" | python3 -m json.tool | grep -A 10 '"list"' | head -20 | |
| 60 | +echo "" | |
| 61 | + | |
| 62 | +# 5. 测试组合搜索(状态 + 岗位) | |
| 63 | +echo "5. 测试组合搜索(启用状态 + 岗位=健康师)..." | |
| 64 | +COMBINED1_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=3&enabledMark=1&gw=%E5%81%A5%E5%BA%B7%E5%B8%88" \ | |
| 65 | + -H "Authorization: ${TOKEN}" \ | |
| 66 | + -H "Content-Type: application/json") | |
| 67 | + | |
| 68 | +COMBINED1_TOTAL=$(echo "$COMBINED1_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['pagination']['total'])" 2>/dev/null) | |
| 69 | +echo " 总记录数: ${COMBINED1_TOTAL}" | |
| 70 | +echo "$COMBINED1_RESPONSE" | python3 -m json.tool | grep -A 10 '"list"' | head -20 | |
| 71 | +echo "" | |
| 72 | + | |
| 73 | +# 6. 测试组合搜索(状态 + 门店ID) | |
| 74 | +echo "6. 测试组合搜索(启用状态 + 门店ID)..." | |
| 75 | +COMBINED2_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=3&enabledMark=1&mdid=1649328471923847168" \ | |
| 76 | + -H "Authorization: ${TOKEN}" \ | |
| 77 | + -H "Content-Type: application/json") | |
| 78 | + | |
| 79 | +COMBINED2_TOTAL=$(echo "$COMBINED2_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['pagination']['total'])" 2>/dev/null) | |
| 80 | +echo " 总记录数: ${COMBINED2_TOTAL}" | |
| 81 | +echo "$COMBINED2_RESPONSE" | python3 -m json.tool | grep -A 10 '"list"' | head -20 | |
| 82 | +echo "" | |
| 83 | + | |
| 84 | +# 7. 测试组合搜索(状态 + 门店ID + 岗位) | |
| 85 | +echo "7. 测试组合搜索(启用状态 + 门店ID + 岗位)..." | |
| 86 | +COMBINED3_RESPONSE=$(curl -s -X GET "${BASE_URL}/api/permission/Users?currentPage=1&pageSize=3&enabledMark=1&mdid=1649328471923847168&gw=%E5%81%A5%E5%BA%B7%E5%B8%88" \ | |
| 87 | + -H "Authorization: ${TOKEN}" \ | |
| 88 | + -H "Content-Type: application/json") | |
| 89 | + | |
| 90 | +COMBINED3_TOTAL=$(echo "$COMBINED3_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['pagination']['total'])" 2>/dev/null) | |
| 91 | +echo " 总记录数: ${COMBINED3_TOTAL}" | |
| 92 | +echo "$COMBINED3_RESPONSE" | python3 -m json.tool | grep -A 10 '"list"' | head -20 | |
| 93 | +echo "" | |
| 94 | + | |
| 95 | +# 8. 验证返回数据的状态字段 | |
| 96 | +echo "8. 验证返回数据的状态字段..." | |
| 97 | +echo "$ENABLED_RESPONSE" | python3 -c " | |
| 98 | +import sys, json | |
| 99 | +data = json.load(sys.stdin) | |
| 100 | +if data['code'] == 200: | |
| 101 | + users = data['data']['list'] | |
| 102 | + print(f' 检查前3条记录的状态字段:') | |
| 103 | + for i, u in enumerate(users[:3], 1): | |
| 104 | + enabled = u.get('enabledMark', 'N/A') | |
| 105 | + print(f' 用户{i}: {u[\"realName\"]} - enabledMark: {enabled}') | |
| 106 | +else: | |
| 107 | + print(' 查询失败') | |
| 108 | +" | |
| 109 | +echo "" | |
| 110 | + | |
| 111 | +echo "==========================================" | |
| 112 | +echo "测试完成" | |
| 113 | +echo "==========================================" | |
| 114 | +echo "" | |
| 115 | +echo "测试结果汇总:" | |
| 116 | +echo " 全部用户: ${ALL_TOTAL}" | |
| 117 | +echo " 启用用户: ${ENABLED_TOTAL}" | |
| 118 | +echo " 禁用用户: ${DISABLED_TOTAL}" | |
| 119 | +echo " 启用+健康师: ${COMBINED1_TOTAL}" | |
| 120 | +echo " 启用+门店: ${COMBINED2_TOTAL}" | |
| 121 | +echo " 启用+门店+健康师: ${COMBINED3_TOTAL}" | ... | ... |