diff --git a/inventory-backend/app/api/v1/inbound/buy.py b/inventory-backend/app/api/v1/inbound/buy.py
index ec8b85f..f6c0604 100644
--- a/inventory-backend/app/api/v1/inbound/buy.py
+++ b/inventory-backend/app/api/v1/inbound/buy.py
@@ -106,7 +106,7 @@ def search_base():
# ------------------------------------------------------------------
-# 1. 获取列表 (修改:接收 category 和 material_type)
+# 1. 获取列表 (修改:接收 category, material_type, orderByColumn, isAsc, advancedFilters)
# ------------------------------------------------------------------
@inbound_buy_bp.route('/list', methods=['GET'])
@permission_required('inbound_buy')
@@ -121,11 +121,24 @@ def get_list():
material_type = request.args.get('material_type', '')
company = request.args.get('company', '')
+ # 排序参数
+ order_by = request.args.get('orderByColumn', '').strip()
+ is_asc = request.args.get('isAsc', '').strip()
+
+ # 高级筛选参数
+ advanced_filters_raw = request.args.get('advancedFilters', '[]')
+ import json
+ try:
+ advanced_filters = json.loads(advanced_filters_raw) if advanced_filters_raw else []
+ except json.JSONDecodeError:
+ advanced_filters = []
+
# 状态参数处理
statuses_str = request.args.get('statuses', '')
statuses = statuses_str.split(',') if statuses_str else []
- result = BuyInboundService.get_list(page, limit, keyword, statuses, category, material_type, company)
+ result = BuyInboundService.get_list(page, limit, keyword, statuses, category, material_type, company,
+ order_by, is_asc, advanced_filters)
# 字段级脱敏
user_permissions = get_current_user_permissions()
if result.get('items'):
diff --git a/inventory-backend/app/services/inbound/buy_service.py b/inventory-backend/app/services/inbound/buy_service.py
index 83bc411..77e3210 100644
--- a/inventory-backend/app/services/inbound/buy_service.py
+++ b/inventory-backend/app/services/inbound/buy_service.py
@@ -237,11 +237,13 @@ class BuyInboundService:
raise e
# ============================================================
- # 5. 获取列表
+ # 5. 获取列表 (支持排序和高级筛选)
# ============================================================
@staticmethod
- def get_list(page, limit, keyword=None, statuses=None, category=None, material_type=None, company=None):
+ def get_list(page, limit, keyword=None, statuses=None, category=None, material_type=None, company=None,
+ order_by='', is_asc='', advanced_filters=None):
try:
+ from sqlalchemy import and_, or_
query = db.session.query(StockBuy).outerjoin(MaterialBase, StockBuy.base_id == MaterialBase.id)
# 1. 通用关键词搜索
@@ -279,7 +281,109 @@ class BuyInboundService:
else:
query = query.filter(and_(StockBuy.status.in_(statuses), StockBuy.stock_quantity > 0))
- pagination = query.order_by(StockBuy.in_date.desc()).paginate(page=page, per_page=limit, error_out=False)
+ # 5. 高级动态筛选
+ if advanced_filters:
+ allowed_fields = {
+ 'company_name': MaterialBase.company_name,
+ 'material_name': MaterialBase.name,
+ 'material_type': MaterialBase.material_type,
+ 'category': MaterialBase.category,
+ 'spec_model': MaterialBase.spec_model,
+ 'unit': MaterialBase.unit,
+ 'sku': StockBuy.sku,
+ 'barcode': StockBuy.barcode,
+ 'batch_number': StockBuy.batch_number,
+ 'serial_number': StockBuy.serial_number,
+ 'warehouse_location': StockBuy.warehouse_location,
+ 'status': StockBuy.status,
+ 'inspection_status': StockBuy.inspection_status,
+ 'qty_inbound': StockBuy.in_quantity,
+ 'qty_stock': StockBuy.stock_quantity,
+ 'qty_available': StockBuy.available_quantity,
+ 'unit_price': StockBuy.pre_tax_unit_price,
+ 'total_price': StockBuy.total_price,
+ 'tax_rate': StockBuy.tax_rate,
+ 'currency': StockBuy.currency,
+ 'exchange_rate': StockBuy.exchange_rate,
+ 'supplier_name': StockBuy.supplier_name,
+ 'purchaser': StockBuy.buyer_name,
+ 'purchaser_email': StockBuy.buyer_email,
+ 'source_link': StockBuy.original_link,
+ 'detail_link': StockBuy.detail_link,
+ }
+ filter_conditions = []
+ for condition in advanced_filters:
+ field = condition.get('field')
+ operator = condition.get('operator')
+ value = condition.get('value')
+ if not field or not operator or value is None:
+ continue
+ column = allowed_fields.get(field)
+ if column is None:
+ continue
+ if operator == 'eq':
+ filter_conditions.append(column == value)
+ elif operator == 'ne':
+ filter_conditions.append(column != value)
+ elif operator == 'contains':
+ filter_conditions.append(column.ilike(f'%{value}%'))
+ elif operator == 'ge':
+ try:
+ num_val = float(value)
+ filter_conditions.append(column >= num_val)
+ except ValueError:
+ continue
+ elif operator == 'le':
+ try:
+ num_val = float(value)
+ filter_conditions.append(column <= num_val)
+ except ValueError:
+ continue
+ if filter_conditions:
+ query = query.filter(and_(*filter_conditions))
+
+ # 6. 排序处理
+ if order_by:
+ sort_field_map = {
+ 'company_name': MaterialBase.company_name,
+ 'material_name': MaterialBase.name,
+ 'material_type': MaterialBase.material_type,
+ 'category': MaterialBase.category,
+ 'spec_model': MaterialBase.spec_model,
+ 'unit': MaterialBase.unit,
+ 'sku': StockBuy.sku,
+ 'barcode': StockBuy.barcode,
+ 'inbound_date': StockBuy.in_date,
+ 'serial_number': StockBuy.serial_number,
+ 'batch_number': StockBuy.batch_number,
+ 'status': StockBuy.status,
+ 'inspection_status': StockBuy.inspection_status,
+ 'qty_inbound': StockBuy.in_quantity,
+ 'qty_stock': StockBuy.stock_quantity,
+ 'qty_available': StockBuy.available_quantity,
+ 'warehouse_loc': StockBuy.warehouse_location,
+ 'unit_price': StockBuy.pre_tax_unit_price,
+ 'total_price': StockBuy.total_price,
+ 'tax_rate': StockBuy.tax_rate,
+ 'currency': StockBuy.currency,
+ 'exchange_rate': StockBuy.exchange_rate,
+ 'supplier_name': StockBuy.supplier_name,
+ 'purchaser': StockBuy.buyer_name,
+ 'purchaser_email': StockBuy.buyer_email,
+ 'source_link': StockBuy.original_link,
+ 'detail_link': StockBuy.detail_link,
+ }
+ column = sort_field_map.get(order_by)
+ if column:
+ if is_asc == 'asc':
+ query = query.order_by(column.asc())
+ elif is_asc == 'desc':
+ query = query.order_by(column.desc())
+ else:
+ # 默认排序
+ query = query.order_by(StockBuy.in_date.desc())
+
+ pagination = query.paginate(page=page, per_page=limit, error_out=False)
items = []
for item in pagination.items:
items.append(item.to_dict()) # 直接使用 model 的 to_dict
diff --git a/inventory-web/src/views/stock/inbound/buy.vue b/inventory-web/src/views/stock/inbound/buy.vue
index bc61c67..4866f13 100644
--- a/inventory-web/src/views/stock/inbound/buy.vue
+++ b/inventory-web/src/views/stock/inbound/buy.vue
@@ -53,6 +53,33 @@