trae兄弟分分鐘就幹完了,你敢相信麼-是有點像那麼回事

会员模块设计文档

会员模块實現

 

image

 

 

 

宠辱不惊,闲看庭前花开花落;去留无意,漫随天外云卷云舒

 

 

📋 项目概述

本模块实现会员卡的完整业务流程,包括后台制卡前台售卡激活以及后续的充值、消费、退款、积分兑换等功能。

  • 架构:WinForm桌面端(SQLite) + Web后端(ZRAdmin .NET 8) + 前端(Vue3)
  • ORM:SqlSugar(非Code First模式)
  • 金额单位:以"分"存储(long类型),避免浮点数精度问题
  • 密码安全:SHA256 + Salt加密

一、业务流程

1.1 会员卡生命周期

1
后台制卡 → 门店工作人员在后台创建未开通的会员卡
卡状态:未开通(0)
2
前台售卡激活 → 顾客付款后激活卡片,填写档案信息
卡状态:正常(1)
3
日常业务 → 充值、消费、退款、积分兑换、修改密码等
4
状态变更 → 冻结、挂失、注销等

二、会员卡状态定义

状态值名称说明可充值可消费可激活
0 未开通 制卡后的初始状态
1 正常 正常使用的状态
2 冻结 账户冻结
3 挂失 卡片遗失挂失
4 注销 卡片已注销

三、数据模型

3.1 会员卡表 (member_card)

字段类型说明
id long 自增主键
key_id string(50) 业务主键(Guid)
fk_company_id string(50) 公司ID
fk_store_id string(50) 门店ID
card_no string(20) 卡号
chip_id string(32) 芯片ID
phone string(11) 手机号
real_name string(50) 姓名
password_hash string(64) 密码哈希
password_salt string(32) 密码盐
status byte 状态(0-4)
current_balance long 当前余额(分)
current_principal long 本金(分)
current_gift long 赠送金(分)
total_recharge long 累计充值(分)
total_consume long 累计消费(分)
total_points int 累计积分
current_points int 当前积分
discount_rate decimal(5,2) 折扣率(%)
open_date datetime 开卡日期
create_time datetime 创建时间

3.2 会员充值记录表 (member_recharge)

字段类型说明
id long 自增主键
key_id string(50) 业务主键
card_id long 会员卡ID
card_key_id string(50) 会员卡业务主键
recharge_no string(32) 充值单号
recharge_type byte 类型(1=开卡,2=充值,3=赠送,4=退款)
amount long 本金金额(分)
gift_amount long 赠送金额(分)
pay_method byte 支付方式(1=现金,2=微信,3=支付宝,4=银行卡)
operator_id string(50) 操作员
recharge_time datetime 充值时间

3.3 会员消费记录表 (member_consume)

字段类型说明
id long 自增主键
consume_no string(32) 消费单号
order_id string(32) 关联订单号
total_amount long 消费总额(分)
actual_amount long 实际金额(分)
principal_amount long 本金扣款(分)
gift_amount long 赠送金扣款(分)
discount_amount long 折扣金额(分)
earned_points int 获得积分

四、API接口

方法路径权限说明
GET /business/MemberCard/list business:member:list 查询会员列表
GET /business/MemberCard/{keyId} business:member:query 获取会员详情
POST /business/MemberCard/make business:member:make 后台制卡
POST /business/MemberCard/activate business:member:activate 售卡激活
POST /business/MemberCard/recharge business:member:recharge 会员充值
POST /business/MemberCard/consume business:member:consume 会员消费
POST /business/MemberCard/refund business:member:refund 会员退款
POST /business/MemberCard/adjust business:member:adjust 余额调账
POST /business/MemberCard/points/exchange business:member:points 积分兑换
POST /business/MemberCard/password business:member:password 修改密码
POST /business/MemberCard/status business:member:status 变更状态

五、业务规则

5.1 金额计算

  • • 金额以为单位存储,使用long类型避免浮点数精度问题
  • • 前端显示时除以100转换为元
  • • 消费时赠送金优先扣除,默认30%扣赠送金

5.2 密码安全

  • • 使用SHA256 + Salt加密存储
  • • Salt长度为16位随机字符串

5.3 消费扣款优先级

  1. 先扣赠送金(默认30%比例)
  2. 不足时用本金补足
  3. 本金不足则拒绝交易

5.4 积分规则

  • • 消费1元获得1积分
  • • 100积分可兑换1元抵现

六、文件清单

后端 (ZRAdmin .NET 8)

