workflow admin 展示

This commit is contained in:
曹前明 2022-07-07 09:39:56 +08:00
parent adde4d671e
commit 7a62edb988
14 changed files with 429 additions and 62 deletions

View File

@ -0,0 +1,38 @@
//python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./BeiHangGrpc.proto
syntax = "proto3";
option java_generic_services = true;
option java_multiple_files = true;
option java_package = "com.lyzh.aiservice.grpc";
option java_outer_classname = "BeiHangProto";
service Helmet_Reg {
rpc sendHelmet_Info(JinYu_Request) returns (BHhelmet_Response){}
}
message JinYu_Request {
int64 zzid = 1; //ID
string imgsbase64 = 2 ; //Base64字符串
string imgUrl = 3 ; //oss链接Url
}
message BHhelmet_Response {
int64 zzid = 1; //ID
repeated HelmetInfo helmetinfoList = 2; //0: 1
}
message Point {
double x = 1; //x坐标
double y = 2; //y坐标
}
message Rectangle {
Point uleft = 1; //
Point lright = 2; //
}
message HelmetInfo {
int64 head_helmet = 1; //
double conf = 2; //
Rectangle coord = 3; //
}

View File

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: BeiHangGrpc.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11\x42\x65iHangGrpc.proto\"A\n\rJinYu_Request\x12\x0c\n\x04zzid\x18\x01 \x01(\x03\x12\x12\n\nimgsbase64\x18\x02 \x01(\t\x12\x0e\n\x06imgUrl\x18\x03 \x01(\t\"F\n\x11\x42Hhelmet_Response\x12\x0c\n\x04zzid\x18\x01 \x01(\x03\x12#\n\x0ehelmetinfoList\x18\x02 \x03(\x0b\x32\x0b.HelmetInfo\"\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\":\n\tRectangle\x12\x15\n\x05uleft\x18\x01 \x01(\x0b\x32\x06.Point\x12\x16\n\x06lright\x18\x02 \x01(\x0b\x32\x06.Point\"J\n\nHelmetInfo\x12\x13\n\x0bhead_helmet\x18\x01 \x01(\x03\x12\x0c\n\x04\x63onf\x18\x02 \x01(\x01\x12\x19\n\x05\x63oord\x18\x03 \x01(\x0b\x32\n.Rectangle2E\n\nHelmet_Reg\x12\x37\n\x0fsendHelmet_Info\x12\x0e.JinYu_Request\x1a\x12.BHhelmet_Response\"\x00\x42,\n\x17\x63om.lyzh.aiservice.grpcB\x0c\x42\x65iHangProtoP\x01\x88\x01\x01\x62\x06proto3')
_JINYU_REQUEST = DESCRIPTOR.message_types_by_name['JinYu_Request']
_BHHELMET_RESPONSE = DESCRIPTOR.message_types_by_name['BHhelmet_Response']
_POINT = DESCRIPTOR.message_types_by_name['Point']
_RECTANGLE = DESCRIPTOR.message_types_by_name['Rectangle']
_HELMETINFO = DESCRIPTOR.message_types_by_name['HelmetInfo']
JinYu_Request = _reflection.GeneratedProtocolMessageType('JinYu_Request', (_message.Message,), {
'DESCRIPTOR': _JINYU_REQUEST,
'__module__': 'BeiHangGrpc_pb2'
# @@protoc_insertion_point(class_scope:JinYu_Request)
})
_sym_db.RegisterMessage(JinYu_Request)
BHhelmet_Response = _reflection.GeneratedProtocolMessageType('BHhelmet_Response', (_message.Message,), {
'DESCRIPTOR': _BHHELMET_RESPONSE,
'__module__': 'BeiHangGrpc_pb2'
# @@protoc_insertion_point(class_scope:BHhelmet_Response)
})
_sym_db.RegisterMessage(BHhelmet_Response)
Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), {
'DESCRIPTOR': _POINT,
'__module__': 'BeiHangGrpc_pb2'
# @@protoc_insertion_point(class_scope:Point)
})
_sym_db.RegisterMessage(Point)
Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), {
'DESCRIPTOR': _RECTANGLE,
'__module__': 'BeiHangGrpc_pb2'
# @@protoc_insertion_point(class_scope:Rectangle)
})
_sym_db.RegisterMessage(Rectangle)
HelmetInfo = _reflection.GeneratedProtocolMessageType('HelmetInfo', (_message.Message,), {
'DESCRIPTOR': _HELMETINFO,
'__module__': 'BeiHangGrpc_pb2'
# @@protoc_insertion_point(class_scope:HelmetInfo)
})
_sym_db.RegisterMessage(HelmetInfo)
_HELMET_REG = DESCRIPTOR.services_by_name['Helmet_Reg']
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\027com.lyzh.aiservice.grpcB\014BeiHangProtoP\001\210\001\001'
_JINYU_REQUEST._serialized_start = 21
_JINYU_REQUEST._serialized_end = 86
_BHHELMET_RESPONSE._serialized_start = 88
_BHHELMET_RESPONSE._serialized_end = 158
_POINT._serialized_start = 160
_POINT._serialized_end = 189
_RECTANGLE._serialized_start = 191
_RECTANGLE._serialized_end = 249
_HELMETINFO._serialized_start = 251
_HELMETINFO._serialized_end = 325
_HELMET_REG._serialized_start = 327
_HELMET_REG._serialized_end = 396
# @@protoc_insertion_point(module_scope)

