版本变更V3.34将图像的处理统一更换到新表当中

This commit is contained in:
dxc
2026-05-26 08:57:41 +08:00
parent e564c5a5d2
commit 682139bab8
5 changed files with 101 additions and 33 deletions

View File

@ -12,7 +12,9 @@ import traceback
import json import json
import io import io
import datetime import datetime
import numpy as np
from app.utils.ai_vision import extract_and_embed from app.utils.ai_vision import extract_and_embed
from app.services.image_embedding_service import ImageEmbeddingService
# 需要 pip install openpyxl # 需要 pip install openpyxl
from openpyxl import Workbook from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
@ -556,10 +558,15 @@ class MaterialBaseService:
product_image=json.dumps(data.get('generalImage', [])), product_image=json.dumps(data.get('generalImage', [])),
is_enabled=is_enabled_val is_enabled=is_enabled_val
) )
# 实时提取产品图向量(失败不影响业务)
if new_material.product_image:
new_material.img_embedding = extract_and_embed(new_material.product_image)
db.session.add(new_material) db.session.add(new_material)
db.session.flush() # 获取 new_material.id
# 提取产品图向量到独立表(失败不影响业务)
image_list = data.get('generalImage', [])
if isinstance(image_list, list) and image_list:
ImageEmbeddingService.save_embeddings(
ImageEmbeddingService.MODULE_MATERIAL_BASE, new_material.id, image_list
)
db.session.commit() db.session.commit()
return new_material return new_material
@ -588,11 +595,17 @@ class MaterialBaseService:
if 'generalManual' in data: if 'generalManual' in data:
material.manual_link = json.dumps(data['generalManual']) material.manual_link = json.dumps(data['generalManual'])
if 'generalImage' in data: if 'generalImage' in data:
material.product_image = json.dumps(data['generalImage']) new_photo_list = data['generalImage']
material.product_image = json.dumps(new_photo_list)
# 补上这两行:提取新上传图片的向量! # 保存向量到独立表(全量替换)
if material.product_image: ImageEmbeddingService.save_embeddings(
material.img_embedding = extract_and_embed(material.product_image) ImageEmbeddingService.MODULE_MATERIAL_BASE, material.id, new_photo_list
)
else:
material.product_image = None
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_MATERIAL_BASE, material.id
)
# 【核心修改】:兼容前端传来的布尔值 # 【核心修改】:兼容前端传来的布尔值
if 'isEnabled' in data: if 'isEnabled' in data:
@ -659,6 +672,10 @@ class MaterialBaseService:
f"请先清理相关库存或仅‘禁用’此条目。" f"请先清理相关库存或仅‘禁用’此条目。"
) )
# 删除时同步清理向量记录
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_MATERIAL_BASE, material.id
)
db.session.delete(material) db.session.delete(material)
db.session.commit() db.session.commit()
return material_name return material_name

View File

