惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
N
News and Events Feed by Topic
D
DataBreaches.Net
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Engineering at Meta
Engineering at Meta
T
Tailwind CSS Blog
博客园_首页
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
月光博客
月光博客
A
About on SuperTechFans
I
InfoQ
S
Securelist
Last Week in AI
Last Week in AI
S
Schneier on Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Hacker News: Ask HN
Hacker News: Ask HN
Schneier on Security
Schneier on Security
Know Your Adversary
Know Your Adversary
腾讯CDC
大猫的无限游戏
大猫的无限游戏
S
Security @ Cisco Blogs
博客园 - 三生石上(FineUI控件)
Simon Willison's Weblog
Simon Willison's Weblog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
美团技术团队
aimingoo的专栏
aimingoo的专栏
G
Google Developers Blog
罗磊的独立博客
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Cloudflare Blog
S
Secure Thoughts
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Latest news
Latest news
Recent Announcements
Recent Announcements
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LINUX DO - 热门话题
Security Latest
Security Latest
TaoSecurity Blog
TaoSecurity Blog
Cyberwarzone
Cyberwarzone
有赞技术团队
有赞技术团队

博客园_首页

Linux实操--组管理、权限管理和定时任务 Java + EasyExcel 实现单个接口导出多个Excel Mem0 源码解析系列(二):提示词工程的深度剖析 Openclaw TaskFlow究竟是什么?和普通Skill技能有什么区别 博文阅读密码验证 - 博客园 嘉立创开源:应该是全网MicroPython教程最多的开发板 Hermes Agent 集成实践:从协议到生产 2026年AI编程工具横评:Cursor、Codex、Claude Code、Zed、Windsurf Java程序员必看的RAG入门教程 2026 AI效率神器:Superpowers + Claude Code 保姆级教程 本地大模型部署全攻略:从 0 到 1 玩转 Ollama 【从0到1构建一个ClaudeAgent】内存管理-上下文压缩 .NET 高级开发 | 设计、实现一个事件总线框架 电子小白入门之NE555 3. WorkBuddy:隐藏玩法,一键召唤专家,让 AI 以"专家身份"给你干活 和AI一起搞事情#3:Claude Teammate 游戏开发翻车实录 【OpenClaw】通过 Nanobot 源码学习架构---(7)Memory C# .NET 周刊|2026年3月3期 我在 Debian 11 上把 K8s 单机搭起来了,过程没你想的那么顺(/opt 目录版) 深度学习进阶(七)Data-efficient Image Transformer CLI+Skill搭建浏览器AI自动化框架,告别一切重复枯燥任务 告别Token账单无底洞:OpenClaw本地部署,重塑企业数据主权的唯一解 FastAPI+Vue:文件分片上传+秒传+断点续传,这坑我帮你踩平了! SBTI 爆火后,我做了个程序员版的 CBTI。。已开源 + 附开发过程 多模态检索开始进入工程期:用 Sentence Transformers 搭建可落地的 Multimodal RAG 100多行代码实现一个最简单的Agent(用ReAct) Claude Code 通关手册(八):推荐 5 个 Hooks,代码质量提升 3 倍 老板:“有人截图了!”。安全部门:“收到,马上查暗水印!” - why技术 技术之外,皆是人间 C#/.NET/.NET Core技术前沿周刊 | 第 69 期(2026年4.01-4.12) Snack JSONPath 项目架构分析 Claude Code Buddy 小析:一个非核心功能,如何体现产品的细节完成度 AI新时代下的图床管理方案-Cloudflare图床+MCP+Skills方案指南 化繁为简:顺丰速运App如何通过 HarmonyOS SDK实现专业级空间测量 从零实现富文本编辑器#13-React非编辑节点的内容渲染 AI开发-python-langchain框架(3-23-OpenAI Functions风格Tool Calling智能助手) .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut PbootCMS 网站内容数量多导致访问慢?这些实用优化方案帮你提速! - 家兴网络技术工作室 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 网站漏洞怎么发现并修复?一篇实用指南(附完整流程) - 家兴网络技术工作室 开了 TUN 模式还是直连?90% 的人都踩过这个坑 Github日报|2026年04月12日 - AI一族 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术 Etsy 把 1000 个 MySQL 分片迁进 Vitess:425TB 数据背后的真正问题不是性能,而是运维规模 MicroPython LVGL基础知识和概念:底层渲染与性能优化 - FreakStudio 数据库草图算法 Python 潮流周刊#146:CPython 引入 Rust 的进展 - 豌豆花下猫 最小生成树 - mofei1116 红日靶场七:从外网入口、容器逃逸到 AD 接管的完整利用链复盘 - YouDiscovered1t 分享四款开源且实用的 Kafka 管理工具 - 追逐时光者 vLLM 权重加载机制全解析:从挑战到理想架构 LCT 学习笔记 - ACehomoxue Avalonia UI 12.0.0 正式发布:架构演进和性能飞跃 - 张善友 当 AI Agent 把调用链拉长,延迟开始成为一门生意 conhost.exe 无法显示 U+2717 - 145a 太秀了,我把自己蒸馏成了 Skill!已开源 - 程序员鱼皮 ASP.NET Core 内存缓存实战:一篇搞懂该怎么配、怎么避坑 基于 Ghostty 带有分割标签页和为 Claude 编程设计的通知终端 - BugShare AI 焊死入口:教育的“操作系统级”重塑 - 郝hai 初级Java开发工程师使用sql脚本编写代码的过程是简单而且不糊涂 - CoderOilStation Claude Code通关手册(六):MCP协议完全指南 - 暮色之狐 边框灯光环绕动画特效实现指南 - Newbe36524 开源:子木蒸馏版的 SEO 审计工具 seo-audit-skill v1.0 我所理解的Python元模型 【从0到1构建一个ClaudeAgent】规划与协调-TodoWrite - 程序员Seven Claude 和 Codex 在审计 Skill 上性能差异探究 - ACai_sec AScript如何实现中文脚本引擎 - rockey627 【渗透测试】HTB Season10 Garfield 全过程wp - dynasty_chenzi Android 开发者为什么必须掌握 AI 能力?端侧视角下的技术变革 树状数组正确性证明 - AC-wyr 你的 AI 焦虑,可能比 AI 本身更危险——ATM 机没有消灭银行柜员,但恐慌消灭了你的判断力 - 我没有三颗心脏 一个拉胯的分库分表方案有多绝望?整个部门都在救火! - 冰河团队 动态规划入门必学之走方格问题 - Ofnoname PostgREST 与 PostgreSQL 角色权限配置全解析(生产级实践) - SheepDog1998 使用 UEFI 图形输出协议 GOP 在屏幕上显示图像的方法 - 阿源- Claude Code通关手册(五):组建你的AI专家团队,子代理系统 - 暮色之狐 一个程序员到架构师的催婚路之感悟(整整10年后的催婚相亲感悟) - MisterLip 用 Agent Skill 自动生成工作周报 - 赵康
DeepSeek幫我設計的會員模塊
数据酷软件 · 2026-06-24 · via 博客园_首页