文件路径说明
ZR.Model/Models/Business/MemberCard.cs 会员卡实体
ZR.Model/Models/Business/MemberRecharge.cs 充值记录实体
ZR.Model/Models/Business/MemberConsume.cs 消费记录实体
ZR.Model/Dto/Business/MemberCardDto.cs 数据传输对象
ZR.Service/Business/IBusinessService/IMemberCardService.cs Service接口
ZR.Service/Business/MemberCardService.cs Service实现
ZR.Admin.WebApi/Controllers/Business/MemberCardController.cs API控制器

前端 (Vue3)

文件路径说明
src/api/business/member.js API接口封装
src/views/business/memberCard.vue 会员管理页面

WinForm端

文件路径说明
POSFramework/Entity/MemberCardStatus.cs 会员卡状态枚举
POSFramework/Dto/MemberCardDto.cs Dto定义
POSFramework/Service/MemberCardService.cs 业务逻辑
POSFramework/modules/MemberCardForm.cs 会员主界面
POSFramework/modules/MemberCardMakeForm.cs 制卡界面
POSFramework/modules/MemberCardActivateForm.cs 售卡激活界面

七、核心代码片段

7.1 制卡 (MakeCard)

public string MakeCard(MemberCardMakeDto dto, string operatorId)
{
    // 检查卡号或芯片ID是否已存在
    var exists = Queryable()
        .Where(c => c.CardNo == dto.CardNo || c.ChipId == dto.ChipId)
        .First();
    if (exists != null) throw new Exception($"卡号[{dto.CardNo}]已存在!");

    var cardKeyId = Guid.NewGuid().ToString("N");
    var card = new MemberCard
    {
        KeyId = cardKeyId,
        FkCompanyId = dto.FkCompanyId,
        FkStoreId = dto.FkStoreId,
        CardNo = dto.CardNo,
        ChipId = dto.ChipId,
        Status = MemberCardStatus.NotActivated, // 未开通
        DiscountRate = 100,
        CreateBy = operatorId,
        CreateTime = DateTime.Now
    };
    Context.Insertable(card).ExecuteCommand();
    return cardKeyId;
}

7.2 售卡激活 (ActivateCard)

public string ActivateCard(MemberCardActivateDto dto, string operatorId)
{
    var card = GetInfo(dto.CardKeyId);
    if (card.Status != MemberCardStatus.NotActivated)
        throw new Exception($"当前状态不能激活!");

    // 更新档案
    card.RealName = dto.RealName;
    card.Phone = dto.Phone;
    card.Status = MemberCardStatus.Normal; // 激活为正常
    card.OpenDate = DateTime.Now;
    card.CurrentBalance = dto.Amount + dto.GiftAmount;
    card.CurrentPrincipal = dto.Amount;
    card.CurrentGift = dto.GiftAmount;

    // 设置密码
    var (hash, salt) = HashPassword(dto.Password);
    card.PasswordHash = hash;
    card.PasswordSalt = salt;

    Context.Ado.BeginTran();
    Context.Updateable(card).ExecuteCommand();
    // 创建充值记录...
    Context.Ado.CommitTran();
    return card.KeyId;
}

7.3 消费 (Consume)

public bool Consume(MemberConsumeDto dto, string operatorId)
{
    var card = GetInfo(dto.CardKeyId);
    if (card.Status != MemberCardStatus.Normal)
        throw new Exception("会员卡状态不允许消费!");

    // 计算折扣和实际金额
    var discountAmt = (long)(dto.TotalAmount * (100m - card.DiscountRate) / 100m);
    var actualAmt = dto.TotalAmount - discountAmt;

    // 赠送金优先扣除(30%)
    long giftDeduct = (long)(actualAmt * 30 / 100);
    long principalDeduct = actualAmt - giftDeduct;
    if (card.CurrentGift < giftDeduct) {
        principalDeduct += giftDeduct - card.CurrentGift;
        giftDeduct = card.CurrentGift;
    }
    if (card.CurrentPrincipal < principalDeduct)
        throw new Exception("本金余额不足!");

    card.CurrentPrincipal -= principalDeduct;
    card.CurrentGift -= giftDeduct;
    card.CurrentBalance = card.CurrentPrincipal + card.CurrentGift;
    card.TotalConsume += principalDeduct;

    // 创建消费记录...
    return true;
}

✅ 完成状态

  • ✓ WinForm端会员模块(含制卡、售卡激活)
  • ✓ 后端ZRAdmin API Controller
  • ✓ 前端Vue3会员页面
  • ✓ 数据库表设计(需手动创建)

🔒 会员生物识别升级

将传统密码验证升级为多种生物识别方式,提升安全性和用户体验。

  • 人脸识别:基于ViewFaceCore开源人脸识别库
  • 指纹识别:预留接口,支持集成第三方指纹SDK
  • 多因素验证:支持密码、人脸、指纹混合验证
  • 扩展架构:支持后续添加虹膜、声纹等识别方式