View File

@ -0,0 +1,67 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import BeiHangGrpc_pb2 as BeiHangGrpc__pb2
class Helmet_RegStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.sendHelmet_Info = channel.unary_unary(
'/Helmet_Reg/sendHelmet_Info',
request_serializer=BeiHangGrpc__pb2.JinYu_Request.SerializeToString,
response_deserializer=BeiHangGrpc__pb2.BHhelmet_Response.FromString,
)
class Helmet_RegServicer(object):
"""Missing associated documentation comment in .proto file."""
def sendHelmet_Info(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_Helmet_RegServicer_to_server(servicer, server):
rpc_method_handlers = {
'sendHelmet_Info': grpc.unary_unary_rpc_method_handler(
servicer.sendHelmet_Info,
request_deserializer=BeiHangGrpc__pb2.JinYu_Request.FromString,
response_serializer=BeiHangGrpc__pb2.BHhelmet_Response.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'Helmet_Reg', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class Helmet_Reg(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def sendHelmet_Info(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/Helmet_Reg/sendHelmet_Info',
BeiHangGrpc__pb2.JinYu_Request.SerializeToString,
BeiHangGrpc__pb2.BHhelmet_Response.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

29
apps/ai/helmet/algo.py Normal file
View File

@ -0,0 +1,29 @@
import grpc
import BeiHangGrpc_pb2_grpc, BeiHangGrpc_pb2
def helmet_test(ip, pic_url):
channel = grpc.insecure_channel(ip) # 监听频道
stub = BeiHangGrpc_pb2_grpc.Helmet_RegStub(channel) # 客户端使用Stub类发送请求,参数为频道,为了绑定链接
image_id = 3
# 本地图像输入
# image_path = "./onnx/image/single3.jpg"
# with open(image_path, 'rb') as f:
# image_base64 = str(base64.b64encode(f.read()), encoding='utf-8')
# request = BeiHangGrpc_pb2.JinYu_Request(zzid=image_id,imgsbase64=image_base64)
request = BeiHangGrpc_pb2.JinYu_Request(zzid=image_id, imgUrl=pic_url)
try:
response = stub.sendHelmet_Info(request)
print("network success! \n")
print(response.helmetinfoList[0].head_helmet)
except Exception:
print("network error! \n")
if __name__ == "__main__":
helmet_test(
ip='122.224.229.24:2000',
pic_url='http://1.203.161.103:2800/media/2022/07/06/dsf_bf6446cc-f9cd-11ec-bd2d-e4246c7d1635_34597240_34614457.jpg')

2
apps/ai/main.py Normal file
View File

@ -0,0 +1,2 @@
class AiService:
pass

View File

@ -473,15 +473,15 @@ class FileViewSet(CustomCreateModelMixin, RetrieveModelMixin, ListModelMixin, Cu
name = file_obj._name
size = file_obj.size
mime = file_obj.content_type
file_type = '其它'
file_type = File.FILE_TYPE_OTHER
if 'image' in mime:
file_type = '图片'
file_type = File.FILE_TYPE_PIC
elif 'video' in mime:
file_type = '视频'
file_type = File.FILE_TYPE_VIDEO
elif 'audio' in mime:
file_type = '音频'
file_type = File.FILE_TYPE_AUDIO
elif 'application' or 'text' in mime:
file_type = '文档'
file_type = File.FILE_TYPE_DOC
instance = serializer.save(
create_by=self.request.user, name=name, size=size, type=file_type, mime=mime)
instance.path = settings.MEDIA_URL + instance.file.name

View File

@ -31,7 +31,7 @@ class TDevice(BaseModel):
(DEVICE_PANEL, '面板机')
)
type = models.PositiveSmallIntegerField('设备类型', choices=DEVICE_CHOICE)
code = models.CharField('设备唯一标识', max_length=50, db_index=True)
code = models.CharField('设备唯一标识', max_length=50, db_index=True, unique=True)
name = models.CharField('名称', max_length=50, null=True, blank=True)
location = models.JSONField('位置信息', default=dict,
null=False, blank=True)
@ -40,14 +40,27 @@ class TDevice(BaseModel):
areas = models.ManyToManyField(Area, verbose_name='覆盖区',
related_name='tareas')
obj_cate = models.CharField('绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
employee = models.ForeignKey(Employee, verbose_name='当前绑定人员', on_delete=models.CASCADE, null=True, blank=True)
employee = models.ForeignKey(Employee, verbose_name='当前绑定人员', on_delete=models.CASCADE,
null=True, blank=True, related_name='td_employee')
is_clock = models.BooleanField('是否打卡设备', default=False)
third_info = models.JSONField('三方信息', default=dict,
null=False, blank=True)
class BltRecord(BaseModel):
pass
class BltBind(BaseModel):
"""标签绑定/解绑记录
"""
BLT_BIND = 10
BLT_UNBIND = 20
BIND_TYPE_CHOICES = (
(10, '绑定'),
(20, '解绑')
)
type = models.PositiveSmallIntegerField('绑定类型', default=10, help_text='10(绑定)/20(解绑)',
choices=BIND_TYPE_CHOICES)
obj_cate = models.CharField('绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
blt = models.ForeignKey(TDevice, verbose_name='关联标签', on_delete=models.CASCADE)
employee = models.ForeignKey(Employee, verbose_name='关联人员', on_delete=models.CASCADE, null=True, blank=True)
class Tlog(BaseModel):

View File

@ -2,8 +2,9 @@ from rest_framework import serializers
from apps.am.models import Area
from apps.hrm.serializers import EmployeeBaseSerializer, EmployeeSimpleSerializer
from apps.third.models import TDevice, Tlog
from apps.third.models import BltBind, TDevice, Tlog
from apps.utils.serializers import CustomModelSerializer
from django.db import transaction
class PicSerializer(serializers.Serializer):
@ -11,6 +12,7 @@ class PicSerializer(serializers.Serializer):
class TDeviceSerializer(CustomModelSerializer):
employee_ = EmployeeSimpleSerializer(source='employee', read_only=True)
area_name = serializers.CharField(source='area.name', read_only=True)
class Meta:
@ -69,10 +71,22 @@ class BltSerializer(serializers.ModelSerializer):
class Meta:
model = TDevice
fields = ['code', 'obj_cate', 'employee', 'employee_']
fields = ['code', 'obj_cate', 'employee', 'employee_', 'id']
class BltQuerySerializer(serializers.ModelSerializer):
class Meta:
model = TDevice
fields = ['area']
class BltBindCreateSerializer(serializers.ModelSerializer):
blt = serializers.PrimaryKeyRelatedField(queryset=TDevice.objects.filter(type=TDevice.DEVICE_BLT))
class Meta:
model = BltBind
fields = ['type', 'blt', 'employee']
class BltCreatesSerializer(serializers.Serializer):
macs = serializers.ListField(child=serializers.CharField(), label='标签mac列表')

View File

@ -1,13 +1,16 @@
import time
from threading import Thread
import uuid
import requests
from rest_framework.exceptions import APIException, ParseError
from django.conf import settings
from apps.third.errors import SP_REQUEST_ERROR
from apps.third.models import Tlog
from apps.utils.tools import print_roundtrip
from apps.third.tapis import spapis
from django.utils.timezone import now
requests.packages.urllib3.disable_warnings()
@ -27,6 +30,7 @@ class SpClient:
self.isGetingToken = False
self.isRuning = True
self.t = None # 线程
self.log = {}
self.setup()
def _get_token_loop(self):
@ -72,47 +76,35 @@ class SpClient:
file_path_rela=None, raise_exception=True):
if not settings.SP_ENABLED:
raise ParseError('音响对接未启用')
if self.isGetingToken:
req_num = 0
while True:
time.sleep(0.5)
if not self.isGetingToken:
self.request(url, method, params, json, timeout, file_path_rela, raise_exception)
req_num = req_num + 1
if req_num > 4:
break
else:
files = None
if file_path_rela: # 相对路径
files = {'file': open(settings.BASE_DIR + file_path_rela, 'rb')}
try:
if params:
url = url.format(**params)
r = getattr(requests, method)('{}{}'.format(settings.SP_BASE_URL, url),
headers=self.headers, params=params, json=json,
timeout=timeout, files=files, verify=False)
except Exception:
if raise_exception:
raise APIException(**SP_REQUEST_ERROR)
return 'error', SP_REQUEST_ERROR
# if settings.DEBUG:
# print_roundtrip(r)
if r.status_code == 200:
ret = r.json()
if 'code' in ret and ret['code'] not in ['0', '100', '00000', '1000', 0, 100, 1000]:
detail = '音响错误:{}'.format(str(ret.get('msg', '')))
err_detail = dict(detail=detail, code='sp_'+str(ret['code']))
if raise_exception:
raise ParseError(**err_detail)
return 'fail', dict(detail=detail, code='sp_'+str(ret['code']))
return 'success', ret
else:
ret = r.json()
detail = '音响错误:{}-{}'.format(str(ret.get('type', '')), str(ret.get('message', '')))
self.log = {"requested_at": now(), "id": uuid.uuid4(), "path": url, "method": method,
"params": params, "body": json, "target": "dahua", "result": 10}
files = None
if file_path_rela: # 相对路径
files = {'file': open(settings.BASE_DIR + file_path_rela, 'rb')}
try:
if params:
url = url.format(**params)
r = getattr(requests, method)('{}{}'.format(settings.SP_BASE_URL, url),
headers=self.headers, params=params, json=json,
timeout=timeout, files=files, verify=False)
except Exception:
if raise_exception:
raise APIException(**SP_REQUEST_ERROR)
return 'error', SP_REQUEST_ERROR
# if settings.DEBUG:
# print_roundtrip(r)
if r.status_code == 200:
ret = r.json()
if 'code' in ret and ret['code'] not in ['0', '100', '00000', '1000', 0, 100, 1000]:
detail = '音响错误:{}'.format(str(ret.get('msg', '')))
err_detail = dict(detail=detail, code='sp_'+str(ret['code']))
self.handle_log(result='fail', response=ret)
if raise_exception:
raise ParseError(**err_detail)
return 'fail', dict(detail=detail, code='sp_'+str(ret['code']))
self.handle_log(result='success', response=ret)
return 'success', ret
self.handle_log(result='error', response=None)
if raise_exception:
raise APIException(**SP_REQUEST_ERROR)
return 'error', SP_REQUEST_ERROR
@ -146,3 +138,20 @@ class SpClient:
}
self.request(**spapis['send_to_device'], json=json)
return
def _get_response_ms(self):
"""
Get the duration of the request response cycle is milliseconds.
In case of negative duration 0 is returned.
"""
response_timedelta = now() - self.log["requested_at"]
response_ms = int(response_timedelta.total_seconds() * 1000)
return max(response_ms, 0)
def handle_log(self, result, response=None):
self.log.update({
"result": result,
"response": response,
"response_ms": self._get_response_ms()
})
Tlog(**self.log).save()

View File

@ -119,6 +119,14 @@ xxapis = {
"rail_ibeacon_list": {
"url": "/WebLocate/locateByRail",
"method": "post"
},
"blt_adds": {
"url": "/api/v4/device/blts/add",
"method": "post"
},
"blt_info": {
"url": "/api/devicesV3/bltInfoByMac",
"method": "post"
}
}

View File

@ -1,5 +1,5 @@
from apps.third.models import TDevice, Tlog
from apps.third.serializers import BindAreaSerializer, BltQuerySerializer, BltSerializer, LabelLocationSerializer, TDeviceSerializer, TlogSerializer
from apps.third.models import BltBind, TDevice, Tlog
from apps.third.serializers import BindAreaSerializer, BltBindCreateSerializer, BltQuerySerializer, BltSerializer, LabelLocationSerializer, TDeviceSerializer, TlogSerializer
from apps.utils.viewsets import CustomGenericViewSet
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from apps.third.clients import xxClient, dhClient, spClient
@ -10,6 +10,8 @@ from rest_framework.decorators import action
from apps.am.models import Area
from rest_framework.views import APIView
from rest_framework.exceptions import ParseError
from django.db import transaction
from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin
class BltViewSet(CustomGenericViewSet):
@ -36,9 +38,9 @@ class BltViewSet(CustomGenericViewSet):
@action(methods=['get'], detail=False, perms_map={'get': '*'})
def count_now(self, request):
"""统计在厂标签数
"""统计在厂且绑定标签数
统计在厂标签数
统计在厂且绑定标签数
"""
json = {
"pageNum": 1,
@ -108,14 +110,91 @@ class BltViewSet(CustomGenericViewSet):
return Response(blt_list)
class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
class TDeviceViewSet(ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
"""
三方设备接口
"""
queryset = TDevice.objects.all()
serializer_class = TDeviceSerializer
ordering = ['code', '-create_time']
filterset_fields = ['type']
ordering = ['-create_time']
filterset_fields = ['type', 'area', 'employee', 'obj_cate']
select_related_fields = ['employee', 'area', 'employee__post', 'employee__belong_dept']
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
else:
serializer = self.get_serializer(queryset, many=True)
data = serializer.data
typex = self.request.query_params.get('type', None)
if typex == str(TDevice.DEVICE_BLT): # 如果是定位标签加载三方信息
macs = []
for i in data:
macs.append(i['code'])
json = {
"macList": macs
}
_, res = xxClient.request(**xxapis['blt_info'], json=json)
macs_dict = {}
for i in res['success']:
macs_dict[i['mac']] = i
for i in res['error']:
macs_dict[i['mac']] = i
for i in data:
i['third_info'] = macs_dict.get(i['code'], {})
if page is not None:
return self.get_paginated_response(data)
else:
return Response(data)
@action(methods=['post'], detail=False, perms_map={'post': '*'},
serializer_class=Serializer)
@transaction.atomic
def blt_sync(self, request):
"""同步标签mac至平台
同步标签mac至平台
"""
json = {
"pageNum": 1,
"numPerPage": 1000
}
_, res = xxClient.request(**xxapis['blt_list'], json=json)
blt_list = res['recordList']
for i in blt_list:
TDevice.objects.get_or_create(code=i['mac'], default={"code": i['mac'], "type": TDevice.DEVICE_BLT})
return Response()
@action(methods=['post'], detail=False, perms_map={'post': '*'},
serializer_class=BltBindCreateSerializer)
@transaction.atomic
def blt_bind(self, request):
"""绑定/解绑定位卡
绑定/解绑定位卡
"""
serializer = BltBindCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
blt = vdata['blt']
if vdata['type'] == BltBind.BLT_BIND and vdata['employee']:
if blt.employee:
raise ParseError('该定位卡已绑定人员,请先解绑')
else:
blt.employee = vdata['employee']
blt.obj_cate = 'people'
blt.save()
vdata['obj_cate'] = 'people'
BltBind.objects.create(**vdata)
elif vdata['type'] == BltBind.BLT_UNBIND:
if blt.employee:
blt.employee = None
blt.save()
vdata['obj_cate'] = 'people'
BltBind.objects.create(**vdata)
return Response()
@action(methods=['post'], detail=False, perms_map={'post': '*'},
serializer_class=Serializer)
@ -128,7 +207,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
macs = []
for i in res['recordList']:
macs.append(i['mac'])
qs = self.queryset.filter(code__in=macs).exclude(employee=None)
qs = self.queryset.filter(code__in=macs)
qs_data = BltSerializer(instance=qs, many=True).data
qs_dict = {}
for i in qs_data:
@ -158,6 +237,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
for i in tds_info:
tds_dict[i['code']] = i
for i in res['pageData']:
i['my_info'] = {}
if i['channelCode'] in tds_dict:
i['my_info'] = tds_dict[i['channelCode']]
return Response(res)
@ -179,6 +259,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
for i in tds_info:
tds_dict[i['code']] = i
for i in res['rows']:
i['my_info'] = {}
if i['sn'] in tds_dict:
i['my_info'] = tds_dict[i['sn']]
return Response(res)
@ -202,6 +283,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
for i in tds_info:
tds_dict[i['code']] = i
for i in res['pageData']:
i['my_info'] = {}
if i['channelCode'] in tds_dict:
i['my_info'] = tds_dict[i['channelCode']]
return Response(res)
@ -246,9 +328,9 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
serializer_class=BindAreaSerializer)
def bind_area(self, request):
"""
绑定所在区域
批量绑定所在区域
绑定所在区域
批量绑定所在区域
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)

View File

@ -1,6 +1,8 @@
from aip import AipSpeech
from django.conf import settings
import uuid
import os
from django.utils import timezone
def generate_voice(msg: str, per: int = 0):
@ -19,9 +21,12 @@ def generate_voice(msg: str, per: int = 0):
result = client.synthesis(msg, 'zh', 1, {'vol': 5, 'spd': 5, 'per': per})
# 识别正确返回语音二进制 错误则返回dict 参照下面错误码
if not isinstance(result, dict):
# name = '{}.mp3'.format(uuid.uuid4())
path = '/media/voice/{}.mp3'.format(uuid.uuid4())
with open(settings.BASE_DIR + path, 'wb') as f:
file_name = '{}.mp3'.format(uuid.uuid4())
path = '/media/' + timezone.now().strftime('%Y/%m/%d/')
full_path = settings.BASE_DIR + path
if not os.path.exists(full_path):
os.makedirs(full_path)
with open(full_path + file_name, 'wb') as f:
f.write(result)
return True, path, None
return True, path + file_name, None
return False, None, result

View File

@ -22,6 +22,13 @@ class Workflow(CommonAModel):
content_template = models.CharField(
'内容模板', max_length=1000, default='标题:{title}, 创建时间:{create_time}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:标题:{title}, 创建时间:{create_time}')
class Meta:
verbose_name = '工作流'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class State(CommonAModel):
"""
@ -99,6 +106,13 @@ class State(CommonAModel):
participant_cc = models.JSONField('抄送给', default=list, blank=True, help_text='抄送给(userid列表)')
on_reach_func = models.CharField('到达时调用方法', max_length=100, null=True, blank=True)
class Meta:
verbose_name = '工作流节点'
verbose_name_plural = verbose_name
def __str__(self):
return '{}-{}-{}'.format(self.id, self.workflow.name, self.name)
class Transition(CommonAModel):
"""
@ -154,6 +168,13 @@ class Transition(CommonAModel):
'是否校验必填项', default=True, help_text='默认在用户点击操作的时候需要校验工单表单的必填项,如果设置为否则不检查。用于如"退回"属性的操作,不需要填写表单内容')
on_submit_func = models.CharField('提交操作调用方法', max_length=100, null=True, blank=True)
class Meta:
verbose_name = '工作流流转'
verbose_name_plural = verbose_name
def __str__(self):
return '{}-{}-{}'.format(self.id, self.workflow.name, self.name)
class CustomField(CommonAModel):
"""自定义字段, 设定某个工作流有哪些自定义字段"""

View File

@ -389,3 +389,7 @@ XNIU_SMS_SECRET = conf.XNIU_SMS_SECRET
BD_SP_ID = conf.BD_SP_ID
BD_SP_KEY = conf.BD_SP_KEY
BD_SP_SECRET = conf.BD_SP_SECRET
# 算法层
AI_IP = conf.AI_IP