diff --git a/deploy_code.sh b/deploy_code.sh old mode 100755 new mode 100644 index 5b0300b..e5899ac --- a/deploy_code.sh +++ b/deploy_code.sh @@ -16,9 +16,16 @@ echo "[1/4] 正在服务器上急救环境并备份旧代码 (可能需要输入 ssh -t $SERVER "sudo mkdir -p $REMOTE_BACKUP_DIR && \ cd $REMOTE_DIR && \ echo '>> 检查并修复缺失目录 (防止 tar 崩溃)...' && \ - sudo mkdir -p inventory-backend inventory-web && \ + sudo mkdir -p inventory-backend inventory-web models_prod && \ echo '>> 执行代码备份...' && \ sudo tar -czf $REMOTE_BACKUP_DIR/code_backup.tar.gz inventory-backend inventory-web docker-compose.prod.yml && \ + echo '>> 检查 CLIP 模型文件...' && \ + if [ ! -f models_prod/clip_vision.onnx ]; then \ + echo '⚠️ 警告: models_prod/clip_vision.onnx 不存在!拍照识图功能将无法使用。'; \ + echo '⚠️ 请手动上传: scp inventory-backend/models/clip_vision.onnx ${SERVER}:${REMOTE_DIR}/models_prod/'; \ + else \ + echo '✅ CLIP 模型文件已存在'; \ + fi && \ echo '>> 执行清理:仅保留 data_copy 下最新的 2 个备份...' && \ cd $REMOTE_BACKUP_BASE && \ sudo sh -c 'ls -dt */ 2>/dev/null | tail -n +3 | xargs -I {} rm -rf {} || true'" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 2490e21..3c9acbb 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -25,6 +25,7 @@ services: - "8000" volumes: - ./uploads_prod:/app/uploads + - ./models_prod:/app/models command: gunicorn -c gunicorn.conf.py run:app environment: DATABASE_URL: postgresql://prod_user:StrongPassword123!@db:5432/inventory_system diff --git a/inventory-backend/app/api/v1/inbound/base.py b/inventory-backend/app/api/v1/inbound/base.py index 57d169a..5d7ed86 100644 --- a/inventory-backend/app/api/v1/inbound/base.py +++ b/inventory-backend/app/api/v1/inbound/base.py @@ -43,6 +43,7 @@ def get_current_user_permissions(): 'material_list:availableCount', 'material_list:files', 'material_list:isEnabled', + 'material_list:referencePrice', 'material_list:operation' ] perm_dict = AuthService.get_user_permissions(user_role, company_name=user_company) @@ -72,6 +73,7 @@ def filter_item_by_permissions(item_dict, user_permissions): 'availableCount': 'material_list:availableCount', 'generalManual': 'material_list:files', 'generalImage': 'material_list:files', + 'referencePrice': 'material_list:referencePrice', 'isEnabled': 'material_list:isEnabled' } for field, perm_code in field_to_perm.items(): @@ -252,6 +254,7 @@ def create(): 'availableCount': 'material_list:availableCount', 'generalManual': 'material_list:files', 'generalImage': 'material_list:files', + 'referencePrice': 'material_list:referencePrice', 'isEnabled': 'material_list:isEnabled' } # 过滤用户没有权限的字段 @@ -311,6 +314,7 @@ def update(id): 'availableCount': 'material_list:availableCount', 'generalManual': 'material_list:files', 'generalImage': 'material_list:files', + 'referencePrice': 'material_list:referencePrice', 'isEnabled': 'material_list:isEnabled' } # 过滤用户没有权限的字段 diff --git a/inventory-backend/app/models/base.py b/inventory-backend/app/models/base.py index 8c95474..ba4cf24 100644 --- a/inventory-backend/app/models/base.py +++ b/inventory-backend/app/models/base.py @@ -39,6 +39,9 @@ class MaterialBase(db.Model): # 强制质检标记(采购入库时必须上传检测报告) is_inspection_required = db.Column(db.Boolean, default=False, comment='是否强制要求质检') + # 参考价格 + reference_price = db.Column(db.Numeric(10, 2), nullable=True, comment='参考价格') + # CLIP 视觉向量(用于以图搜图) img_embedding = db.Column(Vector(512), nullable=True) @@ -96,6 +99,8 @@ class MaterialBase(db.Model): 'isEnabled': bool(self.is_enabled), # 强制质检标记 'isInspectionRequired': bool(self.is_inspection_required), + # 参考价格 + 'referencePrice': float(self.reference_price) if self.reference_price is not None else None, } diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py index e336320..ad15e0b 100644 --- a/inventory-backend/app/services/inbound/base_service.py +++ b/inventory-backend/app/services/inbound/base_service.py @@ -259,6 +259,7 @@ class MaterialBaseService: 'type': 'material_type', 'spec': 'spec_model', 'unit': 'unit', + 'referencePrice': 'reference_price', 'inventoryCount': 'total_inv', 'availableCount': 'total_avail' } @@ -273,6 +274,7 @@ class MaterialBaseService: 'type': 'material_list:type', 'spec': 'material_list:spec', 'unit': 'material_list:unit', + 'referencePrice': 'material_list:referencePrice', 'inventoryCount': 'material_list:inventoryCount', 'availableCount': 'material_list:availableCount' } @@ -390,6 +392,7 @@ class MaterialBaseService: 'type': MaterialBase.material_type, 'spec': MaterialBase.spec_model, 'unit': MaterialBase.unit, + 'referencePrice': MaterialBase.reference_price, 'inventoryCount': inner_sub.c.total_inv, 'availableCount': inner_sub.c.total_avail } @@ -556,6 +559,7 @@ class MaterialBaseService: product_image=json.dumps(data.get('generalImage', [])), product_image_remark=data.get('productImageRemark', ''), manual_link_remark=data.get('manualLinkRemark', ''), + reference_price=data.get('referencePrice'), is_enabled=is_enabled_val ) db.session.add(new_material) @@ -625,6 +629,9 @@ class MaterialBaseService: ) # 【核心修改】:兼容前端传来的布尔值 + if 'referencePrice' in data: + material.reference_price = data['referencePrice'] + if 'isEnabled' in data: raw_enabled = data['isEnabled'] material.is_enabled = str(raw_enabled).lower() in ['1', 'true', 'yes', 't'] diff --git a/inventory-web/src/views/material/buyOdoo.vue b/inventory-web/src/views/material/buyOdoo.vue index 389edc0..aa9b408 100644 --- a/inventory-web/src/views/material/buyOdoo.vue +++ b/inventory-web/src/views/material/buyOdoo.vue @@ -21,6 +21,7 @@ + @@ -194,6 +196,7 @@ + @@ -330,6 +333,12 @@ + + +