@ -9,7 +9,9 @@ from sqlalchemy import or_, func, text, and_
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
import traceback import traceback
import json import json
import numpy as np
from app.utils.ai_vision import extract_and_embed from app.utils.ai_vision import extract_and_embed
from app.services.image_embedding_service import ImageEmbeddingService
class BuyInboundService: class BuyInboundService:
@ -178,10 +180,15 @@ class BuyInboundService:
arrival_photo=json.dumps(data.get('arrival_photo', [])), arrival_photo=json.dumps(data.get('arrival_photo', [])),
inspection_report=json.dumps(data.get('inspection_report', [])) inspection_report=json.dumps(data.get('inspection_report', []))
) )
# 实时提取到货图片向量(失败不影响业务)
if new_stock.arrival_photo:
new_stock.arrival_image_embedding = extract_and_embed(new_stock.arrival_photo)
db.session.add(new_stock) db.session.add(new_stock)
db.session.flush() # 获取 new_stock.id
# 提取到货图片向量到新表(失败不影响业务)
photo_list = data.get('arrival_photo', [])
if isinstance(photo_list, list) and photo_list:
ImageEmbeddingService.save_embeddings(
ImageEmbeddingService.MODULE_STOCK_BUY, new_stock.id, photo_list
)
db.session.commit() db.session.commit()
return new_stock return new_stock
except Exception as e: except Exception as e:
@ -244,9 +251,19 @@ class BuyInboundService:
for k, v in field_mapping.items(): for k, v in field_mapping.items():
if k in data: setattr(stock, v, data[k]) if k in data: setattr(stock, v, data[k])
if 'arrival_photo' in data: stock.arrival_photo = json.dumps(data['arrival_photo']) if 'arrival_photo' in data:
if 'arrival_photo' in data and stock.arrival_photo: new_photo_list = data['arrival_photo']
stock.arrival_image_embedding = extract_and_embed(stock.arrival_photo) stock.arrival_photo = json.dumps(new_photo_list)
# 保存向量到独立表(全量替换)
ImageEmbeddingService.save_embeddings(
ImageEmbeddingService.MODULE_STOCK_BUY, stock.id, new_photo_list
)
else:
stock.arrival_photo = None
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_STOCK_BUY, stock.id
)
if 'inspection_report' in data: stock.inspection_report = json.dumps(data['inspection_report']) if 'inspection_report' in data: stock.inspection_report = json.dumps(data['inspection_report'])
# 更新税率 # 更新税率
@ -289,8 +306,11 @@ class BuyInboundService:
try: try:
stock = StockBuy.query.get(stock_id) stock = StockBuy.query.get(stock_id)
if not stock: raise ValueError("记录不存在") if not stock: raise ValueError("记录不存在")
# 提前获取物料名称用于审计日志(通过外键关系 base.name 获取)
material_name = stock.base.name if stock.base else '未知物料' material_name = stock.base.name if stock.base else '未知物料'
# 删除时同步清理向量记录
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_STOCK_BUY, stock.id
)
db.session.delete(stock) db.session.delete(stock)
db.session.commit() db.session.commit()
return material_name return material_name

View File

@ -9,7 +9,9 @@ from sqlalchemy import or_, func, text, and_
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
import traceback import traceback
import json import json
import numpy as np
from app.utils.ai_vision import extract_and_embed from app.utils.ai_vision import extract_and_embed
from app.services.image_embedding_service import ImageEmbeddingService
class ProductInboundService: class ProductInboundService:
@ -184,10 +186,14 @@ class ProductInboundService:
sale_price=float(data.get('sale_price') or 0), sale_price=float(data.get('sale_price') or 0),
order_id=data.get('order_id') order_id=data.get('order_id')
) )
# 实时提取成品实拍图向量(失败不影响业务)
if new_stock.product_photo:
new_stock.arrival_image_embedding = extract_and_embed(new_stock.product_photo)
db.session.add(new_stock) db.session.add(new_stock)
db.session.flush() # 获取 new_stock.id
# 提取产品图片向量到独立表(失败不影响业务)
if isinstance(photo_list, list) and photo_list:
ImageEmbeddingService.save_embeddings(
ImageEmbeddingService.MODULE_STOCK_PRODUCT, new_stock.id, photo_list
)
db.session.commit() db.session.commit()
return new_stock return new_stock
except Exception as e: except Exception as e:
@ -217,10 +223,17 @@ class ProductInboundService:
if f in data: setattr(stock, f, data[f]) if f in data: setattr(stock, f, data[f])
if 'product_photo' in data: if 'product_photo' in data:
imgs = data['product_photo'] new_photo_list = data['product_photo']
if isinstance(imgs, list): stock.product_photo = json.dumps(imgs) stock.product_photo = json.dumps(new_photo_list)
if stock.product_photo: # 保存向量到独立表(全量替换)
stock.arrival_image_embedding = extract_and_embed(stock.product_photo) ImageEmbeddingService.save_embeddings(
ImageEmbeddingService.MODULE_STOCK_PRODUCT, stock.id, new_photo_list
)
else:
stock.product_photo = None
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_STOCK_PRODUCT, stock.id
)
if 'quality_report_link' in data: if 'quality_report_link' in data:
imgs = data['quality_report_link'] imgs = data['quality_report_link']
if isinstance(imgs, list): stock.quality_report_link = json.dumps(imgs) if isinstance(imgs, list): stock.quality_report_link = json.dumps(imgs)
@ -261,8 +274,11 @@ class ProductInboundService:
try: try:
stock = StockProduct.query.get(stock_id) stock = StockProduct.query.get(stock_id)
if stock: if stock:
# 提前获取物料名称用于审计日志(通过外键关系 base.name 获取)
material_name = stock.base.name if stock.base else '未知物料' material_name = stock.base.name if stock.base else '未知物料'
# 删除时同步清理向量记录
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_STOCK_PRODUCT, stock.id
)
db.session.delete(stock) db.session.delete(stock)
db.session.commit() db.session.commit()
return material_name return material_name