🏷️ 会员模块数据库设计文档

支持多商户·多门店·实物卡·储值消费·积分体系·余额重算 · MySQL 8.0+

📅 版本:v3.0 (多商户版) 📁 数据库:MySQL 8.0 🧩 字符集:utf8mb4 📐 金额精度:分 (BIGINT) 📋 表数量:10 张 🏢 支持:多商户 + 多门店

📖 概述

本数据库设计面向 多商户多门店会员卡管理系统,支持 实物卡(芯片ID)无卡消费(手机号) 两种场景。 核心能力包括:储值充值、折扣消费、积分累积与兑换、余额变动全链路日志、余额重算 机制,以及 多商户/门店数据隔离。 设计时已预留 计次卡 扩展能力。

🏢 多商户多门店支持: 所有会员表已增加 fk_company_idfk_store_id 字段,实现数据隔离。 每个商户/门店可独立配置积分规则、折扣比例、充值策略等。

🔗 实体关系图 (ER)

╔═══════════════════════════════════════════════════════════════════════════════════════════════════════╗ ║ 📦 多商户会员系统 ER 图 ║ ╠═══════════════════════════════════════════════════════════════════════════════════════════════════════╣ ║ ║ ║ ┌─────────────────────────────┐ ┌─────────────────────────────────┐ ║ ║ │ sauna_merchant │ │ sauna_merchant_store │ ║ ║ │ (商户公司表-已有) │ │ (门店表-已有) │ ║ ║ │─────────────────────────────│ │─────────────────────────────────│ ║ ║ │ key_id (PK) │◄─────────│ fk_company_id (FK) │ ║ ║ │ company_fullname │ 1 n │ key_id (PK) │ ║ ║ │ company_shortname │ │ name │ ║ ║ └─────────────────────────────┘ └─────────────────────────────────┘ ║ ║ │ │ ║ ║ │ 1 │ 1 ║ ║ ├───────────────────────┬──────────────────┘ ║ ║ │ │ ║ ║ ▼ ▼ ║ ║ ┌──────────────────────────────────────────────────────────────────────────────┐ ║ ║ │ member_card (会员卡主表) │ ║ ║ │──────────────────────────────────────────────────────────────────────────────│ ║ ║ │ key_id (PK) │ card_no (UK) │ chip_id (UK) │ phone (idx) │ ║ ║ │ fk_company_id (FK) │ fk_store_id (FK) │ status │ card_type │ ║ ║ │ current_principal │ current_gift │ current_points │ discount_rate │ ║ ║ └──────────────────────────────────────────────────────────────────────────────┘ ║ ║ │ ║ ║ │ 1 ║ ║ ├─────────────────────────────────────────────────────────────────┐ ║ ║ │ │ ║ ║ ▼ ▼ ║ ║ ┌─────────────────────────┐ ┌─────────────────────────────────────┐ ║ ║ │ member_recharge │ │ member_consume │ ║ ║ │ (充值记录表) │ │ (消费明细表) │ ║ ║ │─────────────────────────│ │─────────────────────────────────────│ ║ ║ │ key_id (PK) │ │ key_id (PK) │ ║ ║ │ card_key_id (FK) │ │ card_key_id (FK) │ ║ ║ │ recharge_no (UK) │ │ consume_no (UK) │ ║ ║ │ amount, gift_amount │ │ principal_amount, gift_amount │ ║ ║ └─────────────────────────┘ └─────────────────────────────────────┘ ║ ║ │ │ ║ ║ └───────────────────┬───────────────────┘ ║ ║ │ ║ ║ ▼ ║ ║ ┌─────────────────────────────────────────────────────────────────────────────┐ ║ ║ │ member_balance_log (余额变动日志-核心) │ ║ ║ │─────────────────────────────────────────────────────────────────────────────│ ║ ║ │ key_id (PK) │ card_key_id (FK) │ log_no (UK) │ change_type │ ║ ║ │ before_principal │ after_principal │ before_gift │ after_gift │ ║ ║ │ is_recalculated │ source_type │ source_id │ ║ ║ └─────────────────────────────────────────────────────────────────────────────┘ ║ ║ ║ ║ ┌─────────────────────────┐ ┌─────────────────────────────────────┐ ║ ║ │ member_points_exchange │ │ member_balance_recalc │ ║ ║ │ (积分兑换记录表) │ │ (余额重算记录表) │ ║ ║ │─────────────────────────│ │─────────────────────────────────────│ ║ ║ │ key_id (PK) │ │ key_id (PK) │ ║ ║ │ card_key_id (FK) │ │ card_key_id (FK) │ ║ ║ │ points_used │ │ old_principal, new_principal │ ║ ║ │ exchange_type │ │ diff_principal, diff_gift │ ║ ║ └─────────────────────────┘ └─────────────────────────────────────┘ ║ ║ ║ ║ ┌─────────────────────────────┐ ┌─────────────────────────────────┐ ║ ║ │ member_merchant_config │ │ member_operation_log │ ║ ║ │ (商户配置-新增) │ │ (操作审计日志-新增) │ ║ ║ │─────────────────────────────│ │─────────────────────────────────│ ║ ║ │ key_id (PK) │ │ key_id (PK) │ ║ ║ │ fk_company_id (FK) │ │ card_key_id (FK) │ ║ ║ │ fk_store_id (FK) │ │ operation_type │ ║ ║ │ gift_consume_ratio │ │ before_data, after_data │ ║ ║ │ points_rate │ │ ip_address, user_agent │ ║ ║ └─────────────────────────────┘ └─────────────────────────────────┘ ║ ║ ║ ║ ┌─────────────────────────────────────────────────────────────────────────────┐ ║ ║ │ system_consume_config (系统配置) │ ║ ║ │ config_key (UK) │ config_value │ description │ ║ ║ └─────────────────────────────────────────────────────────────────────────────┘ ║ ║ ║ ╚═══════════════════════════════════════════════════════════════════════════════════════════════════════╝

