feat: 添加耗材管理乐观锁机制

- 在 Consumable 模型中添加 version 字段用于乐观锁控制
- 为 quick-inout、inout、adjust 接口添加乐观锁和重试机制
- 修复 adjust/set 类型的负数库存校验
- 添加数据库迁移脚本支持 SQLite 和 MySQL
- 防止并发操作导致的负库存问题

技术细节:
- 使用 version 字段实现乐观锁,更新时校验版本号
- 并发冲突时自动重试(最多3次)
- 409 状态码表示并发冲突,400 表示库存不足
This commit is contained in:
zhang1106
2026-01-29 18:05:22 +08:00
parent 9e6a3da888
commit 94effd3436
2 changed files with 17 additions and 6 deletions
@@ -3,14 +3,18 @@
* 为 consumables 表添加 version 字段 * 为 consumables 表添加 version 字段
*/ */
require('dotenv').config();
const { sequelize, dbDialect } = require('../db'); const { sequelize, dbDialect } = require('../db');
// 从环境变量重新确定数据库类型
const actualDbType = process.env.DB_TYPE || 'sqlite';
async function migrate() { async function migrate() {
try { try {
console.log('开始执行耗材乐观锁迁移...'); console.log('开始执行耗材乐观锁迁移...');
console.log('数据库类型:', dbDialect); console.log('数据库类型:', actualDbType);
if (dbDialect === 'sqlite') { if (actualDbType === 'sqlite') {
// SQLite: 检查字段是否存在 // SQLite: 检查字段是否存在
const tableInfo = await sequelize.query( const tableInfo = await sequelize.query(
"PRAGMA table_info(consumables)", "PRAGMA table_info(consumables)",
@@ -47,7 +51,7 @@ async function migrate() {
console.log('updatedAt 索引已存在,跳过'); console.log('updatedAt 索引已存在,跳过');
} }
} else if (dbDialect === 'mysql') { } else if (actualDbType === 'mysql') {
// MySQL: 检查并添加字段 // MySQL: 检查并添加字段
try { try {
console.log('添加 version 字段...'); console.log('添加 version 字段...');
+10 -3
View File
@@ -226,9 +226,16 @@ function ConsumableStatistics() {
}; };
useEffect(() => { useEffect(() => {
fetchSummary(); const loadData = async () => {
fetchLowStock(); setLoading(true);
fetchInOutStats(); await Promise.all([
fetchSummary(),
fetchLowStock(),
fetchInOutStats()
]);
setLoading(false);
};
loadData();
}, []); }, []);
useEffect(() => { useEffect(() => {