Commit a510c633fc1bab44bd18eaeacd2fe712316d3c0e
Merge branch 'master' of http://39.98.150.180/antissoft/lvqianmeiye_ERP
Showing
4 changed files
with
143 additions
and
53 deletions
antis-ncc-admin/src/views/extend/storeDashboard/index.vue
| @@ -92,18 +92,9 @@ | @@ -92,18 +92,9 @@ | ||
| 92 | </el-col> | 92 | </el-col> |
| 93 | </el-row> | 93 | </el-row> |
| 94 | 94 | ||
| 95 | - <!-- 第二行:每日运营数据趋势 + 门店综合能力雷达图 --> | 95 | + <!-- 第二行:门店综合能力雷达图 --> |
| 96 | <el-row :gutter="16" class="chart-row"> | 96 | <el-row :gutter="16" class="chart-row"> |
| 97 | - <el-col :span="16"> | ||
| 98 | - <el-card class="chart-card" shadow="hover"> | ||
| 99 | - <div slot="header" class="card-header"> | ||
| 100 | - <i class="el-icon-date"></i> | ||
| 101 | - <span>每日运营数据趋势</span> | ||
| 102 | - </div> | ||
| 103 | - <div ref="dailyChart" class="chart-container"></div> | ||
| 104 | - </el-card> | ||
| 105 | - </el-col> | ||
| 106 | - <el-col :span="8"> | 97 | + <el-col :span="24"> |
| 107 | <el-card class="chart-card" shadow="hover"> | 98 | <el-card class="chart-card" shadow="hover"> |
| 108 | <div slot="header" class="card-header"> | 99 | <div slot="header" class="card-header"> |
| 109 | <i class="el-icon-aim"></i> | 100 | <i class="el-icon-aim"></i> |
| @@ -182,7 +173,8 @@ | @@ -182,7 +173,8 @@ | ||
| 182 | <el-table :data="topBillingItems" size="small" border stripe> | 173 | <el-table :data="topBillingItems" size="small" border stripe> |
| 183 | <el-table-column type="index" label="排名" width="60" align="center"> | 174 | <el-table-column type="index" label="排名" width="60" align="center"> |
| 184 | <template slot-scope="scope"> | 175 | <template slot-scope="scope"> |
| 185 | - <el-tag v-if="scope.$index < 3" :type="['danger', 'warning', 'success'][scope.$index]" size="mini"> | 176 | + <el-tag v-if="scope.$index < 3" |
| 177 | + :type="['danger', 'warning', 'success'][scope.$index]" size="mini"> | ||
| 186 | {{ scope.$index + 1 }} | 178 | {{ scope.$index + 1 }} |
| 187 | </el-tag> | 179 | </el-tag> |
| 188 | <span v-else>{{ scope.$index + 1 }}</span> | 180 | <span v-else>{{ scope.$index + 1 }}</span> |
| @@ -191,13 +183,15 @@ | @@ -191,13 +183,15 @@ | ||
| 191 | <el-table-column prop="itemName" label="品项名称" min-width="180" /> | 183 | <el-table-column prop="itemName" label="品项名称" min-width="180" /> |
| 192 | <el-table-column prop="billingAmount" label="开单金额" width="140" align="right"> | 184 | <el-table-column prop="billingAmount" label="开单金额" width="140" align="right"> |
| 193 | <template slot-scope="scope"> | 185 | <template slot-scope="scope"> |
| 194 | - <span style="font-weight: 600; color: #67C23A;">¥{{ formatMoney(scope.row.billingAmount) }}</span> | 186 | + <span style="font-weight: 600; color: #67C23A;">¥{{ |
| 187 | + formatMoney(scope.row.billingAmount) }}</span> | ||
| 195 | </template> | 188 | </template> |
| 196 | </el-table-column> | 189 | </el-table-column> |
| 197 | <el-table-column prop="billingCount" label="开单次数" width="100" align="center" /> | 190 | <el-table-column prop="billingCount" label="开单次数" width="100" align="center" /> |
| 198 | <el-table-column prop="category" label="分类" width="80" align="center"> | 191 | <el-table-column prop="category" label="分类" width="80" align="center"> |
| 199 | <template slot-scope="scope"> | 192 | <template slot-scope="scope"> |
| 200 | - <el-tag size="mini" :type="getCategoryType(scope.row.category)">{{ scope.row.category }}</el-tag> | 193 | + <el-tag size="mini" :type="getCategoryType(scope.row.category)">{{ |
| 194 | + scope.row.category }}</el-tag> | ||
| 201 | </template> | 195 | </template> |
| 202 | </el-table-column> | 196 | </el-table-column> |
| 203 | </el-table> | 197 | </el-table> |
| @@ -217,13 +211,16 @@ | @@ -217,13 +211,16 @@ | ||
| 217 | <el-table-column type="index" label="排名" width="60" align="center" /> | 211 | <el-table-column type="index" label="排名" width="60" align="center" /> |
| 218 | <el-table-column prop="name" label="健康师姓名" min-width="120" /> | 212 | <el-table-column prop="name" label="健康师姓名" min-width="120" /> |
| 219 | <el-table-column prop="billingPerformance" label="开单业绩" width="120" align="right"> | 213 | <el-table-column prop="billingPerformance" label="开单业绩" width="120" align="right"> |
| 220 | - <template slot-scope="scope">¥{{ formatMoney(scope.row.billingPerformance) }}</template> | 214 | + <template slot-scope="scope">¥{{ formatMoney(scope.row.billingPerformance) |
| 215 | + }}</template> | ||
| 221 | </el-table-column> | 216 | </el-table-column> |
| 222 | <el-table-column prop="consumePerformance" label="消耗业绩" width="120" align="right"> | 217 | <el-table-column prop="consumePerformance" label="消耗业绩" width="120" align="right"> |
| 223 | - <template slot-scope="scope">¥{{ formatMoney(scope.row.consumePerformance) }}</template> | 218 | + <template slot-scope="scope">¥{{ formatMoney(scope.row.consumePerformance) |
| 219 | + }}</template> | ||
| 224 | </el-table-column> | 220 | </el-table-column> |
| 225 | <el-table-column prop="totalPerformance" label="总业绩" width="120" align="right"> | 221 | <el-table-column prop="totalPerformance" label="总业绩" width="120" align="right"> |
| 226 | - <template slot-scope="scope">¥{{ formatMoney(scope.row.totalPerformance) }}</template> | 222 | + <template slot-scope="scope">¥{{ formatMoney(scope.row.totalPerformance) |
| 223 | + }}</template> | ||
| 227 | </el-table-column> | 224 | </el-table-column> |
| 228 | </el-table> | 225 | </el-table> |
| 229 | </el-card> | 226 | </el-card> |
| @@ -239,7 +236,8 @@ | @@ -239,7 +236,8 @@ | ||
| 239 | <el-table-column prop="itemName" label="品项名称" min-width="150" /> | 236 | <el-table-column prop="itemName" label="品项名称" min-width="150" /> |
| 240 | <el-table-column prop="consumeAmount" label="消耗金额" width="120" align="right"> | 237 | <el-table-column prop="consumeAmount" label="消耗金额" width="120" align="right"> |
| 241 | <template slot-scope="scope"> | 238 | <template slot-scope="scope"> |
| 242 | - <span style="font-weight: 600; color: #409EFF;">¥{{ formatMoney(scope.row.consumeAmount) }}</span> | 239 | + <span style="font-weight: 600; color: #409EFF;">¥{{ |
| 240 | + formatMoney(scope.row.consumeAmount) }}</span> | ||
| 243 | </template> | 241 | </template> |
| 244 | </el-table-column> | 242 | </el-table-column> |
| 245 | <el-table-column prop="category" label="分类" width="80" /> | 243 | <el-table-column prop="category" label="分类" width="80" /> |
| @@ -340,7 +338,8 @@ | @@ -340,7 +338,8 @@ | ||
| 340 | <span class="rank-number">{{ comparison.performanceRanking }}</span> | 338 | <span class="rank-number">{{ comparison.performanceRanking }}</span> |
| 341 | <span class="rank-total">/ {{ comparison.totalStoreCount }}</span> | 339 | <span class="rank-total">/ {{ comparison.totalStoreCount }}</span> |
| 342 | </div> | 340 | </div> |
| 343 | - <div class="ranking-badge" :class="getRankingClass(comparison.performanceRanking, comparison.totalStoreCount)"> | 341 | + <div class="ranking-badge" |
| 342 | + :class="getRankingClass(comparison.performanceRanking, comparison.totalStoreCount)"> | ||
| 344 | {{ getRankingText(comparison.performanceRanking, comparison.totalStoreCount) }} | 343 | {{ getRankingText(comparison.performanceRanking, comparison.totalStoreCount) }} |
| 345 | </div> | 344 | </div> |
| 346 | </div> | 345 | </div> |
| @@ -410,7 +409,8 @@ | @@ -410,7 +409,8 @@ | ||
| 410 | <span class="progress-label">{{ metric.label }}</span> | 409 | <span class="progress-label">{{ metric.label }}</span> |
| 411 | <span class="progress-value">{{ metric.value }}%</span> | 410 | <span class="progress-value">{{ metric.value }}%</span> |
| 412 | </div> | 411 | </div> |
| 413 | - <el-progress :percentage="metric.value" :color="metric.color" :stroke-width="8"></el-progress> | 412 | + <el-progress :percentage="metric.value" :color="metric.color" |
| 413 | + :stroke-width="8"></el-progress> | ||
| 414 | </div> | 414 | </div> |
| 415 | </div> | 415 | </div> |
| 416 | </el-card> | 416 | </el-card> |
| @@ -517,7 +517,6 @@ export default { | @@ -517,7 +517,6 @@ export default { | ||
| 517 | ], | 517 | ], |
| 518 | trendChart: null, | 518 | trendChart: null, |
| 519 | categoryChart: null, | 519 | categoryChart: null, |
| 520 | - dailyChart: null, | ||
| 521 | compareChart: null, | 520 | compareChart: null, |
| 522 | stackedChart: null, | 521 | stackedChart: null, |
| 523 | funnelChart: null, | 522 | funnelChart: null, |
| @@ -561,7 +560,6 @@ export default { | @@ -561,7 +560,6 @@ export default { | ||
| 561 | beforeDestroy() { | 560 | beforeDestroy() { |
| 562 | if (this.trendChart) this.trendChart.dispose() | 561 | if (this.trendChart) this.trendChart.dispose() |
| 563 | if (this.categoryChart) this.categoryChart.dispose() | 562 | if (this.categoryChart) this.categoryChart.dispose() |
| 564 | - if (this.dailyChart) this.dailyChart.dispose() | ||
| 565 | if (this.compareChart) this.compareChart.dispose() | 563 | if (this.compareChart) this.compareChart.dispose() |
| 566 | if (this.stackedChart) this.stackedChart.dispose() | 564 | if (this.stackedChart) this.stackedChart.dispose() |
| 567 | if (this.funnelChart) this.funnelChart.dispose() | 565 | if (this.funnelChart) this.funnelChart.dispose() |
| @@ -577,7 +575,6 @@ export default { | @@ -577,7 +575,6 @@ export default { | ||
| 577 | this.$nextTick(() => { | 575 | this.$nextTick(() => { |
| 578 | this.renderTrendChart() | 576 | this.renderTrendChart() |
| 579 | this.renderCategoryChart() | 577 | this.renderCategoryChart() |
| 580 | - this.renderDailyChart() | ||
| 581 | this.renderCompareChart() | 578 | this.renderCompareChart() |
| 582 | this.renderStackedChart() | 579 | this.renderStackedChart() |
| 583 | this.renderFunnelChart() | 580 | this.renderFunnelChart() |
| @@ -630,28 +627,6 @@ export default { | @@ -630,28 +627,6 @@ export default { | ||
| 630 | } | 627 | } |
| 631 | this.categoryChart.setOption(option) | 628 | this.categoryChart.setOption(option) |
| 632 | }, | 629 | }, |
| 633 | - renderDailyChart() { | ||
| 634 | - if (!this.$refs.dailyChart) return | ||
| 635 | - this.dailyChart = echarts.init(this.$refs.dailyChart) | ||
| 636 | - const option = { | ||
| 637 | - tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } }, | ||
| 638 | - legend: { data: ['开单业绩', '消耗业绩', '人头数', '人次', '项目数'], top: 10 }, | ||
| 639 | - grid: { left: '60px', right: '80px', top: '50px', bottom: '60px', containLabel: false }, | ||
| 640 | - xAxis: { type: 'category', data: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30'], axisLabel: { rotate: 45, interval: 2, fontSize: 11 } }, | ||
| 641 | - yAxis: [ | ||
| 642 | - { type: 'value', name: '业绩', position: 'left', axisLabel: { formatter: value => value >= 10000 ? '¥' + (value / 10000).toFixed(1) + '万' : '¥' + value }, splitLine: { lineStyle: { type: 'dashed', color: '#E4E7ED' } } }, | ||
| 643 | - { type: 'value', name: '数量', position: 'right', splitLine: { show: false } } | ||
| 644 | - ], | ||
| 645 | - series: [ | ||
| 646 | - { name: '开单业绩', type: 'bar', yAxisIndex: 0, data: [45680, 52890, 48960, 56890, 49860, 59860, 62890, 55860, 51860, 59860, 52890, 48960, 56890, 49860, 59860, 62890, 55860, 51860, 59860, 52890, 48960, 56890, 49860, 59860, 62890, 55860, 51860, 59860, 52890, 48960], itemStyle: { color: '#409EFF' }, barWidth: '30%' }, | ||
| 647 | - { name: '消耗业绩', type: 'bar', yAxisIndex: 0, data: [32890, 38960, 35280, 41250, 36580, 43280, 45680, 40250, 37580, 43280, 38960, 35280, 41250, 36580, 43280, 45680, 40250, 37580, 43280, 38960, 35280, 41250, 36580, 43280, 45680, 40250, 37580, 43280, 38960, 35280], itemStyle: { color: '#67C23A' }, barWidth: '30%' }, | ||
| 648 | - { name: '人头数', type: 'line', yAxisIndex: 1, data: [45, 52, 48, 56, 49, 58, 62, 55, 51, 59, 52, 48, 56, 49, 58, 62, 55, 51, 59, 52, 48, 56, 49, 58, 62, 55, 51, 59, 52, 48], itemStyle: { color: '#F56C6C' }, lineStyle: { width: 2 }, symbol: 'circle', symbolSize: 6 }, | ||
| 649 | - { name: '人次', type: 'line', yAxisIndex: 1, data: [128, 145, 132, 156, 138, 162, 178, 152, 142, 165, 145, 132, 156, 138, 162, 178, 152, 142, 165, 145, 132, 156, 138, 162, 178, 152, 142, 165, 145, 132], itemStyle: { color: '#E6A23C' }, lineStyle: { width: 2 }, symbol: 'circle', symbolSize: 6 }, | ||
| 650 | - { name: '项目数', type: 'line', yAxisIndex: 1, data: [256, 289, 268, 312, 278, 325, 356, 304, 284, 330, 289, 268, 312, 278, 325, 356, 304, 284, 330, 289, 268, 312, 278, 325, 356, 304, 284, 330, 289, 268], itemStyle: { color: '#909399' }, lineStyle: { width: 2 }, symbol: 'circle', symbolSize: 6 } | ||
| 651 | - ] | ||
| 652 | - } | ||
| 653 | - this.dailyChart.setOption(option) | ||
| 654 | - }, | ||
| 655 | renderCompareChart() { | 630 | renderCompareChart() { |
| 656 | if (!this.$refs.compareChart) return | 631 | if (!this.$refs.compareChart) return |
| 657 | this.compareChart = echarts.init(this.$refs.compareChart) | 632 | this.compareChart = echarts.init(this.$refs.compareChart) |
| @@ -864,7 +839,6 @@ export default { | @@ -864,7 +839,6 @@ export default { | ||
| 864 | handleResize() { | 839 | handleResize() { |
| 865 | if (this.trendChart) this.trendChart.resize() | 840 | if (this.trendChart) this.trendChart.resize() |
| 866 | if (this.categoryChart) this.categoryChart.resize() | 841 | if (this.categoryChart) this.categoryChart.resize() |
| 867 | - if (this.dailyChart) this.dailyChart.resize() | ||
| 868 | if (this.compareChart) this.compareChart.resize() | 842 | if (this.compareChart) this.compareChart.resize() |
| 869 | if (this.stackedChart) this.stackedChart.resize() | 843 | if (this.stackedChart) this.stackedChart.resize() |
| 870 | if (this.funnelChart) this.funnelChart.resize() | 844 | if (this.funnelChart) this.funnelChart.resize() |
| @@ -1150,6 +1124,7 @@ export default { | @@ -1150,6 +1124,7 @@ export default { | ||
| 1150 | grid-template-columns: 1fr 400px; | 1124 | grid-template-columns: 1fr 400px; |
| 1151 | gap: 20px; | 1125 | gap: 20px; |
| 1152 | margin-bottom: 20px; | 1126 | margin-bottom: 20px; |
| 1127 | + align-items: start; | ||
| 1153 | 1128 | ||
| 1154 | .content-left { | 1129 | .content-left { |
| 1155 | display: flex; | 1130 | display: flex; |
antis-ncc-admin/src/views/statisticsList/form21.vue
| @@ -270,6 +270,17 @@ | @@ -270,6 +270,17 @@ | ||
| 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"> | ||
| 274 | + <template slot-scope="scope"> | ||
| 275 | + <i class="el-icon-user-solid" style="margin-right: 4px; color: #F56C6C;"></i> | ||
| 276 | + <span>{{ scope.row.healthCoachName || '无' }}</span> | ||
| 277 | + </template> | ||
| 278 | + </el-table-column> | ||
| 279 | + <el-table-column prop="healthCoachPerformance" label="健康师业绩" min-width="130" sortable="custom"> | ||
| 280 | + <template slot-scope="scope"> | ||
| 281 | + <span class="amount-value">¥{{ formatMoney(scope.row.healthCoachPerformance) }}</span> | ||
| 282 | + </template> | ||
| 283 | + </el-table-column> | ||
| 273 | </NCC-table> | 284 | </NCC-table> |
| 274 | <pagination | 285 | <pagination |
| 275 | v-show="total > 0" | 286 | v-show="total > 0" |
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/RefundDetailListOutput.cs
| @@ -81,6 +81,21 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk | @@ -81,6 +81,21 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk | ||
| 81 | /// 品项分类 | 81 | /// 品项分类 |
| 82 | /// </summary> | 82 | /// </summary> |
| 83 | public string itemCategory { get; set; } | 83 | public string itemCategory { get; set; } |
| 84 | + | ||
| 85 | + /// <summary> | ||
| 86 | + /// 健康师账号 | ||
| 87 | + /// </summary> | ||
| 88 | + public string healthCoachId { get; set; } | ||
| 89 | + | ||
| 90 | + /// <summary> | ||
| 91 | + /// 健康师姓名 | ||
| 92 | + /// </summary> | ||
| 93 | + public string healthCoachName { get; set; } | ||
| 94 | + | ||
| 95 | + /// <summary> | ||
| 96 | + /// 健康师业绩 | ||
| 97 | + /// </summary> | ||
| 98 | + public decimal healthCoachPerformance { get; set; } | ||
| 84 | } | 99 | } |
| 85 | } | 100 | } |
| 86 | 101 |
netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
| @@ -27,6 +27,7 @@ using NCC.Extend.Entitys.lq_hytk_jksyj; | @@ -27,6 +27,7 @@ using NCC.Extend.Entitys.lq_hytk_jksyj; | ||
| 27 | using NCC.Extend.Entitys.lq_hytk_kjbsyj; | 27 | using NCC.Extend.Entitys.lq_hytk_kjbsyj; |
| 28 | using NCC.Extend.Entitys.lq_hytk_mx; | 28 | using NCC.Extend.Entitys.lq_hytk_mx; |
| 29 | using NCC.Extend.Entitys.lq_kd_pxmx; | 29 | using NCC.Extend.Entitys.lq_kd_pxmx; |
| 30 | +using NCC.Extend.Entitys.lq_kd_jksyj; | ||
| 30 | using NCC.Extend.Entitys.lq_xmzl; | 31 | using NCC.Extend.Entitys.lq_xmzl; |
| 31 | using NCC.Extend.Entitys.lq_khxx; | 32 | using NCC.Extend.Entitys.lq_khxx; |
| 32 | using NCC.Extend.Entitys.lq_mdxx; | 33 | using NCC.Extend.Entitys.lq_mdxx; |
| @@ -915,7 +916,43 @@ namespace NCC.Extend.LqHytkHytk | @@ -915,7 +916,43 @@ namespace NCC.Extend.LqHytkHytk | ||
| 915 | memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? ""); | 916 | memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? ""); |
| 916 | } | 917 | } |
| 917 | 918 | ||
| 918 | - // 5. 组装数据 | 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()) | ||
| 923 | + { | ||
| 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 }) | ||
| 928 | + .ToListAsync(); | ||
| 929 | + | ||
| 930 | + if (pxmxList.Any()) | ||
| 931 | + { | ||
| 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(); | ||
| 934 | + | ||
| 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(); | ||
| 940 | + | ||
| 941 | + // 建立开单品项明细ID到健康师信息的映射 | ||
| 942 | + foreach (var jksyj in jksyjList) | ||
| 943 | + { | ||
| 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 | + } | ||
| 951 | + } | ||
| 952 | + } | ||
| 953 | + } | ||
| 954 | + | ||
| 955 | + // 6. 组装数据 | ||
| 919 | var resultList = new List<RefundDetailListOutput>(); | 956 | var resultList = new List<RefundDetailListOutput>(); |
| 920 | foreach (var mx in mxList) | 957 | foreach (var mx in mxList) |
| 921 | { | 958 | { |
| @@ -936,6 +973,11 @@ namespace NCC.Extend.LqHytkHytk | @@ -936,6 +973,11 @@ namespace NCC.Extend.LqHytkHytk | ||
| 936 | var memberId = mx.MemberId ?? (refundInfo?.Hy); | 973 | var memberId = mx.MemberId ?? (refundInfo?.Hy); |
| 937 | var refundTime = mx.Tksj ?? refundInfo?.Tksj; | 974 | var refundTime = mx.Tksj ?? refundInfo?.Tksj; |
| 938 | 975 | ||
| 976 | + // 获取健康师信息 | ||
| 977 | + var healthCoachInfo = !string.IsNullOrEmpty(mx.BillingItemId) && healthCoachDict.ContainsKey(mx.BillingItemId) | ||
| 978 | + ? healthCoachDict[mx.BillingItemId] | ||
| 979 | + : (Id: "", Name: "", Performance: 0m); | ||
| 980 | + | ||
| 939 | resultList.Add(new RefundDetailListOutput | 981 | resultList.Add(new RefundDetailListOutput |
| 940 | { | 982 | { |
| 941 | storeId = refundInfo?.Md, | 983 | storeId = refundInfo?.Md, |
| @@ -952,11 +994,14 @@ namespace NCC.Extend.LqHytkHytk | @@ -952,11 +994,14 @@ namespace NCC.Extend.LqHytkHytk | ||
| 952 | performanceType = mx.PerformanceType, | 994 | performanceType = mx.PerformanceType, |
| 953 | beautyType = mx.BeautyType, | 995 | beautyType = mx.BeautyType, |
| 954 | sourceType = mx.SourceType, | 996 | sourceType = mx.SourceType, |
| 955 | - itemCategory = mx.ItemCategory | 997 | + itemCategory = mx.ItemCategory, |
| 998 | + healthCoachId = healthCoachInfo.Id, | ||
| 999 | + healthCoachName = healthCoachInfo.Name, | ||
| 1000 | + healthCoachPerformance = healthCoachInfo.Performance | ||
| 956 | }); | 1001 | }); |
| 957 | } | 1002 | } |
| 958 | 1003 | ||
| 959 | - // 6. 排序 | 1004 | + // 7. 排序 |
| 960 | var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx; | 1005 | var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx; |
| 961 | var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort; | 1006 | var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort; |
| 962 | 1007 | ||
| @@ -969,7 +1014,7 @@ namespace NCC.Extend.LqHytkHytk | @@ -969,7 +1014,7 @@ namespace NCC.Extend.LqHytkHytk | ||
| 969 | resultList = resultList.OrderBy(x => GetPropertyValue(x, sidx)).ToList(); | 1014 | resultList = resultList.OrderBy(x => GetPropertyValue(x, sidx)).ToList(); |
| 970 | } | 1015 | } |
| 971 | 1016 | ||
| 972 | - // 7. 分页 | 1017 | + // 8. 分页 |
| 973 | var total = resultList.Count; | 1018 | var total = resultList.Count; |
| 974 | var skip = (input.currentPage - 1) * input.pageSize; | 1019 | var skip = (input.currentPage - 1) * input.pageSize; |
| 975 | var pagedList = resultList.Skip(skip).Take(input.pageSize).ToList(); | 1020 | var pagedList = resultList.Skip(skip).Take(input.pageSize).ToList(); |
| @@ -1069,7 +1114,43 @@ namespace NCC.Extend.LqHytkHytk | @@ -1069,7 +1114,43 @@ namespace NCC.Extend.LqHytkHytk | ||
| 1069 | memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? ""); | 1114 | memberDict = members.ToDictionary(x => x.Id, x => x.Sjh ?? ""); |
| 1070 | } | 1115 | } |
| 1071 | 1116 | ||
| 1072 | - // 5. 组装数据 | 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()) | ||
| 1121 | + { | ||
| 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 }) | ||
| 1126 | + .ToListAsync(); | ||
| 1127 | + | ||
| 1128 | + if (pxmxList.Any()) | ||
| 1129 | + { | ||
| 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(); | ||
| 1132 | + | ||
| 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(); | ||
| 1138 | + | ||
| 1139 | + // 建立开单品项明细ID到健康师信息的映射 | ||
| 1140 | + foreach (var jksyj in jksyjList) | ||
| 1141 | + { | ||
| 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 | + } | ||
| 1149 | + } | ||
| 1150 | + } | ||
| 1151 | + } | ||
| 1152 | + | ||
| 1153 | + // 6. 组装数据 | ||
| 1073 | var resultList = new List<RefundDetailListOutput>(); | 1154 | var resultList = new List<RefundDetailListOutput>(); |
| 1074 | foreach (var mx in mxList) | 1155 | foreach (var mx in mxList) |
| 1075 | { | 1156 | { |
| @@ -1090,6 +1171,11 @@ namespace NCC.Extend.LqHytkHytk | @@ -1090,6 +1171,11 @@ namespace NCC.Extend.LqHytkHytk | ||
| 1090 | var memberId = mx.MemberId ?? (refundInfo?.Hy); | 1171 | var memberId = mx.MemberId ?? (refundInfo?.Hy); |
| 1091 | var refundTime = mx.Tksj ?? refundInfo?.Tksj; | 1172 | var refundTime = mx.Tksj ?? refundInfo?.Tksj; |
| 1092 | 1173 | ||
| 1174 | + // 获取健康师信息 | ||
| 1175 | + var healthCoachInfo = !string.IsNullOrEmpty(mx.BillingItemId) && healthCoachDict.ContainsKey(mx.BillingItemId) | ||
| 1176 | + ? healthCoachDict[mx.BillingItemId] | ||
| 1177 | + : (Id: "", Name: "", Performance: 0m); | ||
| 1178 | + | ||
| 1093 | resultList.Add(new RefundDetailListOutput | 1179 | resultList.Add(new RefundDetailListOutput |
| 1094 | { | 1180 | { |
| 1095 | storeId = refundInfo?.Md, | 1181 | storeId = refundInfo?.Md, |
| @@ -1106,11 +1192,14 @@ namespace NCC.Extend.LqHytkHytk | @@ -1106,11 +1192,14 @@ namespace NCC.Extend.LqHytkHytk | ||
| 1106 | performanceType = mx.PerformanceType, | 1192 | performanceType = mx.PerformanceType, |
| 1107 | beautyType = mx.BeautyType, | 1193 | beautyType = mx.BeautyType, |
| 1108 | sourceType = mx.SourceType, | 1194 | sourceType = mx.SourceType, |
| 1109 | - itemCategory = mx.ItemCategory | 1195 | + itemCategory = mx.ItemCategory, |
| 1196 | + healthCoachId = healthCoachInfo.Id, | ||
| 1197 | + healthCoachName = healthCoachInfo.Name, | ||
| 1198 | + healthCoachPerformance = healthCoachInfo.Performance | ||
| 1110 | }); | 1199 | }); |
| 1111 | } | 1200 | } |
| 1112 | 1201 | ||
| 1113 | - // 6. 排序 | 1202 | + // 7. 排序 |
| 1114 | var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx; | 1203 | var sidx = string.IsNullOrEmpty(input.sidx) ? "refundTime" : input.sidx; |
| 1115 | var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort; | 1204 | var sort = string.IsNullOrEmpty(input.sort) ? "desc" : input.sort; |
| 1116 | 1205 |