Commit 7d89becc85df33f45b7d8a245c2c9f82dec97ece

Authored by “wangming”
1 parent 297c68d7

feat: 退款明细列表优化 - 支持显示多个健康师及业绩

- 修改退款明细列表查询逻辑,从退款健康师业绩表查询(而非开单健康师业绩表)
- 支持一个退款明细显示多个健康师,格式:姓名(业绩)、姓名(业绩)
- 新增实际退款金额字段,显示所有健康师业绩之和
- 优化前端显示,健康师列显示每个健康师及其业绩
- 添加测试脚本test_refund_detail.sh
antis-ncc-admin/src/views/statisticsList/form21.vue
@@ -270,10 +270,10 @@ @@ -270,10 +270,10 @@
270 </el-tag> 270 </el-tag>
271 </template> 271 </template>
272 </el-table-column> 272 </el-table-column>
273 - <el-table-column prop="healthCoachName" label="健康师" min-width="120" sortable="custom"> 273 + <el-table-column prop="healthCoachName" label="健康师及业绩" min-width="200" sortable="custom">
274 <template slot-scope="scope"> 274 <template slot-scope="scope">
275 <i class="el-icon-user-solid" style="margin-right: 4px; color: #F56C6C;"></i> 275 <i class="el-icon-user-solid" style="margin-right: 4px; color: #F56C6C;"></i>
276 - <span>{{ scope.row.healthCoachName || '无' }}</span> 276 + <span :title="scope.row.healthCoachName || '无'" style="white-space: normal; word-break: break-all;">{{ scope.row.healthCoachName || '无' }}</span>
277 </template> 277 </template>
278 </el-table-column> 278 </el-table-column>
279 <el-table-column prop="healthCoachPerformance" label="健康师业绩" min-width="130" sortable="custom"> 279 <el-table-column prop="healthCoachPerformance" label="健康师业绩" min-width="130" sortable="custom">
@@ -281,6 +281,12 @@ @@ -281,6 +281,12 @@
281 <span class="amount-value">¥{{ formatMoney(scope.row.healthCoachPerformance) }}</span> 281 <span class="amount-value">¥{{ formatMoney(scope.row.healthCoachPerformance) }}</span>
282 </template> 282 </template>
283 </el-table-column> 283 </el-table-column>
  284 + <el-table-column prop="actualRefundAmount" label="实际退款金额" min-width="140" sortable="custom">
  285 + <template slot-scope="scope">
  286 + <i class="el-icon-money" style="margin-right: 4px; color: #67C23A;"></i>
  287 + <span class="amount-value">¥{{ formatMoney(scope.row.actualRefundAmount) }}</span>
  288 + </template>
  289 + </el-table-column>
284 </NCC-table> 290 </NCC-table>
285 <pagination 291 <pagination
286 v-show="total > 0" 292 v-show="total > 0"
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/RefundDetailListOutput.cs
@@ -83,19 +83,24 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk @@ -83,19 +83,24 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
83 public string itemCategory { get; set; } 83 public string itemCategory { get; set; }
84 84
85 /// <summary> 85 /// <summary>
86 - /// 健康师账号 86 + /// 健康师账号(保留字段,兼容旧版本,显示第一个健康师)
87 /// </summary> 87 /// </summary>
88 public string healthCoachId { get; set; } 88 public string healthCoachId { get; set; }
89 89
90 /// <summary> 90 /// <summary>
91 - /// 健康师姓名 91 + /// 健康师姓名(多个健康师用顿号分隔)
92 /// </summary> 92 /// </summary>
93 public string healthCoachName { get; set; } 93 public string healthCoachName { get; set; }
94 94
95 /// <summary> 95 /// <summary>
96 - /// 健康师业绩 96 + /// 健康师业绩(保留字段,兼容旧版本,显示第一个健康师业绩)
97 /// </summary> 97 /// </summary>
98 public decimal healthCoachPerformance { get; set; } 98 public decimal healthCoachPerformance { get; set; }
  99 +
  100 + /// <summary>
  101 + /// 实际退款金额(所有健康师业绩之和)
  102 + /// </summary>
  103 + public decimal actualRefundAmount { get; set; }
