Sfoglia il codice sorgente

更新优化产品方案二维码功能

zhangdongming 2 settimane fa
parent
commit
06768faa44

+ 170 - 31
AdminController/ProductsSchemeManageController.py

@@ -14,13 +14,14 @@ import time
 from io import BytesIO
 from io import BytesIO
 
 
 import qrcode
 import qrcode
+from PIL import Image, ImageDraw, ImageFont
 from django.core.paginator import Paginator, EmptyPage
 from django.core.paginator import Paginator, EmptyPage
 from django.db import transaction, IntegrityError
 from django.db import transaction, IntegrityError
 from django.db.models import Q
 from django.db.models import Q
 from django.http import QueryDict, HttpResponse
 from django.http import QueryDict, HttpResponse
 from django.views import View
 from django.views import View
 
 
-from Ansjer.config import LOGGER
+from Ansjer.config import LOGGER, BASE_DIR
 from Model.models import ProductsScheme, DeviceScheme, DeviceTypeModel, CompanySerialModel
 from Model.models import ProductsScheme, DeviceScheme, DeviceTypeModel, CompanySerialModel
 from Object.ResponseObject import ResponseObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.TokenObject import TokenObject
@@ -78,7 +79,10 @@ class ProductsSchemeManageView(View):
             'edit': self.edit_scheme,  # 编辑方案
             'edit': self.edit_scheme,  # 编辑方案
             'delete': self.delete_scheme,  # 删除方案
             'delete': self.delete_scheme,  # 删除方案
             'generateQR': self.generate_qr_code,  # 生成二维码
             'generateQR': self.generate_qr_code,  # 生成二维码
-            'deviceSchemeList': self.device_scheme_list
+            'deviceSchemeList': self.device_scheme_list,  # 设备方案列表
+            'batchAddScheme': self.batch_add_scheme,  # 批量添加
+            'getSkuList': self.get_sku_list,  # 获取SKU列表'
+            'getSchemeBySku': self.get_scheme_by_sku,  # 根据SKU获取方案
         }
         }
 
 
         handler = operation_handlers.get(operation)
         handler = operation_handlers.get(operation)
@@ -188,7 +192,7 @@ class ProductsSchemeManageView(View):
                 'remark': request_dict.get('remark', ''),
                 'remark': request_dict.get('remark', ''),
                 'sku': request_dict.get('sku', ''),
                 'sku': request_dict.get('sku', ''),
                 'scheme_code': request_dict.get('schemeCode', ''),
                 'scheme_code': request_dict.get('schemeCode', ''),
-                'hw_version':request_dict.get('hwVersion', ''),
+                'hw_version': request_dict.get('hwVersion', ''),
                 'created_time': int(time.time()),
                 'created_time': int(time.time()),
                 'updated_time': int(time.time()),
                 'updated_time': int(time.time()),
                 'created_by': user_id,
                 'created_by': user_id,
@@ -210,6 +214,88 @@ class ProductsSchemeManageView(View):
             LOGGER.exception(f"添加方案异常:{repr(e)}")
             LOGGER.exception(f"添加方案异常:{repr(e)}")
             return response.json(500, "生成编码失败")
             return response.json(500, "生成编码失败")
 
 
