Commit c1196462 authored by wanli's avatar wanli

更新后端

parent 361a917b
......@@ -10,6 +10,7 @@ class SignalManager(object):
# 上传文件
actionUploadFile = PySignal()
actionBackupDatabase = PySignal()
actionApplicationBuild = PySignal()
# 导入excel
# 导出excel
......
......@@ -3,6 +3,7 @@ port = 80
host = store.evmiot.com
protocol = http
upload_path = ./
temp_dir = tmp
upload_dir = uploads
netdisc = netdisc
......
......@@ -23,6 +23,7 @@ def initConnect():
# 系统模块
signalManager.actionUploadFile.connect(uploadManager.upload)
signalManager.actionUpdatePassword.connect(apiManager.update_user_password)
signalManager.actionApplicationBuild.connect(appsManager.build)
# 登录模块
signalManager.actionLogin.connect(loginManager.login)
......
......@@ -10,6 +10,7 @@ import types
import json
import logging
import traceback
from urllib import parse
from datetime import datetime
from pony.orm import *
from app import signalManager, config
......@@ -280,4 +281,66 @@ class AppsManager(object):
return result, "update app {}.".format("success" if result else "fail")
def build(self, files, data):
with db_session:
user = User.get(uuid=data['access_key'])
if not user:
return False, "user does not exists"
if data.get("access_key"): data.pop("access_key")
data.update({
'create_by': user,
'create_at': datetime.now(),
'update_by': user,
'update_at': datetime.now(),
})
app = Apps(**data)
commit()
dir_format = "{}-{}-{}".format(app.app_name, app.app_version, datetime.now().strftime("%Y%m%d%H%M%S"))
upload_dir = os.sep.join([config.get("UPLOAD_PATH"), config.get("UPLOAD_DIR"), "evueapps"])
target_dir = os.sep.join([upload_dir, user.account, dir_format])
dest_dir = os.sep.join([target_dir, "src"])
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
for target_file in files:
filename = os.path.basename(target_file)
name, suffix = os.path.splitext(filename)
name = re.sub(r"_\d{14}$", "", name)
dst_file = os.path.normpath(os.sep.join([dest_dir, name + suffix]))
shutil.copy(os.path.normpath(target_file), dst_file)
Annex(app=app, title=filename, path=dst_file, size=os.path.getsize(dst_file), create_by=user, create_at=datetime.now(), update_by=user, update_at=datetime.now())
flush()
commit()
# 打包成EPK文件
app_info = {}
params = { 'appName': app.app_name, 'appDir': dest_dir, 'appVersion': app.app_version, 'output': target_dir.replace(config.get("UPLOAD_PATH"), "") }
if user.role == "ADMIN":
params['algorithm'] = "h"
epk = EpkApp(**params)
app_info = epk.pack()
app_info['md5'] = str(app_info['md5'])
# 更新数据库对应文件路径
# 将文件拷贝过去后,需要重新更新数据库文件记录
epk_path = os.sep.join([target_dir.replace(config.get("UPLOAD_PATH"), ""), "{}.epk".format(app.app_name)]).replace('\\', '/')
build = BuildLogs.get(app=app)
if build:
build.set(app_path=epk_path, app_info=app_info, update_by=user, update_at=datetime.now())
commit()
else:
BuildLogs(app=app, app_path=epk_path, app_info=app_info, create_by=user, create_at=datetime.now(), update_by=user, update_at=datetime.now())
commit()
# 新增一条AppLogs
AppLogs(app_name=app.app_name, app_path=epk_path, app_version=app.app_version, app_info=app_info, create_by=user, create_at=datetime.now())
commit()
return { 'app_name': app.app_name, 'app_path': parse.urljoin(config['UPLOAD_SERVER'], epk_path) }, "application build {}.".format("success" if app_info else "fail")
appsManager = AppsManager()
......@@ -11,7 +11,6 @@ def validate_schema(schema_class: Schema):
def decorator(view_func):
@functools.wraps(view_func)
def inner(*args, **kwargs):
try:
if request.method == "GET":
form_data = request.args
......@@ -27,6 +26,7 @@ def validate_schema(schema_class: Schema):
data = schema_class().load(form_data)
request.schema_data = data
print(request.schema_data)
except ValidationError as e:
if config['DEBUG']:
return response_result(ResponseCode.PARAMETER_ERROR, e.messages if config['DEBUG'] else None)
......
......@@ -16,6 +16,16 @@ class UpdatePasswordSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class ApplicationBuildSchema(BaseSchema):
access_key = fields.UUID(required=True)
app_name = fields.String(required=True)
app_version = fields.String(required=True)
category = fields.String(required=True)
app_desc = fields.String(required=False)
class Meta:
unknown = INCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
......
......@@ -8,11 +8,13 @@ import traceback
import uuid
from flask import Blueprint, request, redirect, url_for, json, Response, send_file, make_response, send_from_directory
from werkzeug.utils import secure_filename
from app import config, signalManager
from app.setting import conf
from fullstack.login import Auth
from fullstack.response import ResponseCode, response_result
from fullstack.validation import validate_schema
from schema.api import UpdatePasswordSchema
from schema.api import UpdatePasswordSchema, ApplicationBuildSchema
logger = logging.getLogger("api")
......@@ -63,3 +65,32 @@ def update_db():
result.append(str(uuid.uuid1()))
return response_result(ResponseCode.OK, data=result)
@api.route("/application/build", methods=["post"])
@validate_schema(ApplicationBuildSchema)
def application_build():
try:
if request.method == 'POST' and 'binfiles' in request.files:
files = []
data = request.schema_data
dt = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
upload_path = os.sep.join([config["UPLOAD_PATH"], config["UPLOAD_DIR"], conf.get('uploads', 'temp_dir'), str(data['access_key']), dt])
if not os.path.exists(upload_path):
os.makedirs(upload_path)
for f in request.files.getlist('binfiles'):
filename = secure_filename(f.filename)
file_path = os.sep.join([upload_path, filename])
f.save(file_path)
files.append(file_path)
result, message = signalManager.actionApplicationBuild.emit(files, data)
if result:
return response_result(ResponseCode.OK, data=result, msg=message)
else:
return response_result(ResponseCode.REQUEST_ERROR, msg=message)
else:
return response_result(ResponseCode.REQUEST_ERROR, msg="files can not be null")
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return response_result(ResponseCode.SERVER_ERROR, msg=str(e))
......@@ -7,7 +7,6 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico" type="image/x-icon">
<link rel="png" href="<%= BASE_URL %>favicon.png">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css'>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
......
......@@ -8,9 +8,9 @@
<form action="#">
<h1>注册</h1>
<div class="social-container">
<a href="#" class="social" @mouseenter="onMouseEnter(1)" @mouseleave="onMouseLeave"><i class="fab fa-weixin"></i></a>
<a href="#" class="social" @mouseenter="onMouseEnter(2)" @mouseleave="onMouseLeave"><i class="fab fa-qq"></i></a>
<a href="https://gitee.com/scriptiot/evm" target="_blank" class="social"><i class="fab fa-github-alt"></i></a>
<a href="#" class="social" @mouseenter="onMouseEnter(1)" @mouseleave="onMouseLeave"><i class="el-icon-brush"></i></a>
<a href="#" class="social" @mouseenter="onMouseEnter(2)" @mouseleave="onMouseLeave"><i class="el-icon-cherry"></i></a>
<a href="https://gitee.com/scriptiot/evm" target="_blank" class="social"><i class="el-icon-pear"></i></a>
</div>
<span>完善用户基本信息</span>
<input type="text" v-model="post.account" placeholder="账号" />
......@@ -23,9 +23,9 @@
<form action="#">
<h1>登录</h1>
<div class="social-container">
<a href="#" class="social" @mouseenter="onMouseEnter(1)" @mouseleave="onMouseLeave"><i class="fab fa-weixin"></i></a>
<a href="#" class="social" @mouseenter="onMouseEnter(2)" @mouseleave="onMouseLeave"><i class="fab fa-qq"></i></a>
<a href="https://gitee.com/scriptiot/evm" target="_blank" class="social"><i class="fab fa-github-alt"></i></a>
<a href="#" class="social" @mouseenter="onMouseEnter(1)" @mouseleave="onMouseLeave"><i class="el-icon-sunrise"></i></a>
<a href="#" class="social" @mouseenter="onMouseEnter(2)" @mouseleave="onMouseLeave"><i class="el-icon-sunny"></i></a>
<a href="https://gitee.com/scriptiot/evm" target="_blank" class="social"><i class="el-icon-cloudy"></i></a>
</div>
<span>请输入账号密码</span>
<input
......
{
"application": {},
"controllers": [
{
"className": "",
"post": {},
"delete": {},
"get": {},
"put": {},
"parameters": [
{
"name": "",
"dataType": "",
"location": "",
"default": ""
}
]
}
],
"models": [
{
"className": "AreaModel",
"tableName": "area",
"fields": [
{
"name": "areaId",
"dataType": "Integer",
"primaryKey": true,
"autoIncrement": true
},
{
"name": "areaCode",
"dataType": "String",
"default": "",
"length": 20,
"index": true,
"required": true
},
{
"name": "areaName",
"dataType": "String",
"default": "",
"length": 20,
"index": false,
"primaryKey": false,
"autoIncrement": false,
"required": true
}
]
},
{
"tableName": "cache_data",
"className": "CacheDataModel",
"fields": [
{
"name": "id",
"dataType": "Integer",
"primaryKey": true,
"autoIncrement": true
},
{
"name": "equipment",
"dataType": "String",
"default": "",
"length": 64,
"index": false,
"required": true
},
{
"name": "channel1",
"dataType": "Decimal",
"default": 0,
"length": "(10, 5)",
"required": true
},
{
"name": "channel2",
"dataType": "Decimal",
"default": 0,
"length": "(10, 5)",
"required": true
},
{
"name": "channel3",
"dataType": "Decimal",
"default": 0,
"length": "(10, 5)",
"required": true
},
{
"name": "channel4",
"dataType": "Decimal",
"default": 0,
"length": "(10, 5)",
"required": true
},
{
"name": "channel5",
"dataType": "Decimal",
"default": 0,
"length": "(10, 5)",
"required": true
}
]
}
],
"resources": [
{
"post": {},
"delete": {},
"get": {},
"put": {},
"router": ""
}
],
"utils": []
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment