|
@@ -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, "获取方案详情失败")
|