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,8 +124,12 @@ namespace NCC.Extend | ||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | /// <summary> | 126 | /// <summary> |
| 127 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 127 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 128 | /// </summary> | 128 | /// </summary> |
| 129 | + /// <remarks> | ||
| 130 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 131 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 132 | + /// </remarks> | ||
| 129 | [HttpGet("query-by-employee")] | 133 | [HttpGet("query-by-employee")] |
| 130 | public async Task<AssistantSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 134 | public async Task<AssistantSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 131 | { | 135 | { |
| @@ -135,7 +139,7 @@ namespace NCC.Extend | @@ -135,7 +139,7 @@ namespace NCC.Extend | ||
| 135 | throw NCCException.Oh("员工ID不能为空"); | 139 | throw NCCException.Oh("员工ID不能为空"); |
| 136 | var monthStr = $"{input.Year}{input.Month:D2}"; | 140 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 137 | var salary = await _db.Queryable<LqAssistantSalaryStatisticsEntity>() | 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 | .Select(x => new AssistantSalaryOutput | 143 | .Select(x => new AssistantSalaryOutput |
| 140 | { | 144 | { |
| 141 | Id = x.Id, | 145 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqBusinessUnitManagerSalaryService.cs
| @@ -132,8 +132,12 @@ namespace NCC.Extend | @@ -132,8 +132,12 @@ namespace NCC.Extend | ||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | /// <summary> | 134 | /// <summary> |
| 135 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 135 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 136 | /// </summary> | 136 | /// </summary> |
| 137 | + /// <remarks> | ||
| 138 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 139 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 140 | + /// </remarks> | ||
| 137 | [HttpGet("query-by-employee")] | 141 | [HttpGet("query-by-employee")] |
| 138 | public async Task<BusinessUnitManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 142 | public async Task<BusinessUnitManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 139 | { | 143 | { |
| @@ -143,7 +147,7 @@ namespace NCC.Extend | @@ -143,7 +147,7 @@ namespace NCC.Extend | ||
| 143 | throw NCCException.Oh("员工ID不能为空"); | 147 | throw NCCException.Oh("员工ID不能为空"); |
| 144 | var monthStr = $"{input.Year}{input.Month:D2}"; | 148 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 145 | var salary = await _db.Queryable<LqBusinessUnitManagerSalaryStatisticsEntity>() | 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 | .Select(x => new BusinessUnitManagerSalaryOutput | 151 | .Select(x => new BusinessUnitManagerSalaryOutput |
| 148 | { | 152 | { |
| 149 | Id = x.Id, | 153 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqDirectorSalaryService.cs
| @@ -154,8 +154,12 @@ namespace NCC.Extend | @@ -154,8 +154,12 @@ namespace NCC.Extend | ||
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | /// <summary> | 156 | /// <summary> |
| 157 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 157 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 158 | /// </summary> | 158 | /// </summary> |
| 159 | + /// <remarks> | ||
| 160 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 161 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 162 | + /// </remarks> | ||
| 159 | [HttpGet("query-by-employee")] | 163 | [HttpGet("query-by-employee")] |
| 160 | public async Task<DirectorSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 164 | public async Task<DirectorSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 161 | { | 165 | { |
| @@ -165,7 +169,7 @@ namespace NCC.Extend | @@ -165,7 +169,7 @@ namespace NCC.Extend | ||
| 165 | throw NCCException.Oh("员工ID不能为空"); | 169 | throw NCCException.Oh("员工ID不能为空"); |
| 166 | var monthStr = $"{input.Year}{input.Month:D2}"; | 170 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 167 | var salary = await _db.Queryable<LqDirectorSalaryStatisticsEntity>() | 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 | .Select(x => new DirectorSalaryOutput | 173 | .Select(x => new DirectorSalaryOutput |
| 170 | { | 174 | { |
| 171 | Id = x.Id, | 175 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqMajorProjectDirectorSalaryService.cs
| @@ -127,8 +127,12 @@ namespace NCC.Extend | @@ -127,8 +127,12 @@ namespace NCC.Extend | ||
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | /// <summary> | 129 | /// <summary> |
| 130 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 130 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 131 | /// </summary> | 131 | /// </summary> |
| 132 | + /// <remarks> | ||
| 133 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 134 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 135 | + /// </remarks> | ||
| 132 | [HttpGet("query-by-employee")] | 136 | [HttpGet("query-by-employee")] |
| 133 | public async Task<MajorProjectDirectorSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 137 | public async Task<MajorProjectDirectorSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 134 | { | 138 | { |
| @@ -138,7 +142,7 @@ namespace NCC.Extend | @@ -138,7 +142,7 @@ namespace NCC.Extend | ||
| 138 | throw NCCException.Oh("员工ID不能为空"); | 142 | throw NCCException.Oh("员工ID不能为空"); |
| 139 | var monthStr = $"{input.Year}{input.Month:D2}"; | 143 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 140 | var salary = await _db.Queryable<LqMajorProjectDirectorSalaryStatisticsEntity>() | 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 | .Select(x => new MajorProjectDirectorSalaryOutput | 146 | .Select(x => new MajorProjectDirectorSalaryOutput |
| 143 | { | 147 | { |
| 144 | Id = x.Id, | 148 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqMajorProjectTeacherSalaryService.cs
| @@ -142,8 +142,12 @@ namespace NCC.Extend | @@ -142,8 +142,12 @@ namespace NCC.Extend | ||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | /// <summary> | 144 | /// <summary> |
| 145 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 145 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 146 | /// </summary> | 146 | /// </summary> |
| 147 | + /// <remarks> | ||
| 148 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 149 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 150 | + /// </remarks> | ||
| 147 | [HttpGet("query-by-employee")] | 151 | [HttpGet("query-by-employee")] |
| 148 | public async Task<MajorProjectTeacherSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 152 | public async Task<MajorProjectTeacherSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 149 | { | 153 | { |
| @@ -153,7 +157,7 @@ namespace NCC.Extend | @@ -153,7 +157,7 @@ namespace NCC.Extend | ||
| 153 | throw NCCException.Oh("员工ID不能为空"); | 157 | throw NCCException.Oh("员工ID不能为空"); |
| 154 | var monthStr = $"{input.Year}{input.Month:D2}"; | 158 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 155 | var salary = await _db.Queryable<LqMajorProjectTeacherSalaryStatisticsEntity>() | 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 | .Select(x => new MajorProjectTeacherSalaryOutput | 161 | .Select(x => new MajorProjectTeacherSalaryOutput |
| 158 | { | 162 | { |
| 159 | Id = x.Id, | 163 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqSalaryService.cs
| @@ -175,12 +175,13 @@ namespace NCC.Extend | @@ -175,12 +175,13 @@ namespace NCC.Extend | ||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | /// <summary> | 177 | /// <summary> |
| 178 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 178 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 179 | /// </summary> | 179 | /// </summary> |
| 180 | /// <remarks> | 180 | /// <remarks> |
| 181 | /// 根据年份、月份和员工ID查询对应员工的工资记录 | 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,7 +213,7 @@ namespace NCC.Extend | ||
| 212 | var monthStr = $"{input.Year}{input.Month:D2}"; | 213 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 213 | 214 | ||
| 214 | var salary = await _db.Queryable<LqSalaryStatisticsEntity>() | 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 | .Select(x => new HealthCoachSalaryOutput | 217 | .Select(x => new HealthCoachSalaryOutput |
| 217 | { | 218 | { |
| 218 | Id = x.Id, | 219 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqStoreManagerSalaryService.cs
| @@ -133,8 +133,12 @@ namespace NCC.Extend | @@ -133,8 +133,12 @@ namespace NCC.Extend | ||
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | /// <summary> | 135 | /// <summary> |
| 136 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 136 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 137 | /// </summary> | 137 | /// </summary> |
| 138 | + /// <remarks> | ||
| 139 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 140 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 141 | + /// </remarks> | ||
| 138 | [HttpGet("query-by-employee")] | 142 | [HttpGet("query-by-employee")] |
| 139 | public async Task<StoreManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 143 | public async Task<StoreManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 140 | { | 144 | { |
| @@ -144,7 +148,7 @@ namespace NCC.Extend | @@ -144,7 +148,7 @@ namespace NCC.Extend | ||
| 144 | throw NCCException.Oh("员工ID不能为空"); | 148 | throw NCCException.Oh("员工ID不能为空"); |
| 145 | var monthStr = $"{input.Year}{input.Month:D2}"; | 149 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 146 | var salary = await _db.Queryable<LqStoreManagerSalaryStatisticsEntity>() | 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 | .Select(x => new StoreManagerSalaryOutput | 152 | .Select(x => new StoreManagerSalaryOutput |
| 149 | { | 153 | { |
| 150 | Id = x.Id, | 154 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqTechGeneralManagerSalaryService.cs
| @@ -131,8 +131,12 @@ namespace NCC.Extend | @@ -131,8 +131,12 @@ namespace NCC.Extend | ||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | /// <summary> | 133 | /// <summary> |
| 134 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 134 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 135 | /// </summary> | 135 | /// </summary> |
| 136 | + /// <remarks> | ||
| 137 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 138 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 139 | + /// </remarks> | ||
| 136 | [HttpGet("query-by-employee")] | 140 | [HttpGet("query-by-employee")] |
| 137 | public async Task<TechGeneralManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 141 | public async Task<TechGeneralManagerSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 138 | { | 142 | { |
| @@ -142,7 +146,7 @@ namespace NCC.Extend | @@ -142,7 +146,7 @@ namespace NCC.Extend | ||
| 142 | throw NCCException.Oh("员工ID不能为空"); | 146 | throw NCCException.Oh("员工ID不能为空"); |
| 143 | var monthStr = $"{input.Year}{input.Month:D2}"; | 147 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 144 | var salary = await _db.Queryable<LqTechGeneralManagerSalaryStatisticsEntity>() | 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 | .Select(x => new TechGeneralManagerSalaryOutput | 150 | .Select(x => new TechGeneralManagerSalaryOutput |
| 147 | { | 151 | { |
| 148 | Id = x.Id, | 152 | Id = x.Id, |
netcore/src/Modularity/Extend/NCC.Extend/LqTechTeacherSalaryService.cs
| @@ -146,8 +146,12 @@ namespace NCC.Extend | @@ -146,8 +146,12 @@ namespace NCC.Extend | ||
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | /// <summary> | 148 | /// <summary> |
| 149 | - /// 通过月份和员工ID查询工资(仅查询已锁定的工资) | 149 | + /// 通过月份和员工ID查询工资(仅查询已锁定且未确认的工资) |
| 150 | /// </summary> | 150 | /// </summary> |
| 151 | + /// <remarks> | ||
| 152 | + /// **重要**:此接口只能查询已锁定(IsLocked=1)且未确认(EmployeeConfirmStatus=0或null)的工资记录 | ||
| 153 | + /// **注意**:已确认的工资记录无法通过此接口查询 | ||
| 154 | + /// </remarks> | ||
| 151 | [HttpGet("query-by-employee")] | 155 | [HttpGet("query-by-employee")] |
| 152 | public async Task<TechTeacherSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) | 156 | public async Task<TechTeacherSalaryOutput> GetSalaryByEmployee([FromQuery] SalaryQueryByEmployeeInput input) |
| 153 | { | 157 | { |
| @@ -157,7 +161,7 @@ namespace NCC.Extend | @@ -157,7 +161,7 @@ namespace NCC.Extend | ||
| 157 | throw NCCException.Oh("员工ID不能为空"); | 161 | throw NCCException.Oh("员工ID不能为空"); |
| 158 | var monthStr = $"{input.Year}{input.Month:D2}"; | 162 | var monthStr = $"{input.Year}{input.Month:D2}"; |
| 159 | var salary = await _db.Queryable<LqTechTeacherSalaryStatisticsEntity>() | 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 | .Select(x => new TechTeacherSalaryOutput | 165 | .Select(x => new TechTeacherSalaryOutput |
| 162 | { | 166 | { |
| 163 | Id = x.Id, | 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,5 +13,20 @@ namespace NCC.System.Entitys.Dto.Permission.User | ||
| 13 | /// 机构ID | 13 | /// 机构ID |
| 14 | /// </summary> | 14 | /// </summary> |
| 15 | public string organizeId { get; set; } | 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,6 +136,9 @@ namespace NCC.System.Service.Permission | ||
| 136 | //组织机构 | 136 | //组织机构 |
| 137 | .WhereIF(organizeIds.Any(), u => organizeIds.Contains(SqlFunc.ToString(u.organizeId))) | 137 | .WhereIF(organizeIds.Any(), u => organizeIds.Contains(SqlFunc.ToString(u.organizeId))) |
| 138 | .WhereIF(!pageInput.keyword.IsNullOrEmpty(), u => u.account.Contains(pageInput.keyword) || u.realName.Contains(pageInput.keyword)) | 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 | .Where(a => a.deleteMark == null) | 142 | .Where(a => a.deleteMark == null) |
| 140 | .OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) | 143 | .OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc) |
| 141 | .ToPagedListAsync(pageInput.currentPage, pageInput.pageSize); | 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}" |