🆕 本次新增/变更:

  • 新增 fk_company_idfk_store_id 字段到所有会员表
  • 新增 member_merchant_config 表 - 商户/门店级别配置
  • 新增 member_operation_log 表 - 操作审计日志
  • 统一 所有表增加公用字段:key_idsort_indexcreate_bycreate_timeupdate_byupdate_time
  • 新增 v_member_card_full 视图 - 关联商户门店信息

📋 表结构详细设计

1. member_card 会员卡主表

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
fk_company_id VARCHAR(50) NO FK 🏢 所属公司ID
fk_store_id VARCHAR(50) NO FK 🏪 所属门店ID
card_no VARCHAR(20) NO UK 会员卡编号(自编号)
chip_id VARCHAR(32) NO UK 芯片ID唯一码(实物卡)
phone VARCHAR(11) NO INDEX 绑定手机号(无卡消费)
card_type TINYINT NO - 1-储值卡,2-计次卡(预留)
status TINYINT NO INDEX 0-冻结,1-正常,2-挂失,3-注销
total_recharge BIGINT NO - 累计充值金额(不含赠送,分)
total_gift BIGINT NO - 累计赠送金额(分)
total_consume BIGINT NO - 累计消费本金(分)
total_gift_consume BIGINT NO - 累计赠送消费(分)
current_balance BIGINT NO - 当前可用总余额(本金+赠送)
current_principal BIGINT NO - 当前本金余额
current_gift BIGINT NO - 当前赠送余额
total_points INT NO - 累计获得积分
used_points INT NO - 已使用积分
current_points INT NO - 当前可用积分
discount_rate DECIMAL(5,2) NO - 折扣比例(100=不打折,90=9折)
open_date DATETIME NO - 开卡日期
expire_date DATETIME YES - 有效期(计次卡使用)
last_consume_time DATETIME YES - 最后消费时间
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