一、升级目标

1.1 业务目标

  • • 替代传统密码验证,提升会员身份认证安全性
  • • 支持人脸直接识别会员,简化操作流程
  • • 为后续扩展指纹、虹膜等识别方式奠定基础
  • • 与现有考勤模块(viewface_attendance_ext)共用识别能力

1.2 技术目标

  • • 识别准确率:人脸识别 ≥ 99%(阈值70以上)
  • • 识别速度:单次识别 ≤ 500ms
  • • 支持1:N识别(通过人脸查找会员)
  • • 支持1:1验证(验证指定会员身份)
  • • 支持多终端同步生物特征数据

二、验证方式对比

验证方式安全性便捷性成本实现状态
密码 ★★☆ ★★☆ ★★★ 原有
人脸识别 ★★★ ★★★ ★★☆ 新增
指纹识别 ★★★ ★★★ ★★☆ 预留接口
卡片 ★★☆ ★★★ ★★☆ 规划中

三、架构设计

3.1 整体架构

数据层

member_biometric - 生物特征存储

member_biometric_log - 识别日志

服务层

IBiometricService - 统一接口

FaceRecognitionService - 人脸识别

FingerprintService - 指纹识别

管理层

BiometricManager - 服务管理

MemberCardService - 会员验证

界面层

MemberBiometricForm - 生物识别管理

3.2 服务接口设计

public interface IBiometricService
{
    byte BiometricType { get; }
    string ServiceName { get; }
    bool IsInitialized { get; }
    
    bool Initialize(string modelPath = null);
    Task<(bool success, string featureData, string message)> RegisterAsync(
        string cardKeyId, Image image, int threshold, string operatorId);
    Task IdentifyAsync(Image image, string companyId, string storeId);
    Task<(bool success, decimal similarity, string message)> VerifyAsync(
        string cardKeyId, Image image);
    bool Delete(string cardKeyId, int indexNo, string operatorId);
    void LogIdentify(string cardKeyId, byte result, decimal? similarity, 
        int durationMs, string deviceId, string operatorId, string remark);
}

3.3 管理器设计

public class BiometricManager
{
    // 注册服务
    void RegisterService(IBiometricService service);
    
    // 验证会员(支持多种方式)
    Task<(bool success, string message)> VerifyMemberAsync(
        string cardKeyId, byte authMethod, object authData);
    
    // 识别会员(1:N)
    Task IdentifyMemberAsync(
        byte biometricType, Image image, string companyId, string storeId);
    
    // 注册生物特征
    Task<(bool success, string message)> RegisterBiometricAsync(
        string cardKeyId, byte biometricType, Image image, int threshold);
}

四、人脸识别实现

4.1 依赖库

库名版本用途
ViewFaceCore 6.0+ 人脸识别核心库
ViewFaceCore.Model 6.0+ 人脸模型定义
AForge.NET 2.2+ 摄像头采集

4.2 识别流程

1
人脸检测 → FaceDetector.Detect(image)
检测图像中人脸位置和大小
2
关键点检测 → FaceLandmarker.Mark(image, faceInfo)
检测68个人脸关键点(眼睛、鼻子、嘴巴等)
3
特征提取 → FaceRecognizer.Extract(image, faceInfo, markPoints)
提取512维人脸特征向量
4
特征比对 → FaceRecognizer.Compare(feature1, feature2)
计算余弦相似度(0-1)
5
结果判断 → similarity ≥ threshold
根据阈值判断是否匹配

4.3 特征数据处理

// 序列化特征(存储到数据库)
private string SerializeFeature(FaceFeature feature)
{
    return Convert.ToBase64String(feature.Data);
}

// 反序列化特征(从数据库读取)
private FaceFeature DeserializeFeature(string featureData)
{
    var data = Convert.FromBase64String(featureData);
    return new FaceFeature(data);
}

五、安全机制

5.1 失败锁定

  • • 连续失败5次后锁定生物识别
  • • 锁定时间:30分钟
  • • 可由管理员手动解锁
  • • 验证成功后自动重置失败次数

5.2 识别阈值

  • • 默认阈值:70%
  • • 阈值范围:50%-100%
  • • 越高越严格,越低越宽松
  • • 每个会员可独立设置阈值

5.3 日志记录

字段说明
card_key_id 会员卡号
biometric_type 识别类型
result 结果(0=成功,1=失败,2=锁定)
similarity 相似度
duration_ms 耗时(毫秒)
device_id 设备ID
create_time 时间

六、数据库升级

6.1 member_biometric 表