99 } 104 }
100 } 105 }
101 106
netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
@@ -916,39 +916,36 @@ namespace NCC.Extend.LqHytkHytk @@ -916,39 +916,36 @@ namespace NCC.Extend.LqHytkHytk
916 memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? ""); 916 memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? "");
917 } 917 }
918 918
919 - // 5. 批量查询健康师业绩信息  
920 - var billingItemIds = mxList.Select(x => x.BillingItemId).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();  
921 - var healthCoachDict = new Dictionary<string, (string Id, string Name, decimal Performance)>();  
922 - if (billingItemIds.Any()) 919 + // 5. 批量查询退款健康师业绩信息(从退款健康师业绩表查询,而不是开单健康师业绩表)
  920 + var mxIds = mxList.Select(x => x.Id).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();
  921 + // 使用字典存储每个退款明细对应的多个健康师信息
  922 + var healthCoachDict = new Dictionary<string, List<(string Id, string Name, decimal Performance)>>();
  923 + var actualRefundAmountDict = new Dictionary<string, decimal>();
  924 +
  925 + if (mxIds.Any())
923 { 926 {
924 - // 通过开单品项明细ID查询开单品项明细,获取开单编号和品项明细ID  
925 - var pxmxList = await _db.Queryable<LqKdPxmxEntity>()  
926 - .Where(x => billingItemIds.Contains(x.Id))  
927 - .Select(x => new { x.Id, x.Glkdbh }) 927 + // 通过退卡品相表ID(F_CardReturn)查询退款健康师业绩
  928 + var jksyjList = await _db.Queryable<LqHytkJksyjEntity>()
  929 + .Where(x => mxIds.Contains(x.CardReturn) && x.IsEffective == StatusEnum.有效.GetHashCode())
  930 + .Select(x => new { x.CardReturn, x.Jkszh, x.Jksxm, x.Jksyj })
928 .ToListAsync(); 931 .ToListAsync();
929 932
930 - if (pxmxList.Any()) 933 + // 按退款明细ID分组,建立映射
  934 + foreach (var jksyj in jksyjList)
931 { 935 {
932 - var glkdbhList = pxmxList.Select(x => x.Glkdbh).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();  
933 - var pxmxIdList = pxmxList.Select(x => x.Id).Distinct().ToList(); 936 + if (string.IsNullOrEmpty(jksyj.CardReturn))
  937 + continue;
934 938
935 - // 通过开单编号和品项明细ID查询健康师业绩  
936 - var jksyjList = await _db.Queryable<LqKdJksyjEntity>()  
937 - .Where(x => glkdbhList.Contains(x.Glkdbh) && pxmxIdList.Contains(x.Kdpxid) && x.IsEffective == 1)  
938 - .Select(x => new { x.Glkdbh, x.Kdpxid, x.Jkszh, x.Jksxm, x.Jksyj })  
939 - .ToListAsync(); 939 + var jksyjValue = jksyj.Jksyj ?? 0m;
940 940
941 - // 建立开单品项明细ID到健康师信息的映射  
942 - foreach (var jksyj in jksyjList) 941 + if (!healthCoachDict.ContainsKey(jksyj.CardReturn))
943 { 942 {
944 - // 找到对应的开单品项明细ID  
945 - var pxmxId = pxmxList.FirstOrDefault(x => x.Glkdbh == jksyj.Glkdbh && x.Id == jksyj.Kdpxid)?.Id;  
946 - if (!string.IsNullOrEmpty(pxmxId))  
947 - {  
948 - var jksyjValue = decimal.TryParse(jksyj.Jksyj, out var perf) ? perf : 0;  
949 - healthCoachDict[pxmxId] = (jksyj.Jkszh ?? "", jksyj.Jksxm ?? "", jksyjValue);  
950 - } 943 + healthCoachDict[jksyj.CardReturn] = new List<(string Id, string Name, decimal Performance)>();
  944 + actualRefundAmountDict[jksyj.CardReturn] = 0m;
951 } 945 }
  946 +
  947 + healthCoachDict[jksyj.CardReturn].Add((jksyj.Jkszh ?? "", jksyj.Jksxm ?? "", jksyjValue));
  948 + actualRefundAmountDict[jksyj.CardReturn] += jksyjValue;
952 } 949 }
953 } 950 }
954 951
@@ -957,7 +954,7 @@ namespace NCC.Extend.LqHytkHytk @@ -957,7 +954,7 @@ namespace NCC.Extend.LqHytkHytk
957 foreach (var mx in mxList) 954 foreach (var mx in mxList)
958 { 955 {
959 var refundInfo = refundInfoDict.ContainsKey(mx.RefundInfoId) ? refundInfoDict[mx.RefundInfoId] : null; 956 var refundInfo = refundInfoDict.ContainsKey(mx.RefundInfoId) ? refundInfoDict[mx.RefundInfoId] : null;
960 - 957 +
961 // 应用筛选条件 958 // 应用筛选条件
962 if (input.storeIds != null && input.storeIds.Any()) 959 if (input.storeIds != null && input.storeIds.Any())
963 { 960 {
@@ -973,10 +970,29 @@ namespace NCC.Extend.LqHytkHytk @@ -973,10 +970,29 @@ namespace NCC.Extend.LqHytkHytk
973 var memberId = mx.MemberId ?? (refundInfo?.Hy); 970 var memberId = mx.MemberId ?? (refundInfo?.Hy);
974 var refundTime = mx.Tksj ?? refundInfo?.Tksj; 971 var refundTime = mx.Tksj ?? refundInfo?.Tksj;
975 972
976 - // 获取健康师信息  
977 - var healthCoachInfo = !string.IsNullOrEmpty(mx.BillingItemId) && healthCoachDict.ContainsKey(mx.BillingItemId)  
978 - ? healthCoachDict[mx.BillingItemId]  
979 - : (Id: "", Name: "", Performance: 0m); 973 + // 获取健康师信息(支持多个健康师)
  974 + var healthCoachList = healthCoachDict.ContainsKey(mx.Id)
  975 + ? healthCoachDict[mx.Id]
  976 + : new List<(string Id, string Name, decimal Performance)>();
  977 +
  978 + // 合并多个健康师姓名和业绩(格式:姓名(业绩),用顿号分隔)
  979 + var healthCoachNames = "";
  980 + if (healthCoachList.Any())
  981 + {
  982 + var healthCoachItems = healthCoachList
  983 + .Where(h => !string.IsNullOrEmpty(h.Name))
  984 + .Select(h => $"{h.Name}({h.Performance:F2})")
  985 + .ToList();
  986 + healthCoachNames = string.Join("、", healthCoachItems);
  987 + }
  988 +
  989 + // 获取第一个健康师信息(兼容旧版本)
  990 + var firstHealthCoach = healthCoachList.FirstOrDefault();
  991 +
  992 + // 获取实际退款金额(所有健康师业绩之和)
  993 + var actualRefundAmount = actualRefundAmountDict.ContainsKey(mx.Id)
  994 + ? actualRefundAmountDict[mx.Id]
  995 + : 0m;
980 996
981 resultList.Add(new RefundDetailListOutput 997 resultList.Add(new RefundDetailListOutput
982 { 998 {
@@ -995,16 +1011,17 @@ namespace NCC.Extend.LqHytkHytk @@ -995,16 +1011,17 @@ namespace NCC.Extend.LqHytkHytk
995 beautyType = mx.BeautyType, 1011 beautyType = mx.BeautyType,
996 sourceType = mx.SourceType, 1012 sourceType = mx.SourceType,
997 itemCategory = mx.ItemCategory, 1013 itemCategory = mx.ItemCategory,
998 - healthCoachId = healthCoachInfo.Id,  
999 - healthCoachName = healthCoachInfo.Name,  
1000 - healthCoachPerformance = healthCoachInfo.Performance 1014 + healthCoachId = firstHealthCoach.Id,
  1015 + healthCoachName = healthCoachNames,
  1016 + healthCoachPerformance = firstHealthCoach.Performance,
  1017 + actualRefundAmount = actualRefundAmount
1001 }); 1018 });
1002 } 1019 }
1003 1020
1004 // 7. 排序 1021 // 7. 排序
1005 var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx; 1022 var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx;
1006 var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort; 1023 var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort;
1007 - 1024 +
1008 if (sort.ToLower() == "desc") 1025 if (sort.ToLower() == "desc")
1009 { 1026 {
1010 resultList = resultList.OrderByDescending(x => GetPropertyValue(x, sidx)).ToList(); 1027 resultList = resultList.OrderByDescending(x => GetPropertyValue(x, sidx)).ToList();
@@ -1114,39 +1131,36 @@ namespace NCC.Extend.LqHytkHytk @@ -1114,39 +1131,36 @@ namespace NCC.Extend.LqHytkHytk
1114 memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? ""); 1131 memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? "");
1115 } 1132 }
1116 1133
1117 - // 5. 批量查询健康师业绩信息  
1118 - var billingItemIds = mxList.Select(x => x.BillingItemId).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();  
1119 - var healthCoachDict = new Dictionary<string, (string Id, string Name, decimal Performance)>();  
1120 - if (billingItemIds.Any()) 1134 + // 5. 批量查询退款健康师业绩信息(从退款健康师业绩表查询,而不是开单健康师业绩表)
  1135 + var mxIds = mxList.Select(x => x.Id).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();
  1136 + // 使用字典存储每个退款明细对应的多个健康师信息
  1137 + var healthCoachDict = new Dictionary<string, List<(string Id, string Name, decimal Performance)>>();
  1138 + var actualRefundAmountDict = new Dictionary<string, decimal>();
  1139 +
  1140 + if (mxIds.Any())