🏢 多商户关键字段: fk_company_idfk_store_id 实现数据隔离, 查询时务必带上这两个条件,确保不同商户/门店数据互不干扰。

2. member_recharge 开卡/充值记录表

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
card_id BIGINT UNSIGNED NO FK 会员卡自增ID
card_key_id VARCHAR(50) NO FK 会员卡业务ID
recharge_no VARCHAR(32) NO UK 充值流水号
recharge_type TINYINT NO - 1-开卡,2-充值,3-赠送活动,4-手动调账
amount BIGINT NO - 充值金额(本金,分)
gift_amount BIGINT NO - 赠送金额(分)
pay_method TINYINT YES - 1-现金,2-微信,3-支付宝,4-银行卡
operator_id VARCHAR(50) YES - 操作人员ID
remark VARCHAR(255) YES - 备注
recharge_time DATETIME NO INDEX 充值时间
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

3. member_consume 消费明细表

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
card_id BIGINT UNSIGNED NO FK 会员卡自增ID
card_key_id VARCHAR(50) NO FK 会员卡业务ID
consume_no VARCHAR(32) NO UK 消费流水号
order_id VARCHAR(32) YES INDEX 关联订单号
total_amount BIGINT NO - 消费总金额(原始金额,分)
actual_amount BIGINT NO - 实际扣款金额(折扣后)
principal_amount BIGINT NO - 扣本金金额
gift_amount BIGINT NO - 扣赠送金额
discount_amount BIGINT NO - 优惠金额
earned_points INT NO - 获得积分
consume_time DATETIME NO INDEX 消费时间
operator_id VARCHAR(50) YES - 操作人员ID
remark VARCHAR(255) YES - 备注
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