CREATE TABLE `member_biometric` (
    `id` INTEGER PRIMARY KEY AUTOINCREMENT,
    `key_id` VARCHAR(50) NOT NULL,
    `card_key_id` VARCHAR(50) NOT NULL,
    `biometric_type` TINYINT NOT NULL COMMENT '2=人脸,3=指纹',
    `feature_data` TEXT NOT NULL COMMENT '特征数据(Base64)',
    `feature_version` INT DEFAULT 1,
    `index_no` INT DEFAULT 0 COMMENT '索引号(多指纹)',
    `is_enabled` BOOLEAN DEFAULT 1,
    `threshold` INT DEFAULT 70,
    `last_used_time` DATETIME,
    `fail_count` INT DEFAULT 0,
    `lock_expire_time` DATETIME,
    `create_by` VARCHAR(50),
    `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
    `update_by` VARCHAR(50),
    `update_time` DATETIME
);

6.2 member_biometric_log 表

CREATE TABLE `member_biometric_log` (
    `id` INTEGER PRIMARY KEY AUTOINCREMENT,
    `card_key_id` VARCHAR(50) NOT NULL,
    `biometric_type` TINYINT NOT NULL,
    `result` TINYINT NOT NULL COMMENT '0=成功,1=失败,2=锁定',
    `similarity` DECIMAL(5,2),
    `duration_ms` INT DEFAULT 0,
    `device_id` VARCHAR(50),
    `operator_id` VARCHAR(50),
    `remark` VARCHAR(255),
    `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP
);

七、文件清单

文件路径类型说明
POSFramework/Entity/MemberBiometricEntity.cs Entity 生物识别实体类
POSFramework/Service/IBiometricService.cs Interface 生物识别服务接口
POSFramework/Service/FaceRecognitionService.cs Service 人脸识别服务
POSFramework/Service/FingerprintService.cs Service 指纹识别服务(预留)
POSFramework/Service/BiometricManager.cs Manager 生物识别管理器
POSFramework/modules/MemberBiometricForm.cs Form 生物识别管理界面
POSFramework/Service/MemberCardService.cs Service 会员服务(已修改)

八、使用示例

8.1 初始化

// 创建生物识别管理器
var biometricManager = new BiometricManager();

// 注册人脸识别服务
biometricManager.RegisterService(new FaceRecognitionService());

// 初始化服务(加载模型)
biometricManager.InitializeAll("Models/Face");

8.2 注册人脸

// 获取摄像头图像
var faceImage = CaptureFaceImage();

// 注册人脸特征
var (success, message) = await biometricManager.RegisterBiometricAsync(
    cardKeyId: "card123",
    biometricType: BiometricType.Face,
    image: faceImage,
    threshold: 70,
    operatorId: "admin"
);

8.3 验证会员

// 方式1:人脸验证
var (success, msg) = await memberService.VerifyMemberAsync(
    cardKeyId: "card123",
    authMethod: BiometricType.Face,
    authData: faceImage,
    biometricManager: biometricManager
);

// 方式2:密码验证
var (success, msg) = await memberService.VerifyMemberAsync(
    cardKeyId: "card123",
    authMethod: BiometricType.Password,
    authData: "123456"
);

8.4 识别会员

// 通过人脸直接识别会员
var result = await biometricManager.IdentifyMemberAsync(
    biometricType: BiometricType.Face,
    image: faceImage,
    companyId: "company001",
    storeId: "store001"
);

if (result.Success)
{
    var card = memberService.GetByKeyId(result.CardKeyId);
    Console.WriteLine($"识别成功:{card.RealName}");
}

九、与考勤模块集成

9.1 共享识别能力

  • • 使用相同的ViewFaceCore库进行人脸识别
  • • 人脸特征存储在同一数据库表
  • • 会员可使用人脸进行考勤打卡
  • • 考勤打卡后自动记录会员消费

9.2 同步机制

  • • 人脸特征数据通过UDP局域网同步
  • • 定期与服务器MySQL同步
  • • 支持离线识别(本地存储特征)

十、扩展计划

阶段功能状态
Phase 1 人脸识别(注册、验证、识别) 已实现
Phase 2 指纹识别接口(预留) 已实现
Phase 3 集成指纹SDK(Upek/Synaptics) 待实现
Phase 4 虹膜识别(预留接口) 规划中
Phase 5 声纹识别(预留接口) 规划中
Phase 6 多因素认证(人脸+指纹) 规划中

✅ 升级完成

  • ✓ 人脸识别服务(基于ViewFaceCore)
  • ✓ 指纹识别服务(预留接口)
  • ✓ 生物识别管理器
  • ✓ 会员验证逻辑升级
  • ✓ 生物识别管理界面
  • ✓ 数据库表设计
  • ✓ 安全机制(失败锁定、日志记录)
posted @ 2026-06-24 20:33  数据酷软件  阅读(15)  评论(1)    收藏  举报