From 75c8f70997d81958e1c7d952916d15ce89f72806 Mon Sep 17 00:00:00 2001
From: “wangming” <“wangming@antissoft.com”>
Date: Fri, 26 Dec 2025 14:36:24 +0800
Subject: [PATCH] feat: 1. 拓客明细页面是否字段使用tag样式显示;2. 6个接口支持多门店筛选;3. 门店日报统计接口添加在职人数字段
---
antis-ncc-admin/.env.development | 4 ++--
antis-ncc-admin/src/components/kpi-drill/tk-analysis.vue | 10 +++++++++-
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/StoreDailyStatisticsOutput.cs | 5 +++++
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs | 8 +++++++-
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/HealthCoachStatisticsQueryInput.cs | 10 ++++++++--
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs | 8 +++++++-
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/MemberUpgradeStatisticsListQueryInput.cs | 5 +++++
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/LqTkjlbListOutput.cs | 5 +++++
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/ConsumeItemDetailListQueryInput.cs | 8 +++++++-
netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs | 4 ++++
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs | 34 ++++++++++++++++++++++++++++++----
netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs | 17 ++++++++++++++---
netcore/src/Modularity/Extend/NCC.Extend/LqReportService.cs | 13 +++++++------
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs | 27 +++++++++++++++++++++++++++
netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs | 13 ++++++++++++-
16 files changed, 209 insertions(+), 24 deletions(-)
diff --git a/antis-ncc-admin/.env.development b/antis-ncc-admin/.env.development
index 0eaf86c..6462393 100644
--- a/antis-ncc-admin/.env.development
+++ b/antis-ncc-admin/.env.development
@@ -1,9 +1,9 @@
# 开发
VUE_CLI_BABEL_TRANSPILE_MODULES = true
-VUE_APP_BASE_API = 'https://erp.lvqianmeiye.com'
+# VUE_APP_BASE_API = 'https://erp.lvqianmeiye.com'
# VUE_APP_BASE_API = 'http://erp_test.lvqianmeiye.com'
-# VUE_APP_BASE_API = 'http://localhost:2011'
+VUE_APP_BASE_API = 'http://localhost:2011'
# VUE_APP_BASE_API = 'http://localhost:2011'
VUE_APP_IMG_API = ''
VUE_APP_BASE_WSS = 'ws://192.168.110.45:2011/websocket'
diff --git a/antis-ncc-admin/src/components/kpi-drill/tk-analysis.vue b/antis-ncc-admin/src/components/kpi-drill/tk-analysis.vue
index 89dc234..b96ad97 100644
--- a/antis-ncc-admin/src/components/kpi-drill/tk-analysis.vue
+++ b/antis-ncc-admin/src/components/kpi-drill/tk-analysis.vue
@@ -43,7 +43,15 @@
- {{ scope.row[col.prop] || '—' }}
+
+
+ {{ scope.row[col.prop] || '否' }}
+
+
+ {{ scope.row[col.prop] || '—' }}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/StoreDailyStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/StoreDailyStatisticsOutput.cs
index 4868c35..fc7e684 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/StoreDailyStatisticsOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/StoreDailyStatisticsOutput.cs
@@ -19,6 +19,11 @@ namespace NCC.Extend.Entitys.Dto.LqDailyReport
public string StoreName { get; set; }
///
+ /// 在职人数
+ ///
+ public int EmployeeCount { get; set; }
+
+ ///
/// 人头数(去重后的消费会员数)
///
public int HeadCount { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs
index f9955be..c4334a8 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListQueryInput.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using NCC.Common.Filter;
namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
@@ -78,9 +79,14 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
public string SourceType { get; set; }
///
- /// 门店ID
+ /// 门店ID(单门店,兼容旧版本)
///
public string StoreId { get; set; }
+
+ ///
+ /// 门店ID列表(多门店筛选)
+ ///
+ public List StoreIds { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/HealthCoachStatisticsQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/HealthCoachStatisticsQueryInput.cs
index 4dc317d..c1022bd 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/HealthCoachStatisticsQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/HealthCoachStatisticsQueryInput.cs
@@ -1,5 +1,6 @@
-using NCC.Common.Filter;
using System;
+using System.Collections.Generic;
+using NCC.Common.Filter;
namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
{
@@ -24,11 +25,16 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
public string DepartmentId { get; set; }
///
- /// 门店ID
+ /// 门店ID(单门店,兼容旧版本)
///
public string StoreId { get; set; }
///
+ /// 门店ID列表(多门店筛选)
+ ///
+ public List StoreIds { get; set; }
+
+ ///
/// 健康师姓名
///
public string EmployeeName { get; set; }
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs
index 2fa2ac7..13af103 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/MemberItemInfoQueryInput.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using NCC.Common.Filter;
namespace NCC.Extend.Entitys.Dto.LqKhxx
@@ -19,11 +20,16 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx
public string BelongStoreId { get; set; }
///
- /// 开单门店ID
+ /// 开单门店ID(单门店,兼容旧版本)
///
public string BillingStoreId { get; set; }
///
+ /// 开单门店ID列表(多门店筛选)
+ ///
+ public List BillingStoreIds { get; set; }
+
+ ///
/// 会员类型
///
public int MemberType { get; set; } = -1;
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/MemberUpgradeStatisticsListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/MemberUpgradeStatisticsListQueryInput.cs
index 5e4f55b..e730eec 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/MemberUpgradeStatisticsListQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/MemberUpgradeStatisticsListQueryInput.cs
@@ -37,6 +37,11 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
/// 是否升生美(true-是,false-否,null-不筛选)
///
public bool? HasUpgradeLifeBeauty { get; set; }
+
+ ///
+ /// 门店ID列表(多门店筛选)
+ ///
+ public List StoreIds { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/LqTkjlbListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/LqTkjlbListOutput.cs
index be0f45b..1d51b9a 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/LqTkjlbListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/LqTkjlbListOutput.cs
@@ -117,5 +117,10 @@ namespace NCC.Extend.Entitys.Dto.LqTkjlb
/// 是否开卡(是/否)
///
public string hasBilling { get; set; }
+
+ ///
+ /// 会员ID(内部使用,不返回给前端)
+ ///
+ public string memberId { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/ConsumeItemDetailListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/ConsumeItemDetailListQueryInput.cs
index 43db838..818a9ac 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/ConsumeItemDetailListQueryInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhPxmx/ConsumeItemDetailListQueryInput.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using NCC.Common.Filter;
namespace NCC.Extend.Entitys.Dto.LqXhPxmx
@@ -73,9 +74,14 @@ namespace NCC.Extend.Entitys.Dto.LqXhPxmx
public string SourceType { get; set; }
///
- /// 门店ID
+ /// 门店ID(单门店,兼容旧版本)
///
public string StoreId { get; set; }
+
+ ///
+ /// 门店ID列表(多门店筛选)
+ ///
+ public List StoreIds { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
index dd3945d..fc116f1 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
@@ -99,6 +99,7 @@ namespace NCC.Extend
/// 返回说明:
/// - StoreId: 门店ID
/// - StoreName: 门店名称
+ /// - EmployeeCount: 在职人数
/// - HeadCount: 人头数(去重后的消费会员数)
/// - PersonCount: 人次(日度去重客户数,同一天同一客户只算一次)
/// - ProjectCount: 项目数(消耗的项目总数,从品项明细表统计)
@@ -134,6 +135,8 @@ namespace NCC.Extend
SELECT
consume.Md as StoreId,
MAX(store.dm) as StoreName,
+ -- 在职人数(从门店表获取)
+ MAX(COALESCE(store.zzrs, 0)) as EmployeeCount,
-- 人头数(去重后的消费会员数)
COALESCE(COUNT(DISTINCT consume.Hy), 0) as HeadCount,
-- 人次(日度去重客户数)
@@ -185,6 +188,7 @@ namespace NCC.Extend
{
StoreId = item.StoreId,
StoreName = item.StoreName,
+ EmployeeCount = Convert.ToInt32(item.EmployeeCount ?? 0),
HeadCount = Convert.ToInt32(item.HeadCount),
PersonCount = Convert.ToInt32(item.PersonCount),
ProjectCount = Convert.ToInt32(item.ProjectCount),
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
index 83e31e8..a8e9a82 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -3635,10 +3635,25 @@ namespace NCC.Extend.LqKdKdjlb
parameters.Add(new SugarParameter("@departmentId", input.DepartmentId));
}
- if (!string.IsNullOrEmpty(input.StoreId))
+ // 处理多门店筛选:优先使用StoreIds,如果没有则使用StoreId
+ var storeIds = new List();
+ if (input.StoreIds != null && input.StoreIds.Any())
{
- conditions.Add("u.F_MDID = @storeId");
- parameters.Add(new SugarParameter("@storeId", input.StoreId));
+ storeIds = input.StoreIds.Where(x => !string.IsNullOrEmpty(x)).ToList();
+ }
+ else if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ storeIds = new List { input.StoreId };
+ }
+
+ if (storeIds.Any())
+ {
+ var storeIdParams = string.Join(",", storeIds.Select((_, i) => $"@storeId{i}"));
+ conditions.Add($"u.F_MDID IN ({storeIdParams})");
+ for (int i = 0; i < storeIds.Count; i++)
+ {
+ parameters.Add(new SugarParameter($"@storeId{i}", storeIds[i]));
+ }
}
if (!string.IsNullOrEmpty(input.EmployeeName))
@@ -3839,9 +3854,20 @@ namespace NCC.Extend.LqKdKdjlb
.WhereIF(!string.IsNullOrEmpty(input.ItemType), pxmx => pxmx.ItemCategory == input.ItemType);
// 2. 通过 EXISTS 子查询筛选关联字段(在分页前筛选,确保分页准确)
+ // 处理多门店筛选:优先使用StoreIds,如果没有则使用StoreId
+ var filterStoreIds = new List();
+ if (input.StoreIds != null && input.StoreIds.Any())
+ {
+ filterStoreIds = input.StoreIds.Where(x => !string.IsNullOrEmpty(x)).ToList();
+ }
+ else if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ filterStoreIds = new List { input.StoreId };
+ }
+
baseQuery = baseQuery.WhereIF(!string.IsNullOrEmpty(input.MemberName), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Khmc != null && x.Khmc.Contains(input.MemberName)).Any())
.WhereIF(!string.IsNullOrEmpty(input.MemberPhone), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Sjh == input.MemberPhone).Any())
- .WhereIF(!string.IsNullOrEmpty(input.StoreId), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.Glkdbh && x.Djmd == input.StoreId).Any());
+ .WhereIF(filterStoreIds.Any(), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.Glkdbh && filterStoreIds.Contains(x.Djmd)).Any());
// 3. 先分页查询主表数据(查询实体类,提高性能)
var pagedData = await baseQuery.OrderBy(sidx + " " + sort).ToPagedListAsync(input.currentPage, input.pageSize);
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
index 9fba079..6fbeb1a 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
@@ -1145,7 +1145,18 @@ namespace NCC.Extend.LqKhxx
}
// 如果指定了开单门店、开单人、品项ID等条件,需要通过开单表进行筛选
- if (!string.IsNullOrEmpty(input.BillingStoreId) ||
+ // 处理多门店筛选:优先使用BillingStoreIds,如果没有则使用BillingStoreId
+ var billingStoreIds = new List();
+ if (input.BillingStoreIds != null && input.BillingStoreIds.Any())
+ {
+ billingStoreIds = input.BillingStoreIds.Where(x => !string.IsNullOrEmpty(x)).ToList();
+ }
+ else if (!string.IsNullOrEmpty(input.BillingStoreId))
+ {
+ billingStoreIds = new List { input.BillingStoreId };
+ }
+
+ if (billingStoreIds.Any() ||
!string.IsNullOrEmpty(input.BillingUserId) ||
!string.IsNullOrEmpty(input.PurchaseItemId) ||
!string.IsNullOrEmpty(input.GiftItemId) ||
@@ -1155,9 +1166,9 @@ namespace NCC.Extend.LqKhxx
var billingQuery = _db.Queryable()
.Where(x => x.IsEffective == StatusEnum.有效.GetHashCode());
- if (!string.IsNullOrEmpty(input.BillingStoreId))
+ if (billingStoreIds.Any())
{
- billingQuery = billingQuery.Where(x => x.Djmd == input.BillingStoreId);
+ billingQuery = billingQuery.Where(x => billingStoreIds.Contains(x.Djmd));
}
if (!string.IsNullOrEmpty(input.BillingUserId))
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqReportService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqReportService.cs
index 7b0bdad..e5e9391 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqReportService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqReportService.cs
@@ -503,7 +503,7 @@ namespace NCC.Extend
/// - TopAmountMemberName: 开单金额最高会员姓名
/// - TopAmountValue: 该会员整月实付金额
/// - TopTimesMemberName: 开单次数最多会员姓名
- /// - TopTimesCount: 该会员整月开单次数
+ /// - TopTimesCount: 该会员整月开单次数(按天去重,同一天多次开单只算一次)
/// - DebtTotal: 整月欠款总额(sfyj+ck金额以外的qk累加)
/// - TopDebtMemberName: 欠款最多会员姓名
/// - TopDebtValue: 欠款最多会员的欠款金额
@@ -598,15 +598,16 @@ namespace NCC.Extend
.OrderBy(x => x.Date)
.ToList();
- // 3. 会员极值:按会员聚合金额和次数
+ // 3. 会员极值:按会员聚合金额和次数(开单次数按天去重)
var memberAgg = rawList
- .Where(x => !string.IsNullOrEmpty(x.MemberId))
- .GroupBy(x => x.MemberId)
+ .Where(x => !string.IsNullOrEmpty(x.MemberId) && x.BillingDate.HasValue)
+ .GroupBy(x => new { x.MemberId, Date = x.BillingDate.Value.Date })
+ .GroupBy(g => g.Key.MemberId)
.Select(g => new
{
MemberId = g.Key,
- Amount = g.Sum(x => x.Amount),
- Times = g.Count()
+ Amount = g.SelectMany(dayGroup => dayGroup).Sum(x => x.Amount),
+ Times = g.Count() // 按天去重后的开单天数
})
.ToList();
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
index 4fc9207..852f32f 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
@@ -4898,6 +4898,7 @@ namespace NCC.Extend.LqStatistics
) xh_stats ON xh_stats.member_id = tk.F_MemberId
-- 开单统计子查询(只统计通过预约产生的开单,包含金额和品项)
-- 通过会员ID关联:线索池 -> 邀约 -> 预约 -> 开单(通过预约ID,且会员ID匹配)
+ -- 注意:剔除品项ID是61且金额是0的记录
LEFT JOIN (
SELECT
tk_inner.F_MemberId as member_id,
@@ -4908,7 +4909,14 @@ namespace NCC.Extend.LqStatistics
INNER JOIN lq_yaoyjl yaoy ON yaoy.yykh = tk_inner.F_MemberId
INNER JOIN lq_yyjl yy ON yy.F_InviteId = yaoy.F_Id AND yy.gk = tk_inner.F_MemberId
INNER JOIN lq_kd_kdjlb kd ON kd.F_AppointmentId = yy.F_Id AND kd.kdhy = tk_inner.F_MemberId AND kd.F_IsEffective = 1
+ INNER JOIN (
+ SELECT DISTINCT glkdbh
+ FROM lq_kd_pxmx
+ WHERE F_IsEffective = 1
+ AND NOT (px = '61' AND (COALESCE(F_ActualPrice, 0) = 0 AND COALESCE(F_TotalPrice, 0) = 0))
+ ) valid_px ON valid_px.glkdbh = kd.F_Id
LEFT JOIN lq_kd_pxmx kdpx ON kdpx.glkdbh = kd.F_Id AND kdpx.F_IsEffective = 1
+ AND NOT (kdpx.px = '61' AND (COALESCE(kdpx.F_ActualPrice, 0) = 0 AND COALESCE(kdpx.F_TotalPrice, 0) = 0))
GROUP BY tk_inner.F_MemberId
) kd_stats ON kd_stats.member_id = tk.F_MemberId
-- 实际预约记录数统计(不管是否通过邀约产生)
@@ -5229,6 +5237,7 @@ namespace NCC.Extend.LqStatistics
) xh_stats ON xh_stats.member_id = tk.F_MemberId
-- 开单统计子查询(只统计通过预约产生的开单,包含金额和品项)
-- 通过会员ID关联:线索池 -> 邀约 -> 预约 -> 开单(通过预约ID,且会员ID匹配)
+ -- 注意:剔除品项ID是61且金额是0的记录
LEFT JOIN (
SELECT
tk_inner.F_MemberId as member_id,
@@ -5239,7 +5248,14 @@ namespace NCC.Extend.LqStatistics
INNER JOIN lq_yaoyjl yaoy ON yaoy.yykh = tk_inner.F_MemberId
INNER JOIN lq_yyjl yy ON yy.F_InviteId = yaoy.F_Id AND yy.gk = tk_inner.F_MemberId
INNER JOIN lq_kd_kdjlb kd ON kd.F_AppointmentId = yy.F_Id AND kd.kdhy = tk_inner.F_MemberId AND kd.F_IsEffective = 1
+ INNER JOIN (
+ SELECT DISTINCT glkdbh
+ FROM lq_kd_pxmx
+ WHERE F_IsEffective = 1
+ AND NOT (px = '61' AND (COALESCE(F_ActualPrice, 0) = 0 AND COALESCE(F_TotalPrice, 0) = 0))
+ ) valid_px ON valid_px.glkdbh = kd.F_Id
LEFT JOIN lq_kd_pxmx kdpx ON kdpx.glkdbh = kd.F_Id AND kdpx.F_IsEffective = 1
+ AND NOT (kdpx.px = '61' AND (COALESCE(kdpx.F_ActualPrice, 0) = 0 AND COALESCE(kdpx.F_TotalPrice, 0) = 0))
GROUP BY tk_inner.F_MemberId
) kd_stats ON kd_stats.member_id = tk.F_MemberId
-- 实际预约记录数统计(不管是否通过邀约产生)
@@ -5703,6 +5719,17 @@ namespace NCC.Extend.LqStatistics
}
}
+ // 添加多门店筛选
+ if (input.StoreIds != null && input.StoreIds.Any())
+ {
+ var storeIdParams = string.Join(",", input.StoreIds.Select((_, i) => $"@StoreId{i}"));
+ whereConditions.Add($"kd.Djmd IN ({storeIdParams})");
+ for (int i = 0; i < input.StoreIds.Count; i++)
+ {
+ parameters.Add(new SugarParameter($"@StoreId{i}", input.StoreIds[i]));
+ }
+ }
+
var whereClause = whereConditions.Any() ? "AND " + string.Join(" AND ", whereConditions) : "";
// 构建HAVING条件(用于筛选升单条件)
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
index 4b7e68b..b1a80b6 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
@@ -147,12 +147,70 @@ namespace NCC.Extend.LqTkjlb
hasAppointment = SqlFunc.Subqueryable().Where(y => y.Gk == it.MemberId).Any() ? "是" : "否",
// 是否消耗:通过会员ID关联耗卡表(hy字段存储的是会员ID)
hasConsume = SqlFunc.Subqueryable().Where(x => x.Hy == it.MemberId).Any() ? "是" : "否",
- // 是否开卡:通过会员ID关联开单表(kdhy字段存储的是会员ID)
- hasBilling = SqlFunc.Subqueryable().Where(k => k.Kdhy == it.MemberId).Any() ? "是" : "否"
+ // 是否开卡:通过会员ID关联开单表(kdhy字段存储的是会员ID),剔除品项ID是61(女神卡)且金额是0的记录
+ // 先设置为否,后面在内存中处理
+ hasBilling = "否"
})
.MergeTable()
.OrderBy(sidx + " " + input.sort)
.ToPagedListAsync(input.currentPage, input.pageSize);
+
+ // 批量查询有有效开单的会员ID(剔除品项ID是61且金额是0的记录)
+ // 先查询所有拓客记录的会员ID
+ var tkIds = data.list?.Select(x => x.id).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList() ?? new List();
+ var memberIdDict = new Dictionary(); // tkId -> MemberId
+
+ if (tkIds.Any())
+ {
+ // 查询拓客记录的会员ID
+ var tkMembers = await _db.Queryable()
+ .Where(x => tkIds.Contains(x.Id))
+ .Select(x => new { x.Id, x.MemberId })
+ .ToListAsync();
+ memberIdDict = tkMembers?.Where(x => !string.IsNullOrEmpty(x.MemberId))
+ .ToDictionary(x => x.Id, x => x.MemberId) ?? new Dictionary();
+ }
+
+ var memberIds = memberIdDict.Values.Distinct().ToList();
+ var hasBillingMemberIds = new HashSet();
+
+ if (memberIds.Any())
+ {
+ var sql = $@"
+ SELECT DISTINCT kd.kdhy as MemberId
+ FROM lq_kd_kdjlb kd
+ INNER JOIN (
+ SELECT DISTINCT glkdbh
+ FROM lq_kd_pxmx
+ WHERE F_IsEffective = 1
+ AND NOT (px = '61' AND (COALESCE(F_ActualPrice, 0) = 0 AND COALESCE(F_TotalPrice, 0) = 0))
+ ) valid_px ON valid_px.glkdbh = kd.F_Id
+ WHERE kd.F_IsEffective = 1
+ AND kd.kdhy IN ('{string.Join("','", memberIds)}')";
+ var billingMembers = await _db.Ado.SqlQueryAsync(sql);
+ if (billingMembers != null)
+ {
+ var memberIdList = billingMembers.Select(x => x.MemberId?.ToString()).Where(x => !string.IsNullOrEmpty(x)).Cast().ToList();
+ hasBillingMemberIds = new HashSet(memberIdList);
+ }
+ }
+
+ // 更新hasBilling字段
+ if (data.list != null)
+ {
+ foreach (var item in data.list)
+ {
+ if (memberIdDict.TryGetValue(item.id, out var memberId) && !string.IsNullOrEmpty(memberId))
+ {
+ item.hasBilling = hasBillingMemberIds.Contains(memberId) ? "是" : "否";
+ }
+ else
+ {
+ item.hasBilling = "否";
+ }
+ }
+ }
+
return PageResult.SqlSugarPageResult(data);
}
#endregion
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
index 8554c6d..5c86c91 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
@@ -2036,9 +2036,20 @@ namespace NCC.Extend.LqXhHyhk
.WhereIF(!string.IsNullOrEmpty(input.ItemType), pxmx => pxmx.ItemCategory == input.ItemType);
// 2. 通过 EXISTS 子查询筛选关联字段(在分页前筛选,确保分页准确)
+ // 处理多门店筛选:优先使用StoreIds,如果没有则使用StoreId
+ var filterStoreIds = new List();
+ if (input.StoreIds != null && input.StoreIds.Any())
+ {
+ filterStoreIds = input.StoreIds.Where(x => !string.IsNullOrEmpty(x)).ToList();
+ }
+ else if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ filterStoreIds = new List { input.StoreId };
+ }
+
baseQuery = baseQuery.WhereIF(!string.IsNullOrEmpty(input.MemberName), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Khmc != null && x.Khmc.Contains(input.MemberName)).Any())
.WhereIF(!string.IsNullOrEmpty(input.MemberPhone), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.MemberId && x.Sjh == input.MemberPhone).Any())
- .WhereIF(!string.IsNullOrEmpty(input.StoreId), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.ConsumeInfoId && x.Md == input.StoreId).Any());
+ .WhereIF(filterStoreIds.Any(), pxmx => SqlFunc.Subqueryable().Where(x => x.Id == pxmx.ConsumeInfoId && filterStoreIds.Contains(x.Md)).Any());
// 3. 先分页查询主表数据(查询实体类,提高性能)
var pagedData = await baseQuery.OrderBy(sidx + " " + sort).ToPagedListAsync(input.currentPage, input.pageSize);
--
libgit2 0.21.4