+    def batch_add_scheme(self, user_id, request_dict, response):
+        """批量新增方案(支持批量处理,集成自动编码生成)"""
+        try:
+            # 获取批量方案数据数组
+            schemes_array = request_dict.get('schemes', [])
+            order_number = request_dict.get('orderNumber', '')
+            if not order_number:
+                return response.json(444, "请提供有效的方案数据数组")
+
+            # 准备批量创建的数据列表
+            batch_data = []
+            result_ids = []
+            current_time = int(time.time())
+            schemes_array = json.loads(schemes_array)
+            for item in schemes_array:
+                # 确保每个项都是字典
+                if not isinstance(item, dict):
+                    continue
+
+                # 生成唯一storage_code
+                device_type = int(item.get('deviceType', 0))
+                storage_code = self.generate_timestamp_code(device_type)
+
+                # 构造单个方案数据
+                scheme_data = {
+                    'storage_code': storage_code,
+                    'order_number': order_number,
+                    'device_type': device_type,
+                    'product_model': int(item.get('productModel', 0)),
+                    'flash': item.get('flash', ''),
+                    'ddr': item.get('ddr', ''),
+                    'main_controller': item.get('mainController', ''),
+                    'wifi': item.get('wifi', ''),
+                    'four_g': item.get('fourG', ''),
+                    'ad': item.get('ad', ''),
+                    'sensor': item.get('sensor', ''),
+                    'order_quantity': int(item.get('orderQuantity', 0)),
+                    'customer_code': item.get('customerCode', ''),
+                    'phy': item.get('phy', ''),
+                    'remark': item.get('remark', ''),
+                    'sku': item.get('sku', ''),
+                    'scheme_code': item.get('schemeCode', ''),
+                    'hw_version': item.get('hwVersion', ''),
+                    'created_time': current_time,
+                    'updated_time': current_time,
+                    'created_by': user_id,
+                    'updated_by': user_id
+                }
+
+                batch_data.append(ProductsScheme(**scheme_data))
+
+            if not batch_data:
+                return response.json(444, "没有有效的方案数据可添加")
+
+            # 批量创建记录
+            created_schemes = ProductsScheme.objects.bulk_create(batch_data)
+
+            # 收集结果
+            result = {
+                'success_count': len(created_schemes),
+                'total_count': len(schemes_array),
+                'schemes': [
+                    {
+                        'id': scheme.id,
+                        'storageCode': scheme.storage_code,
+                        'orderNumber': scheme.order_number
+                    }
+                    for scheme in created_schemes
+                ]
+            }
+
+            return response.json(0, result)
+
+        except IntegrityError as e:
+            LOGGER.error(f"唯一性冲突: {str(e)}")
+            return response.json(173, "部分数据已存在,批量添加失败")
+        except ValueError as e:
+            return response.json(444, f"参数类型错误: {str(e)}")
+        except Exception as e:
+            LOGGER.exception(f"批量添加方案异常:{repr(e)}")
+            return response.json(500, "批量生成编码失败")
+
         # 可编辑字段白名单(前端字段名: 模型字段名)
         # 可编辑字段白名单(前端字段名: 模型字段名)
 
 
     EDITABLE_FIELDS = {
     EDITABLE_FIELDS = {
@@ -229,7 +315,7 @@ class ProductsSchemeManageView(View):
         'sku': 'sku',
         'sku': 'sku',
         'schemeCode': 'scheme_code',
         'schemeCode': 'scheme_code',
         'productModel': 'product_model',
         'productModel': 'product_model',
-        'hwVersion':'hw_version'
+        'hwVersion': 'hw_version'
     }
     }
 
 
     # 需要类型转换的字段配置(字段名: 转换函数)
     # 需要类型转换的字段配置(字段名: 转换函数)
@@ -347,7 +433,7 @@ class ProductsSchemeManageView(View):
         """方案对象序列化(优化点:集中管理序列化逻辑)"""
         """方案对象序列化(优化点:集中管理序列化逻辑)"""
         # 定义需要包含在str_schema中的字段
         # 定义需要包含在str_schema中的字段
         schema_fields = [
         schema_fields = [
-            'order_number','hw_version', 'main_controller', 'sensor', 'ad', 'wifi', 'four_g',
+            'order_number', 'hw_version', 'main_controller', 'sensor', 'ad', 'wifi', 'four_g',
             'flash', 'ddr', 'phy'
             'flash', 'ddr', 'phy'
         ]
         ]
 
 
@@ -384,12 +470,11 @@ class ProductsSchemeManageView(View):
         }
         }
 
 
     def generate_qr_code(self, user_id, request_dict, response):
     def generate_qr_code(self, user_id, request_dict, response):
-        """生成方案二维码"""
+        """生成方案二维码并附带明文"""
         try:
         try:
             scheme_id = int(request_dict.get('scheme_id'))
             scheme_id = int(request_dict.get('scheme_id'))
             scheme = ProductsScheme.objects.get(id=scheme_id, deleted=False)
             scheme = ProductsScheme.objects.get(id=scheme_id, deleted=False)
 
 
-            # 创建二维码(示例生成包含方案ID+名称)
             qr = qrcode.QRCode(
             qr = qrcode.QRCode(
                 version=1,
                 version=1,
                 error_correction=qrcode.constants.ERROR_CORRECT_L,
                 error_correction=qrcode.constants.ERROR_CORRECT_L,
@@ -397,39 +482,43 @@ class ProductsSchemeManageView(View):
                 border=4,
                 border=4,
             )
             )
 
 