4. member_balance_log ⭐ 余额变动日志表(核心)

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
card_id BIGINT UNSIGNED NO FK 会员卡自增ID
card_key_id VARCHAR(50) NO FK 会员卡业务ID
log_no VARCHAR(32) NO UK 日志流水号
change_type TINYINT NO - 1-开卡,2-充值,3-消费,4-退款,5-手动调整,6-积分兑换,7-余额重算修正
change_amount BIGINT NO - 变动金额(正数增加,负数减少,分)
before_principal BIGINT NO - 变动前本金余额
after_principal BIGINT NO - 变动后本金余额
before_gift BIGINT NO - 变动前赠送余额
after_gift BIGINT NO - 变动后赠送余额
before_total BIGINT NO - 变动前总余额
after_total BIGINT NO - 变动后总余额
source_type VARCHAR(30) YES INDEX 来源类型:recharge/consume/refund/adjust
source_id VARCHAR(50) YES INDEX 来源表KeyId
operator_id VARCHAR(50) YES - 操作人ID
remark VARCHAR(255) YES - 备注
is_recalculated TINYINT NO - 是否被重算修正:0-否,1-是
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

5. member_points_exchange 积分兑换记录表

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
card_id BIGINT UNSIGNED NO FK 会员卡自增ID
card_key_id VARCHAR(50) NO FK 会员卡业务ID
exchange_no VARCHAR(32) NO UK 兑换流水号
points_used INT NO - 使用的积分
exchange_type TINYINT NO - 1-抵现,2-兑换礼品,3-兑换优惠券
exchange_value BIGINT NO - 兑换价值(抵现金额或礼品价值,分)
consume_id BIGINT UNSIGNED YES - 关联消费自增ID
consume_key_id VARCHAR(50) YES - 关联消费业务ID
status TINYINT NO - 1-成功,2-取消,3-失效
exchange_time DATETIME NO INDEX 兑换时间
operator_id VARCHAR(50) YES - 操作人ID
remark VARCHAR(255) YES - 备注
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

6. member_balance_recalc 余额重算记录表(审计)

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
card_id BIGINT UNSIGNED NO FK 会员卡自增ID
card_key_id VARCHAR(50) NO FK 会员卡业务ID
recalc_no VARCHAR(32) NO UK 重算流水号
old_principal BIGINT NO - 重算前本金余额
new_principal BIGINT NO - 重算后本金余额
old_gift BIGINT NO - 重算前赠送余额
new_gift BIGINT NO - 重算后赠送余额
old_total BIGINT NO - 重算前总余额
new_total BIGINT NO - 重算后总余额
diff_principal BIGINT NO - 本金差异
diff_gift BIGINT NO - 赠送差异
recalc_reason VARCHAR(255) NO - 重算原因
operator_id VARCHAR(50) NO - 操作人ID
recalc_time DATETIME NO INDEX 重算时间
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

7. member_merchant_config 🆕 商户会员卡配置表

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
fk_company_id VARCHAR(50) NO FK 🏢 所属公司ID
fk_store_id VARCHAR(50) YES FK 🏪 所属门店ID(NULL表示公司级配置)
config_type TINYINT NO - 配置类型:1-公司级,2-门店级
gift_consume_ratio INT NO - 赠送金额消费比例(百分比)
points_rate INT NO - 积分获得比例(每消费1元得N积分)
points_exchange_rate INT NO - 积分兑换比例(N积分=1元)
min_recharge_amount BIGINT YES - 最低充值金额(分)
max_gift_amount BIGINT YES - 单次最大赠送金额(分)
is_enabled TINYINT NO - 是否启用:0-禁用,1-启用
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

⚙️ 配置优先级: 门店配置(fk_store_id 有值)> 公司配置(fk_store_id 为 NULL)> 系统默认配置

8. member_operation_log 🆕 会员卡操作日志表(审计)