1121 { 1141 {
1122 - // 通过开单品项明细ID查询开单品项明细,获取开单编号和品项明细ID  
1123 - var pxmxList = await _db.Queryable<LqKdPxmxEntity>()  
1124 - .Where(x => billingItemIds.Contains(x.Id))  
1125 - .Select(x => new { x.Id, x.Glkdbh }) 1142 + // 通过退卡品相表ID(F_CardReturn)查询退款健康师业绩
  1143 + var jksyjList = await _db.Queryable<LqHytkJksyjEntity>()
  1144 + .Where(x => mxIds.Contains(x.CardReturn) && x.IsEffective == StatusEnum.有效.GetHashCode())
  1145 + .Select(x => new { x.CardReturn, x.Jkszh, x.Jksxm, x.Jksyj })
1126 .ToListAsync(); 1146 .ToListAsync();
1127 1147
1128 - if (pxmxList.Any()) 1148 + // 按退款明细ID分组,建立映射
  1149 + foreach (var jksyj in jksyjList)
1129 { 1150 {
1130 - var glkdbhList = pxmxList.Select(x => x.Glkdbh).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();  
1131 - var pxmxIdList = pxmxList.Select(x => x.Id).Distinct().ToList(); 1151 + if (string.IsNullOrEmpty(jksyj.CardReturn))
  1152 + continue;
1132 1153
1133 - // 通过开单编号和品项明细ID查询健康师业绩  
1134 - var jksyjList = await _db.Queryable<LqKdJksyjEntity>()  
1135 - .Where(x => glkdbhList.Contains(x.Glkdbh) && pxmxIdList.Contains(x.Kdpxid) && x.IsEffective == 1)  
1136 - .Select(x => new { x.Glkdbh, x.Kdpxid, x.Jkszh, x.Jksxm, x.Jksyj })  
1137 - .ToListAsync(); 1154 + var jksyjValue = jksyj.Jksyj ?? 0m;
1138 1155
1139 - // 建立开单品项明细ID到健康师信息的映射  
1140 - foreach (var jksyj in jksyjList) 1156 + if (!healthCoachDict.ContainsKey(jksyj.CardReturn))
1141 { 1157 {
1142 - // 找到对应的开单品项明细ID  
1143 - var pxmxId = pxmxList.FirstOrDefault(x => x.Glkdbh == jksyj.Glkdbh && x.Id == jksyj.Kdpxid)?.Id;  
1144 - if (!string.IsNullOrEmpty(pxmxId))  
1145 - {  
1146 - var jksyjValue = decimal.TryParse(jksyj.Jksyj, out var perf) ? perf : 0;  
1147 - healthCoachDict[pxmxId] = (jksyj.Jkszh ?? "", jksyj.Jksxm ?? "", jksyjValue);  
1148 - } 1158 + healthCoachDict[jksyj.CardReturn] = new List<(string Id, string Name, decimal Performance)>();
  1159 + actualRefundAmountDict[jksyj.CardReturn] = 0m;
1149 } 1160 }
  1161 +
  1162 + healthCoachDict[jksyj.CardReturn].Add((jksyj.Jkszh ?? "", jksyj.Jksxm ?? "", jksyjValue));
  1163 + actualRefundAmountDict[jksyj.CardReturn] += jksyjValue;
1150 } 1164 }
1151 } 1165 }
1152 1166
@@ -1155,7 +1169,7 @@ namespace NCC.Extend.LqHytkHytk @@ -1155,7 +1169,7 @@ namespace NCC.Extend.LqHytkHytk
1155 foreach (var mx in mxList) 1169 foreach (var mx in mxList)
1156 { 1170 {
1157 var refundInfo = refundInfoDict.ContainsKey(mx.RefundInfoId) ? refundInfoDict[mx.RefundInfoId] : null; 1171 var refundInfo = refundInfoDict.ContainsKey(mx.RefundInfoId) ? refundInfoDict[mx.RefundInfoId] : null;
1158 - 1172 +
1159 // 应用筛选条件 1173 // 应用筛选条件
1160 if (input.storeIds != null && input.storeIds.Any()) 1174 if (input.storeIds != null && input.storeIds.Any())
1161 { 1175 {
@@ -1171,10 +1185,29 @@ namespace NCC.Extend.LqHytkHytk @@ -1171,10 +1185,29 @@ namespace NCC.Extend.LqHytkHytk
1171 var memberId = mx.MemberId ?? (refundInfo?.Hy); 1185 var memberId = mx.MemberId ?? (refundInfo?.Hy);
1172 var refundTime = mx.Tksj ?? refundInfo?.Tksj; 1186 var refundTime = mx.Tksj ?? refundInfo?.Tksj;
1173 1187
1174 - // 获取健康师信息  
1175 - var healthCoachInfo = !string.IsNullOrEmpty(mx.BillingItemId) && healthCoachDict.ContainsKey(mx.BillingItemId)  
1176 - ? healthCoachDict[mx.BillingItemId]  
1177 - : (Id: "", Name: "", Performance: 0m); 1188 + // 获取健康师信息(支持多个健康师)
  1189 + var healthCoachList = healthCoachDict.ContainsKey(mx.Id)
  1190 + ? healthCoachDict[mx.Id]
  1191 + : new List<(string Id, string Name, decimal Performance)>();
  1192 +
  1193 + // 合并多个健康师姓名和业绩(格式:姓名(业绩),用顿号分隔)
  1194 + var healthCoachNames = "";
  1195 + if (healthCoachList.Any())
  1196 + {
  1197 + var healthCoachItems = healthCoachList
  1198 + .Where(h => !string.IsNullOrEmpty(h.Name))
  1199 + .Select(h => $"{h.Name}({h.Performance:F2})")
  1200 + .ToList();
  1201 + healthCoachNames = string.Join("、", healthCoachItems);
  1202 + }
  1203 +
  1204 + // 获取第一个健康师信息(兼容旧版本)
  1205 + var firstHealthCoach = healthCoachList.FirstOrDefault();
  1206 +
  1207 + // 获取实际退款金额(所有健康师业绩之和)
  1208 + var actualRefundAmount = actualRefundAmountDict.ContainsKey(mx.Id)
  1209 + ? actualRefundAmountDict[mx.Id]
  1210 + : 0m;
1178 1211
1179 resultList.Add(new RefundDetailListOutput 1212 resultList.Add(new RefundDetailListOutput
1180 { 1213 {
@@ -1193,16 +1226,17 @@ namespace NCC.Extend.LqHytkHytk @@ -1193,16 +1226,17 @@ namespace NCC.Extend.LqHytkHytk
1193 beautyType = mx.BeautyType, 1226 beautyType = mx.BeautyType,
1194 sourceType = mx.SourceType, 1227 sourceType = mx.SourceType,
1195 itemCategory = mx.ItemCategory, 1228 itemCategory = mx.ItemCategory,
1196 - healthCoachId = healthCoachInfo.Id,  
1197 - healthCoachName = healthCoachInfo.Name,  
1198 - healthCoachPerformance = healthCoachInfo.Performance 1229 + healthCoachId = firstHealthCoach.Id,
  1230 + healthCoachName = healthCoachNames,
  1231 + healthCoachPerformance = firstHealthCoach.Performance,
  1232 + actualRefundAmount = actualRefundAmount
1199 }); 1233 });
1200 } 1234 }
1201 1235
1202 // 7. 排序 1236 // 7. 排序
1203 var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx; 1237 var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx;
1204 var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort; 1238 var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort;
1205 - 1239 +
1206 if (sort.ToLower() == "desc") 1240 if (sort.ToLower() == "desc")
1207 { 1241 {
1208 resultList = resultList.OrderByDescending(x => GetPropertyValue(x, sidx)).ToList(); 1242 resultList = resultList.OrderByDescending(x => GetPropertyValue(x, sidx)).ToList();
@@ -1264,7 +1298,7 @@ namespace NCC.Extend.LqHytkHytk @@ -1264,7 +1298,7 @@ namespace NCC.Extend.LqHytkHytk
1264 1298
1265 // 定义导出字段 1299 // 定义导出字段
1266 List<ParamsModel> paramList = 1300 List<ParamsModel> paramList =
1267 - "[{\"value\":\"门店\",\"field\":\"storeName\"},{\"value\":\"会员ID\",\"field\":\"memberId\"},{\"value\":\"会员名称\",\"field\":\"memberName\"},{\"value\":\"会员电话\",\"field\":\"memberPhone\"},{\"value\":\"退卡时间\",\"field\":\"refundTime\"},{\"value\":\"退卡品项ID\",\"field\":\"itemId\"},{\"value\":\"退卡品项名称\",\"field\":\"itemName\"},{\"value\":\"退卡数量\",\"field\":\"refundQuantity\"},{\"value\":\"单价\",\"field\":\"unitPrice\"},{\"value\":\"总价\",\"field\":\"totalPrice\"},{\"value\":\"业绩类型\",\"field\":\"performanceType\"},{\"value\":\"科美类型\",\"field\":\"beautyType\"},{\"value\":\"来源类型\",\"field\":\"sourceType\"},{\"value\":\"品项分类\",\"field\":\"itemCategory\"},]".ToList<ParamsModel>(); 1301 + "[{\"value\":\"门店\",\"field\":\"storeName\"},{\"value\":\"会员ID\",\"field\":\"memberId\"},{\"value\":\"会员名称\",\"field\":\"memberName\"},{\"value\":\"会员电话\",\"field\":\"memberPhone\"},{\"value\":\"退卡时间\",\"field\":\"refundTime\"},{\"value\":\"退卡品项ID\",\"field\":\"itemId\"},{\"value\":\"退卡品项名称\",\"field\":\"itemName\"},{\"value\":\"退卡数量\",\"field\":\"refundQuantity\"},{\"value\":\"单价\",\"field\":\"unitPrice\"},{\"value\":\"总价\",\"field\":\"totalPrice\"},{\"value\":\"业绩类型\",\"field\":\"performanceType\"},{\"value\":\"科美类型\",\"field\":\"beautyType\"},{\"value\":\"来源类型\",\"field\":\"sourceType\"},{\"value\":\"品项分类\",\"field\":\"itemCategory\"},{\"value\":\"健康师\",\"field\":\"healthCoachName\"},{\"value\":\"健康师业绩\",\"field\":\"healthCoachPerformance\"},]".ToList<ParamsModel>();
1268 1302
1269 ExcelConfig excelconfig = new ExcelConfig(); 1303 ExcelConfig excelconfig = new ExcelConfig();
1270 excelconfig.FileName = "退卡明细_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls"; 1304 excelconfig.FileName = "退卡明细_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls";
test_refund_detail.sh 0 → 100755
  1 +#!/bin/bash
  2 +
  3 +# 测试退款明细列表接口
  4 +
  5 +echo "=== 测试退款明细列表接口 ==="
  6 +echo ""
  7 +
  8 +# 步骤1: 获取Token
  9 +echo "步骤1: 获取Token..."
  10 +TOKEN_RESPONSE=$(curl -s -X POST "http://localhost:2011/api/oauth/Login" \
  11 + -H "Content-Type: application/x-www-form-urlencoded" \
  12 + -d "account=admin&password=e10adc3949ba59abbe56e057f20f883e")
  13 +
  14 +TOKEN=$(echo "$TOKEN_RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data['data']['token'])" 2>/dev/null)
  15 +
  16 +if [ -z "$TOKEN" ]; then
  17 + echo "❌ Token获取失败"
  18 + exit 1
  19 +fi
  20 +
  21 +echo "✅ Token获取成功"
  22 +echo ""
  23 +
  24 +# 步骤2: 调用退款明细列表接口(2025年11月数据)
  25 +echo "步骤2: 调用退款明细列表接口(2025年11月数据)..."
  26 +echo "接口: POST /api/Extend/LqHytkHytk/refund-detail-list"
  27 +
  28 +RESPONSE=$(curl -s -X POST "http://localhost:2011/api/Extend/LqHytkHytk/refund-detail-list" \
  29 + -H "Authorization: Bearer $TOKEN" \
  30 + -H "Content-Type: application/json" \
  31 + -d '{
  32 + "currentPage": 1,
  33 + "pageSize": 5,
  34 + "startTime": "2025-11-01T00:00:00",
  35 + "endTime": "2025-11-30T23:59:59"
  36 + }')
  37 +
  38 +echo "$RESPONSE" | python3 -c "
  39 +import sys, json
  40 +try:
  41 + data = json.load(sys.stdin)
  42 + print('状态码:', data.get('code'))
  43 + print('消息:', data.get('msg'))
  44 + items = data.get('data', {}).get('list', [])
  45 + print('返回数据条数:', len(items))
  46 + if items:
  47 + print('\\n前3条数据详情:')
  48 + for i, item in enumerate(items[:3], 1):
  49 + print(f'\\n第{i}条:')
  50 + print(f' 门店名称: {item.get(\"storeName\", \"N/A\")}')
  51 + print(f' 会员名称: {item.get(\"memberName\", \"N/A\")}')
  52 + print(f' 品项名称: {item.get(\"itemName\", \"N/A\")}')
  53 + print(f' 健康师姓名: {item.get(\"healthCoachName\", \"N/A\")}')
  54 + print(f' 健康师业绩: {item.get(\"healthCoachPerformance\", \"N/A\")}')
  55 + print(f' 实际退款金额: {item.get(\"actualRefundAmount\", \"N/A\")}')
  56 +except Exception as e:
  57 + print('解析错误:', str(e))
  58 + print('原始响应:')
  59 + print(sys.stdin.read())
  60 +" 2>/dev/null
  61 +
  62 +echo ""
  63 +echo "=== 测试完成 ==="
  64 +