-            # 组织二维码内容(根据业务需求自定义)
-            qr_data = json.dumps({
-                "sc": scheme.storage_code,
-                "t": 'NVR' if scheme.device_type == 1 else 'IPC',
-                "hw": scheme.hw_version,
-                "mc": scheme.main_controller,
-                "s": scheme.sensor,
-                "ad": scheme.ad,
-                "wifi": scheme.wifi,
-                "mode4G": scheme.four_g,
-                "f": scheme.flash,
-                "ddr": scheme.ddr,
-                'uc': scheme.customer_code,
-                'phy': scheme.phy,
-                "num": scheme.order_quantity,
-                "ct": scheme.created_time
-            })
-            qr.add_data(qr_data)
+            qr.add_data(scheme.order_number)
             qr.make(fit=True)
             qr.make(fit=True)
+            img = qr.make_image(fill_color="black", back_color="white").convert("RGB")
 
 
-            # 生成图片
-            img = qr.make_image(fill_color="black", back_color="white")
+            # 要显示的明文(比如 storage_code)
+            text = scheme.order_number
+
+            # 设置字体(如果服务器没有 ttf,可以用默认字体)
+            try:
+                path = BASE_DIR + '/Ansjer/file/font/simhei.ttf'
+                font = ImageFont.truetype(path, 40, encoding="unic")  # 需要系统有 Arial.ttf
+            except IOError:
+                font = ImageFont.load_default()
+
+            # 计算文字大小
+            draw = ImageDraw.Draw(img)
+            text_width, text_height = draw.textsize(text, font=font)
+
+            # 创建一个新图像(比二维码高一些,给文字留空间)
+            new_height = img.height + text_height + 20
+            new_img = Image.new("RGB", (img.width, new_height), "white")
+            new_img.paste(img, (0, 0))
+
+            # 在底部居中绘制文字
+            draw = ImageDraw.Draw(new_img)
+            text_x = (img.width - text_width) // 2
+            text_y = img.height + 10
+            draw.text((text_x, text_y), text, font=font, fill="black")
 
 
-            # 将图片转为字节流
             buffer = BytesIO()
             buffer = BytesIO()
-            img.save(buffer, format="PNG")
+            new_img.save(buffer, format="PNG")
 
 
-            # 返回文件响应
             return HttpResponse(
             return HttpResponse(
                 buffer.getvalue(),
                 buffer.getvalue(),
                 content_type="image/png",
                 content_type="image/png",
                 headers={
                 headers={
-                    'Content-Disposition': f'attachment; filename="scheme_{scheme.id}_qr.png"'
+                    'Content-Disposition': f'attachment; filename="scheme_{scheme.order_number}_qr.png"'
                 }
                 }
             )
             )
 
 
@@ -576,3 +665,53 @@ class ProductsSchemeManageView(View):
             })
             })
 
 
         return device_data
         return device_data
+
+    def get_sku_list(self, user_id, request_dict, response):
+        """获取历史SKU列表"""
+        try:
+            sku_list = (
+                ProductsScheme.objects
+                .exclude(sku__isnull=True)
+                .exclude(sku__exact='')
+                .exclude(deleted = True)
+                .values_list('sku', flat=True)
+                .distinct()
+            )
+            return response.json(0, list(sku_list))
+        except Exception as e:
+            LOGGER.exception(f"获取 SKU 列表异常: {repr(e)}")
+            return response.json(500, "获取 SKU 列表失败")
+
+    def get_scheme_by_sku(self, user_id, request_dict, response):
+        """根据SKU获取方案"""
+        try:
+            sku = request_dict.get('sku', '')
+            if not sku:
+                return response.json(444, "请提供有效的 SKU")
+
+            scheme = ProductsScheme.objects.filter(sku=sku).order_by('-created_time').first()
+
+            if not scheme:
+                return response.json(0, {})
+
+            scheme_data = {
+                'deviceType': scheme.device_type,
+                'productModel': scheme.product_model,
+                'flash': scheme.flash,
+                'ddr': scheme.ddr,
+                'mainController': scheme.main_controller,
+                'wifi': scheme.wifi,
+                'fourG': scheme.four_g,
+                'ad': scheme.ad,
+                'sensor': scheme.sensor,
+                'phy': scheme.phy,
+                'sku': scheme.sku,
+                'schemeCode': scheme.scheme_code,
+                'hwVersion': scheme.hw_version
+            }
+
+            return response.json(0, scheme_data)
+
+        except Exception as e:
+            LOGGER.exception(f"获取方案详情异常: {repr(e)}")
+            return response.json(500, "获取方案详情失败")