字段类型说明
id BIGINT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
card_id BIGINT UNSIGNED NO FK 会员卡自增ID
card_key_id VARCHAR(50) NO FK 会员卡业务ID
operation_type TINYINT NO INDEX 操作类型:1-开卡,2-充值,3-消费,4-冻结,5-解冻,6-挂失,7-解挂,8-注销,9-余额调整,10-积分调整
operation_content TEXT YES - 操作内容(JSON)
before_data TEXT YES - 操作前数据(JSON)
after_data TEXT YES - 操作后数据(JSON)
ip_address VARCHAR(50) YES - 操作IP
user_agent VARCHAR(255) YES - 用户代理
operator_id VARCHAR(50) YES - 操作人ID
operator_name VARCHAR(100) YES - 操作人姓名
remark VARCHAR(255) YES - 备注
operation_time DATETIME NO INDEX 操作时间
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO INDEX 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

9. system_consume_config 系统配置表

字段类型说明
id INT UNSIGNED NO PK 自增主键
key_id VARCHAR(50) NO UK 业务主键ID
config_key VARCHAR(50) NO UK 配置键
config_value VARCHAR(100) NO - 配置值
description VARCHAR(255) YES - 描述
sort_index INT YES - 排序码
create_by VARCHAR(50) YES - 创建人
create_time DATETIME NO - 创建时间
update_by VARCHAR(50) YES - 修改人
update_time DATETIME NO - 修改时间

10. v_member_card_full 📊 会员卡完整信息视图

CREATE OR REPLACE VIEW v_member_card_full AS SELECT mc.key_id, mc.card_no, mc.chip_id, mc.phone, mc.card_type, mc.status, mc.current_balance, mc.current_principal, mc.current_gift, mc.current_points, mc.discount_rate, mc.open_date, mc.expire_date, mc.last_consume_time, sm.company_fullname AS company_name, sm.company_shortname AS company_shortname, sm.contact_info AS company_contact, sm.contact_phone AS company_phone, sms.name AS store_name, sms.store_no, sms.phone AS store_phone, sms.address AS store_address, sms.contact AS store_contact, COALESCE(mmc_store.gift_consume_ratio, mmc_company.gift_consume_ratio, sys1.config_value) AS gift_consume_ratio, COALESCE(mmc_store.points_rate, mmc_company.points_rate, sys2.config_value) AS points_rate, COALESCE(mmc_store.points_exchange_rate, mmc_company.points_exchange_rate, sys3.config_value) AS points_exchange_rate FROM member_card mc LEFT JOIN sauna_merchant sm ON mc.fk_company_id = sm.key_id LEFT JOIN sauna_merchant_store sms ON mc.fk_store_id = sms.key_id LEFT JOIN member_merchant_config mmc_store ON mc.fk_store_id = mmc_store.fk_store_id AND mmc_store.is_enabled = 1 LEFT JOIN member_merchant_config mmc_company ON mc.fk_company_id = mmc_company.fk_company_id AND mmc_company.fk_store_id IS NULL AND mmc_company.is_enabled = 1 LEFT JOIN system_consume_config sys1 ON sys1.config_key = 'gift_consume_ratio' LEFT JOIN system_consume_config sys2 ON sys2.config_key = 'points_rate' LEFT JOIN system_consume_config sys3 ON sys3.config_key = 'points_exchange_rate';

⚙️ 核心建表SQL(完整)