View File

@ -9,7 +9,9 @@ from sqlalchemy import or_, func, text, and_
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
import traceback import traceback
import json import json
import numpy as np
from app.utils.ai_vision import extract_and_embed from app.utils.ai_vision import extract_and_embed
from app.services.image_embedding_service import ImageEmbeddingService
class SemiInboundService: class SemiInboundService:
@ -221,10 +223,14 @@ class SemiInboundService:
detail_link=data.get('detail_link'), detail_link=data.get('detail_link'),
remark=data.get('remark') remark=data.get('remark')
) )
# 实时提取到货图片向量(失败不影响业务)
if new_stock.arrival_photo:
new_stock.arrival_image_embedding = extract_and_embed(new_stock.arrival_photo)
db.session.add(new_stock) db.session.add(new_stock)
db.session.flush() # 获取 new_stock.id
# 提取到货图片向量到独立表(失败不影响业务)
if isinstance(arrival_list, list) and arrival_list:
ImageEmbeddingService.save_embeddings(
ImageEmbeddingService.MODULE_STOCK_SEMI, new_stock.id, arrival_list
)
db.session.commit() db.session.commit()
return new_stock return new_stock
except Exception as e: except Exception as e:
@ -272,11 +278,17 @@ class SemiInboundService:
setattr(stock, db_attr, data[frontend_key]) setattr(stock, db_attr, data[frontend_key])
if 'arrival_photo' in data: if 'arrival_photo' in data:
imgs = data['arrival_photo'] new_photo_list = data['arrival_photo']
if isinstance(imgs, list): stock.arrival_photo = json.dumps(new_photo_list)
stock.arrival_photo = json.dumps(imgs) # 保存向量到独立表(全量替换)
if stock.arrival_photo: ImageEmbeddingService.save_embeddings(
stock.arrival_image_embedding = extract_and_embed(stock.arrival_photo) ImageEmbeddingService.MODULE_STOCK_SEMI, stock.id, new_photo_list
)
else:
stock.arrival_photo = None
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_STOCK_SEMI, stock.id
)
if 'quality_report_link' in data: if 'quality_report_link' in data:
imgs = data['quality_report_link'] imgs = data['quality_report_link']
if isinstance(imgs, list): if isinstance(imgs, list):
@ -350,8 +362,11 @@ class SemiInboundService:
stock = StockSemi.query.get(stock_id) stock = StockSemi.query.get(stock_id)
if not stock: if not stock:
raise ValueError("记录不存在") raise ValueError("记录不存在")
# 提前获取物料名称用于审计日志(通过外键关系 base.name 获取)
material_name = stock.base.name if stock.base else '未知物料' material_name = stock.base.name if stock.base else '未知物料'
# 删除时同步清理向量记录
ImageEmbeddingService.delete_embeddings(
ImageEmbeddingService.MODULE_STOCK_SEMI, stock.id
)
db.session.delete(stock) db.session.delete(stock)
db.session.commit() db.session.commit()
return material_name return material_name

View File

@ -239,7 +239,7 @@ const handleLogout = () => {
<footer v-if="!isLoginPage" class="app-footer"> <footer v-if="!isLoginPage" class="app-footer">
<span class="version-tag"> <span class="version-tag">
<el-icon style="vertical-align: middle; margin-right: 4px"><InfoFilled /></el-icon> <el-icon style="vertical-align: middle; margin-right: 4px"><InfoFilled /></el-icon>
当前版本:V3.33识图版 当前版本:V3.34识图版
</span> </span>
</footer> </footer>