diff --git a/inventory-backend/app/api/v1/inbound/semi.py b/inventory-backend/app/api/v1/inbound/semi.py index 1939d56..86c7bb4 100644 --- a/inventory-backend/app/api/v1/inbound/semi.py +++ b/inventory-backend/app/api/v1/inbound/semi.py @@ -75,7 +75,38 @@ def get_list(): keyword = request.args.get('keyword', '') statuses_str = request.args.get('statuses', '') statuses = statuses_str.split(',') if statuses_str else [] - result = SemiInboundService.get_list(page, limit, keyword, statuses) + company = request.args.get('company', '') + category = request.args.get('category', '') + material_type = request.args.get('material_type', '') + order_by_column = request.args.get('orderByColumn', '') + is_asc = request.args.get('isAsc', '') + advanced_filters_str = request.args.get('advancedFilters', '') + + # 准备额外筛选字典 + extra_filters = {} + if company: + extra_filters['company'] = company + if category: + extra_filters['category'] = category + if material_type: + extra_filters['material_type'] = material_type + if order_by_column: + extra_filters['order_by_column'] = order_by_column + if is_asc: + extra_filters['is_asc'] = is_asc + if advanced_filters_str: + try: + import json + advanced_filters = json.loads(advanced_filters_str) + extra_filters['advanced_filters'] = advanced_filters + except Exception: + extra_filters['advanced_filters'] = [] + + # 调用服务,传入所有参数 + result = SemiInboundService.get_list( + page, limit, keyword, statuses, + **extra_filters + ) user_permissions = get_current_user_permissions() if result.get('items'): result['items'] = [filter_item_by_permissions(item, user_permissions) for item in result['items']] @@ -181,4 +212,4 @@ def calculate_bom_cost(): return jsonify({"code": 200, "msg": "success", "data": cost}) except Exception as e: traceback.print_exc() - return jsonify({"code": 500, "msg": str(e)}), 500 \ No newline at end of file + return jsonify({"code": 500, "msg": str(e)}), 500 diff --git a/inventory-backend/app/services/inbound/semi_service.py b/inventory-backend/app/services/inbound/semi_service.py index e4462c5..8abf6e1 100644 --- a/inventory-backend/app/services/inbound/semi_service.py +++ b/inventory-backend/app/services/inbound/semi_service.py @@ -343,7 +343,8 @@ class SemiInboundService: return [] @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_column=None, is_asc=None, advanced_filters=None): from app.models.inbound.semi import StockSemi try: query = db.session.query(StockSemi).outerjoin(MaterialBase, StockSemi.base_id == MaterialBase.id) @@ -380,11 +381,108 @@ class SemiInboundService: StockSemi.stock_quantity > 0 ) ) - pagination = query.order_by(StockSemi.production_date.desc()).paginate(page=page, per_page=limit, - error_out=False) + + # 动态高级筛选 + if advanced_filters: + if isinstance(advanced_filters, str): + try: + import json + advanced_filters = json.loads(advanced_filters) + except: + advanced_filters = [] + if isinstance(advanced_filters, list): + field_mapping = { + 'company_name': MaterialBase.company_name, + 'material_name': MaterialBase.name, + 'spec_model': MaterialBase.spec_model, + 'category': MaterialBase.category, + 'material_type': MaterialBase.material_type, + 'status': StockSemi.status, + 'quality_status': StockSemi.quality_status, + 'warehouse_location': StockSemi.warehouse_location, + 'bom_code': StockSemi.bom_code, + 'work_order_code': StockSemi.work_order_code, + 'qty_stock': StockSemi.stock_quantity, + 'qty_available': StockSemi.available_quantity, + 'unit_total_cost': StockSemi.manual_cost, + 'raw_material_cost': StockSemi.raw_material_cost, + } + for cond in advanced_filters: + field = cond.get('field') + operator = cond.get('operator') + value = cond.get('value') + if not field or not operator: + continue + model_field = field_mapping.get(field) + if model_field is None: + continue + # 防止 SQL 注入,只允许映射的字段 + if operator == '=': + query = query.filter(model_field == value) + elif operator == '!=': + query = query.filter(model_field != value) + elif operator == 'like': + query = query.filter(model_field.ilike(f'%{value}%')) + elif operator == 'not_like': + query = query.filter(~model_field.ilike(f'%{value}%')) + elif operator == '>': + if value.replace('.', '', 1).isdigit(): + query = query.filter(model_field > float(value)) + elif operator == '<': + if value.replace('.', '', 1).isdigit(): + query = query.filter(model_field < float(value)) + elif operator == '>=': + if value.replace('.', '', 1).isdigit(): + query = query.filter(model_field >= float(value)) + elif operator == '<=': + if value.replace('.', '', 1).isdigit(): + query = query.filter(model_field <= float(value)) + + # 动态排序 + order_field = None + if order_by_column and is_asc is not None: + order_mapping = { + 'id': StockSemi.id, + 'base_id': StockSemi.base_id, + 'company_name': MaterialBase.company_name, + 'material_name': MaterialBase.name, + 'category': MaterialBase.category, + 'material_type': MaterialBase.material_type, + 'spec_model': MaterialBase.spec_model, + 'unit': MaterialBase.unit, + 'sku': StockSemi.sku, + 'inbound_date': StockSemi.production_date, + 'barcode': StockSemi.barcode, + 'serial_number': StockSemi.serial_number, + 'batch_number': StockSemi.batch_number, + 'status': StockSemi.status, + 'quality_status': StockSemi.quality_status, + 'qty_inbound': StockSemi.in_quantity, + 'qty_stock': StockSemi.stock_quantity, + 'qty_available': StockSemi.available_quantity, + 'warehouse_loc': StockSemi.warehouse_location, + 'bom_code': StockSemi.bom_code, + 'bom_version': StockSemi.bom_version, + 'work_order_code': StockSemi.work_order_code, + 'raw_material_cost': StockSemi.raw_material_cost, + 'unit_total_cost': StockSemi.manual_cost, + 'total_price': StockSemi.total_price, + 'production_manager': StockSemi.production_manager, + 'production_start_time': StockSemi.production_start_time, + 'production_end_time': StockSemi.production_end_time, + } + order_field = order_mapping.get(order_by_column) + if order_field is not None: + if is_asc == 'true' or is_asc == True: + query = query.order_by(order_field.asc()) + else: + query = query.order_by(order_field.desc()) + if order_field is None: + query = query.order_by(StockSemi.production_date.desc()) + + pagination = query.paginate(page=page, per_page=limit, error_out=False) items = [] for item in pagination.items: - # 把 manual_cost 伪装成 unit_total_cost 返回给前端 item_dict = item.to_dict() item_dict['unit_total_cost'] = float(item.manual_cost or 0) items.append(item_dict) diff --git a/inventory-web/src/views/stock/inbound/semi.vue b/inventory-web/src/views/stock/inbound/semi.vue index bbb91f0..a6e0322 100644 --- a/inventory-web/src/views/stock/inbound/semi.vue +++ b/inventory-web/src/views/stock/inbound/semi.vue @@ -54,6 +54,36 @@ 搜索 重置 + + +
+
+ + + + + + + + 删除 +
+
+ 添加条件 +
+ 重置 + 应用 +
+
+
+
+