CREATE TABLE member_card ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', key_id VARCHAR(50) NOT NULL COMMENT '业务主键ID', card_no VARCHAR(20) NOT NULL COMMENT '会员卡编号', chip_id VARCHAR(32) NOT NULL COMMENT '芯片ID唯一码', phone VARCHAR(11) NOT NULL COMMENT '绑定手机号', fk_company_id VARCHAR(50) NOT NULL COMMENT '所属公司ID', fk_store_id VARCHAR(50) NOT NULL COMMENT '所属门店ID', card_type TINYINT NOT NULL DEFAULT 1 COMMENT '卡类型:1-储值卡,2-计次卡', status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:0-冻结,1-正常,2-挂失,3-注销', total_recharge BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值金额', total_gift BIGINT NOT NULL DEFAULT 0 COMMENT '累计赠送金额', total_consume BIGINT NOT NULL DEFAULT 0 COMMENT '累计消费本金', total_gift_consume BIGINT NOT NULL DEFAULT 0 COMMENT '累计赠送消费', current_balance BIGINT NOT NULL DEFAULT 0 COMMENT '当前可用总余额', current_principal BIGINT NOT NULL DEFAULT 0 COMMENT '当前本金余额', current_gift BIGINT NOT NULL DEFAULT 0 COMMENT '当前赠送余额', total_points INT NOT NULL DEFAULT 0 COMMENT '累计获得积分', used_points INT NOT NULL DEFAULT 0 COMMENT '已使用积分', current_points INT NOT NULL DEFAULT 0 COMMENT '当前可用积分', discount_rate DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '折扣比例', open_date DATETIME NOT NULL COMMENT '开卡日期', expire_date DATETIME DEFAULT NULL COMMENT '有效期', last_consume_time DATETIME DEFAULT NULL COMMENT '最后消费时间', sort_index INT DEFAULT 0 COMMENT '排序码', create_by VARCHAR(50) DEFAULT NULL COMMENT '创建人', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_by VARCHAR(50) DEFAULT NULL COMMENT '修改人', update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (id), UNIQUE KEY uk_key_id (key_id), UNIQUE KEY uk_card_no (card_no), UNIQUE KEY uk_chip_id (chip_id), KEY idx_phone (phone), KEY idx_company_store (fk_company_id, fk_store_id), KEY idx_status (status), KEY idx_create_time (create_time) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员卡主表'; CREATE TABLE member_recharge ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, key_id VARCHAR(50) NOT NULL COMMENT '业务主键ID', card_id BIGINT UNSIGNED NOT NULL COMMENT '会员卡自增ID', card_key_id VARCHAR(50) NOT NULL COMMENT '会员卡业务ID', recharge_no VARCHAR(32) NOT NULL COMMENT '充值流水号', recharge_type TINYINT NOT NULL COMMENT '类型:1-开卡,2-充值,3-赠送活动,4-手动调账', amount BIGINT NOT NULL DEFAULT 0 COMMENT '充值金额(本金)', gift_amount BIGINT NOT NULL DEFAULT 0 COMMENT '赠送金额', pay_method TINYINT DEFAULT NULL COMMENT '支付方式', operator_id VARCHAR(50) DEFAULT NULL COMMENT '操作人员ID', remark VARCHAR(255) DEFAULT NULL COMMENT '备注', recharge_time DATETIME NOT NULL COMMENT '充值时间', sort_index INT DEFAULT 0 COMMENT '排序码', create_by VARCHAR(50) DEFAULT NULL COMMENT '创建人', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_by VARCHAR(50) DEFAULT NULL COMMENT '修改人', update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (id), UNIQUE KEY uk_key_id (key_id), UNIQUE KEY uk_recharge_no (recharge_no), KEY idx_card_id (card_id), KEY idx_card_key_id (card_key_id), KEY idx_recharge_time (recharge_time), KEY idx_create_time (create_time) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='充值/开卡记录表';

🧠 核心业务逻辑

💰 消费扣款流程

  • 1 获取商户/门店配置的 gift_consume_ratio
  • 2 根据比例计算赠送扣款金额
  • 3 优先扣除赠送金额,不足时从本金补扣
  • 4 按实际扣款金额计算积分
  • 5 记录 member_consume 明细
  • 6 同步更新 member_card 余额
  • 7 写入 member_balance_log 变动日志

🔄 余额重算流程

  • 1 根据 recharge + consume 重新计算
  • 2 对比当前余额,计算差异
  • 3 更新 member_card 为正确余额
  • 4 记录 member_balance_recalc 重算审计
  • 5member_balance_log 中插入修正记录
  • 6 标记相关日志 is_recalculated = 1

🏢 多商户数据隔离

  • 所有查询必须带 fk_company_id
  • 门店级查询额外带 fk_store_id
  • 配置优先级:门店 > 公司 > 系统
  • 支持跨门店会员(公司级统一管理)
  • 每个商户独立积分/折扣规则