+ 33 - 7
Controller/IncomeProductsController.py

@@ -2,10 +2,10 @@ import time
 
 
 from django.views import View
 from django.views import View
 
 
-from Model.models import DeviceScheme
-from Object.RedisObject import RedisObject
-from Service.CommonService import CommonService
 from Ansjer.config import LOGGER
 from Ansjer.config import LOGGER
+from Model.models import DeviceScheme, ProductsScheme
+from Service.CommonService import CommonService
+
 
 
 class IncomeProductsView(View):
 class IncomeProductsView(View):
     def get(self, request, *args, **kwargs):
     def get(self, request, *args, **kwargs):
@@ -24,6 +24,8 @@ class IncomeProductsView(View):
             return self.income_device_scheme(request_dict, response)
             return self.income_device_scheme(request_dict, response)
         elif operation == 'statistics':
         elif operation == 'statistics':
             return self.statistics_device_scheme(request_dict, response)
             return self.statistics_device_scheme(request_dict, response)
+        elif operation == 'getProductSchemeList':
+            return self.get_product_scheme_list(request_dict, response)
         else:
         else:
             return response.json(414)
             return response.json(414)
 
 
@@ -53,7 +55,8 @@ class IncomeProductsView(View):
             device_scheme_qs = DeviceScheme.objects.filter(serial_number=serial_number)
             device_scheme_qs = DeviceScheme.objects.filter(serial_number=serial_number)
             if device_scheme_qs.exists():
             if device_scheme_qs.exists():
                 storage_code = device_scheme_qs.first().storage_code
                 storage_code = device_scheme_qs.first().storage_code
-                LOGGER.info(f"设备关联产品方案, serialNumber已存在, storageCode: {storage_code}, serialNumber: {serial_number}")
+                LOGGER.info(
+                    f"设备关联产品方案, serialNumber已存在, storageCode: {storage_code}, serialNumber: {serial_number}")
                 return response.json(174, f"数据已存在, storage_code为: {storage_code}")
                 return response.json(174, f"数据已存在, storage_code为: {storage_code}")
 
 
             now_time = int(time.time())
             now_time = int(time.time())
@@ -63,7 +66,8 @@ class IncomeProductsView(View):
                                         phone_model=phone_model, created_time=now_time,
                                         phone_model=phone_model, created_time=now_time,
                                         updated_time=now_time)
                                         updated_time=now_time)
 
 
-            LOGGER.info(f"设备关联产品方案, serialNumber录入成功, storageCode: {storage_code}, serialNumber: {serial_number}")
+            LOGGER.info(
+                f"设备关联产品方案, serialNumber录入成功, storageCode: {storage_code}, serialNumber: {serial_number}")
 
 
             return response.json(0)
             return response.json(0)
 
 
@@ -84,7 +88,29 @@ class IncomeProductsView(View):
             if not storage_code:
             if not storage_code:
                 return response.json(444)
                 return response.json(444)
             device_num = DeviceScheme.objects.filter(storage_code=storage_code).count()
             device_num = DeviceScheme.objects.filter(storage_code=storage_code).count()
-            return response.json(0, {"storageCode": storage_code,"deviceNum": device_num})
+            return response.json(0, {"storageCode": storage_code, "deviceNum": device_num})
         except Exception as e:
         except Exception as e:
             print(e)
             print(e)
-            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def get_product_scheme_list(request_dict, response):
+        order_number = request_dict.get('orderNumber', None)
+        if not order_number:
+            # 缺少订单号,返回错误码
+            return response.json(444)
+
+        # 查询符合条件的方案,仅获取指定字段
+        scheme_qs = ProductsScheme.objects.filter(order_number=order_number).values(
+            'storage_code', 'sku', 'hw_version', 'product_model', 'order_quantity', 'remark'
+        )
+
+        if not scheme_qs.exists():
+            # 没有查询到数据,返回对应错误码
+            return response.json(173)
+
+        # 将QuerySet转换为列表(数组格式),便于前端解析
+        scheme_list = list(scheme_qs)
+
+        # 返回成功状态码(0)和数据数组
+        return response.json(0, scheme_list)