📱 无卡消费 + 审计

  • 通过 phone 字段查询会员
  • 支持手机号+验证码身份验证
  • 所有操作记录 member_operation_log
  • 记录操作前后数据快照(JSON)
  • 支持操作追溯和问题排查

🚀 扩展性设计

✓ 计次卡

card_type=2,可增加次卡消费记录表

✓ 活动赠送

recharge_type=3 支持满赠活动

✓ 多级折扣

discount_rate 支持不同等级折扣

✓ 商户独立配置

member_merchant_config 支持各商户独立规则

✓ 完整审计

member_operation_log 记录所有操作

📌 索引优化建议

CREATE INDEX idx_company_store ON member_card(fk_company_id, fk_store_id); CREATE INDEX idx_company_store_status ON member_card(fk_company_id, fk_store_id, status); CREATE INDEX idx_company_store_time ON member_card(fk_company_id, fk_store_id, create_time); CREATE INDEX idx_balance_log_card_time ON member_balance_log(card_key_id, create_time DESC); CREATE INDEX idx_balance_log_company ON member_balance_log(card_key_id, create_time DESC); CREATE INDEX idx_consume_card_time ON member_consume(card_key_id, consume_time DESC); CREATE INDEX idx_consume_company_time ON member_consume(card_key_id, consume_time DESC); CREATE INDEX idx_oplog_card_time ON member_operation_log(card_key_id, operation_time DESC); CREATE INDEX idx_oplog_type_time ON member_operation_log(operation_type, operation_time DESC);

📊 枚举值说明

status

0-冻结,1-正常,2-挂失,3-注销

recharge_type

1-开卡,2-充值,3-赠送活动,4-手动调账

change_type (balance_log)

1-开卡,2-充值,3-消费,4-退款,5-手动调整,6-积分兑换,7-重算修正

exchange_type

1-抵现,2-兑换礼品,3-兑换优惠券

pay_method

1-现金,2-微信,3-支付宝,4-银行卡

operation_type

1-开卡,2-充值,3-消费,4-冻结,5-解冻,6-挂失,7-解挂,8-注销,9-余额调整,10-积分调整

📌 重要设计原则:

  • 所有金额字段以 「分」 为单位存储(BIGINT),避免浮点数精度问题
  • 余额变动 必须 记录 member_balance_log,且记录变动前后完整快照
  • 重算操作 必须 记录 member_balance_recalc,并标记相关日志
  • 多商户查询务必带上 fk_company_id,确保数据隔离
  • 建议使用 数据库事务 保证充值/消费/日志写入的原子性
  • key_id 作为业务主键,推荐使用 REPLACE(UUID(), '-', '') 生成

💻 C# 实体类示例

namespace ZR.Model.Merchant { [SugarTable("member_card")] public class MemberCard { [SugarColumn(IsPrimaryKey = true, IsIdentity = false, ColumnName = "key_id")] public string KeyId { get; get; set; } [SugarColumn(ColumnName = "fk_company_id")] public string FkCompanyId { get; get; set; } [SugarColumn(ColumnName = "fk_store_id")] public string FkStoreId { get; get; set; } [SugarColumn(ColumnName = "card_no")] public string CardNo { get; get; set; } [SugarColumn(ColumnName = "chip_id")] public string ChipId { get; get; set; } public string Phone { get; get; set; } [SugarColumn(ColumnName = "current_principal")] public long CurrentPrincipal { get; get; set; } [SugarColumn(ColumnName = "current_gift")] public long CurrentGift { get; get; set; } [SugarColumn(ColumnName = "current_points")] public int CurrentPoints { get; get; set; } [SugarColumn(ColumnName = "sort_index")] public int? SortIndex { get; get; set; } [SugarColumn(ColumnName = "create_by")] public string CreateBy { get; get; set; } [SugarColumn(ColumnName = "create_time")] public DateTime? CreateTime { get; get; set; } [SugarColumn(ColumnName = "update_by")] public string UpdateBy { get; get; set; } [SugarColumn(ColumnName = "update_time")] public DateTime? UpdateTime { get; get; set; } } }