Commit e339fd7a authored by wanli's avatar wanli

update

parent a1eea683
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.dylib
# Compiled Static libraries
*.lai
*.la
*.a
# Executables
*.exe
*.out
*.app
*.Debug
*.Release
*.rc
*.zip
*.pyc
debug
deploy/
build/
logs/*.log
logs/*.log.*
frontend/node_modules
frontend/dist
backend/logs/*.log
backend/logs/*.log.*
backend/kelixie.db
backend/klx_main.db
backend/klx_backup.db
backend/scheduler.db
backend/*.db-journal
backend/backup/*
backend/upload/
backend/uploads
backend/static/uploads
nginx-1.18.0
nginx-1.18.0/*
nssm-2.24
nssm-2.24/*
release/
release.*
KXPMS/
KXPMS*.tar.gz
wwwroot/
.DS_Store
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.db
# evm-store
EVM应用商店
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import json
from .signal_manager import signalManager
from .setting import config
import logging
from controller import initConnect
logger = logging.getLogger("ApplicationManager")
def loadSettings(path=None):
global config
projectFile = os.sep.join([os.path.dirname(os.getcwd()), "project.json"])
if os.path.exists(projectFile):
with open(projectFile, "rb") as f:
obj = json.loads(f.read())
config['PORT'] = obj['port']
for key in config:
lowerKey = key.lower()
if lowerKey in obj:
config[key] = obj[lowerKey]
if lowerKey in obj["server"]:
config[key] = obj["server"][lowerKey]
if key == "PONY":
config["PONY"]= obj["server"]["db"]
return config
def initApp():
global config
config = loadSettings()
return config
config = initApp()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import configparser
conf = configparser.ConfigParser()
conf.read(os.path.join(os.getcwd(), "config.ini"))
config = dict(
NAME='evm_store',
DEBUG=True,
HOST="0.0.0.0",
PORT=9999,
SECRET_KEY='secret_key_EhuqUkwV',
LOGIN_DISABLED=False,
BACKUP_DIR=conf.get('application', 'backup_dir'),
NETDISC=conf.get('uploads', 'netdisc'),
DATABASE=conf.get('database', 'filename'),
DATABASE_FILE=conf.get('scheduler', 'db'),
PONY={
'provider': conf.get('database', 'provider'),
'filename': "../{}".format(conf.get('database', 'filename')),
'create_db': True,
},
TABLE_PREFIX='klx_',
MD5_SALT="EhuqUkwV",
UPLOAD_SERVER="{}://{}:{}/".format(conf.get('uploads', 'protocol'), conf.get('uploads', 'host'), conf.get('uploads', 'port')),
UPLOAD_PATH=conf.get('uploads', 'upload_path'),
UPLOAD_DIR=conf.get('uploads', 'upload_dir'),
TEMPLATE_PATH=os.path.join(os.getcwd(), "static"),
STATIC_PATH=os.path.join(os.getcwd(), "static"),
LOGO=r'''
______ _____
___ _________ /_ ________________________ __ /______________
__ | /| / / _ \_ __ \ _ ___/_ ___/ _ \ __ `/ __/ __ \_ ___/
__ |/ |/ // __/ /_/ / / /__ _ / / __/ /_/ // /_ / /_/ / /
____/|__/ \___//_.___/ \___/ /_/ \___/\__,_/ \__/ \____//_/
Power by EVM Team
'''
)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from fullstack.event import PySignal
class SignalManager(object):
# 接口模块
actionUpdatePassword = PySignal()
# 上传文件
actionUploadFile = PySignal()
actionBackupDatabase = PySignal()
# 导入excel
# 导出excel
# 登录模块
actionLogin = PySignal()
actionLogout = PySignal()
actionRegister = PySignal()
# 应用管理
actionAddApp = PySignal()
actionGetApp = PySignal()
actionGetAppList = PySignal()
actionUpdateApp = PySignal()
actionDeleteApp = PySignal()
# 应用打包记录
actionAddBuildLog = PySignal()
actionGetBuildLog = PySignal()
actionGetBuildLogList = PySignal()
actionUpdateBuildLog = PySignal()
actionDeleteBuildLog = PySignal()
# 网盘管理
actionAddNetDisc = PySignal()
actionGetNetDisc = PySignal()
actionGetNetDiscList = PySignal()
actionUpdateNetDisc = PySignal()
actionDeleteNetDisc = PySignal()
# 用户模块
actionAddUser = PySignal()
actionDeleteUser = PySignal()
actionGetUser = PySignal()
actionGetUserList = PySignal()
actionUpdateUser = PySignal()
# 文件附件模块
actionAddAnnex = PySignal()
actionDeleteAnnex = PySignal()
actionGetAnnex = PySignal()
actionGetAnnexList = PySignal()
actionUpdateAnnex = PySignal()
def __init__(self):
super(SignalManager, self).__init__()
signalManager = SignalManager()
[uploads]
port = 8888
host = localhost
protocol = http
upload_path = F:\Wanli\projects\evm-store\backend
upload_dir = uploads
netdisc = netdisc
[database]
provider = sqlite
filename = app-store.db
[scheduler]
db = scheduler.db
[application]
name = evm_store
nginx = NginxService
backup_dir = backup
evueapps_dir = evueapps
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import json
import logging
from app import signalManager
from .user_manager import userManager
from .login_manager import loginManager
from .annex_manager import annexManager
from .upload_manager import uploadManager
from .apps_manager import appsManager
from .build_logs_manager import buildLogsManager
logger = logging.getLogger("controller")
def initConnect():
# 系统模块
signalManager.actionUploadFile.connect(uploadManager.upload)
# 登录模块
signalManager.actionLogin.connect(loginManager.login)
signalManager.actionLogout.connect(loginManager.logout)
signalManager.actionRegister.connect(loginManager.register)
# 应用管理
signalManager.actionAddApp.connect(appsManager.add)
signalManager.actionDeleteApp.connect(appsManager.delete)
signalManager.actionGetApp.connect(appsManager.get)
signalManager.actionGetAppList.connect(appsManager.getList)
signalManager.actionUpdateApp.connect(appsManager.update)
# 打包记录
signalManager.actionAddBuildLog.connect(buildLogsManager.add)
signalManager.actionDeleteBuildLog.connect(buildLogsManager.delete)
signalManager.actionGetBuildLog.connect(buildLogsManager.get)
signalManager.actionGetBuildLogList.connect(buildLogsManager.getList)
signalManager.actionUpdateBuildLog.connect(buildLogsManager.update)
# 用户模块
signalManager.actionAddUser.connect(userManager.add)
signalManager.actionDeleteUser.connect(userManager.delete)
signalManager.actionGetUser.connect(userManager.get)
signalManager.actionGetUserList.connect(userManager.getList)
signalManager.actionUpdateUser.connect(userManager.update)
# 文件附件模块
signalManager.actionAddAnnex.connect(annexManager.add)
signalManager.actionDeleteAnnex.connect(annexManager.delete)
signalManager.actionGetAnnex.connect(annexManager.get)
signalManager.actionGetAnnexList.connect(annexManager.getList)
signalManager.actionUpdateAnnex.connect(annexManager.update)
initConnect()
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import time
import types
import json
import logging
import traceback
from datetime import datetime
from pony.orm import *
from flask import request
from model import fullStackDB
from model.annex import Annex
from model.user import User
from utils import sql_filter
logger = logging.getLogger("AnnexManager")
class AnnexManager(object):
def __init__(self):
super(AnnexManager, self).__init__()
def add(self, data):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
if data.get("flow"):
flow = Flow.get(uuid=data.get("flow"))
if not flow:
return False, "flow does not exists."
data.update({ "flow": flow })
elif data.get("project"):
project = Project.get(uuid=data.get("project"))
if not project:
return False, "project does not exists."
data.update({ "project": project })
data.update({
'title': data.get("title"),
'path': data.get("path"),
'size': data.get("size"),
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = fullStackDB.add(Annex, **data)
return result, "add annex {}.".format("success" if result else "fail")
def delete(self, uuid):
result = False
with db_session:
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = Annex.get(uuid=uuid)
if result:
if result.project:
count = Annex.select(project=result.project, remarks=result.remarks, is_delete=False).count()
if count == 1:
project = Project.get(id=result.project.id)
if project:
condition = dict()
if result.remarks == "bidding": # 中标通知书
condition.update({ "is_bidding": False })
elif result.remarks == "acceptance": # 验收表
condition.update({ "is_acceptance": False })
elif result.remarks == "evaluation": # 评价表
condition.update({ "is_evaluation": False })
elif result.remarks == "contract": # 合同
condition.update({ "is_contract": False })
project.extend1.get("uploads").update({ result.remarks: False })
project.set(extend1=project.extend1, **condition)
result.set(is_delete=True, delete_at=datetime.now(), delete_by=editor)
commit()
result = True
return result, "delete annex {}.".format("success" if result else "fail")
def get(self, data):
result = Annex.get(**data)
if result:
result = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "title", "create_at", "update_at", "delete_at"])
return result, "get annex {}.".format("success" if result else "fail")
def getList(self, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
result = Annex.select().where(is_delete=False, **data)
if len(result):
temp = []
for item in result:
# t = item.to_dict(with_collections=True, only=["uuid", "title", "project", "path", "remarks"])
# temp.append(t)
temp.append({
"uuid": item.uuid,
"name": item.title,
"project": item.project.id,
"url": item.path,
"type": item.remarks
})
result = temp
return result, len(result), "get annex {}.".format("success" if result else "no data")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Annex, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update annex {}.".format("success" if result else "fail")
annexManager = AnnexManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import time
import types
import json
import logging
import traceback
from datetime import datetime
from pony.orm import *
from flask import request
from model import fullStackDB
from model.annex import Annex
from model.apps import Apps
from model.user import User
from utils import sql_filter
logger = logging.getLogger("AppsManager")
class AppsManager(object):
def __init__(self):
super(AppsManager, self).__init__()
def add(self, data):
with db_session:
result = Apps.get(app_name=data.get("app_name"))
if result:
return False, "app_name has been exists."
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
app_files = []
if data.get("app_files"):
app_files = data.get("app_files")
data.pop("app_files")
result = Apps(**data)
commit()
for a in app_files:
Annex(app_id=result, title=a.get("filename"), path=a.get("filepath"), size=a.get("filesize"), create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
flush()
commit()
return result, "add app {}.".format("success" if result else "fail")
def delete(self, uuid):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Apps, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete app {}.".format("success" if result else "fail")
def get(self, data):
result = Apps.get(**data)
if result:
result = result.to_dict(only=["uuid", "name", "create_at", "update_at"])
return result, "get app {}.".format("success" if result else "no data")
def getList(self, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
temp.setdefault("is_delete", False)
with db_session:
if "scope_type" in data and data.get("scope_type") == "list":
result = Apps.select().where(**temp).order_by(desc(Apps.create_at))
temp = []
for item in result:
temp.append(item.to_dict(only=["uuid", "app_name"]))
return temp, len(temp), "get app {}.".format("success" if temp else "fail")
result = Apps.select().where(**temp).order_by(desc(Apps.create_at)).page(data.get("pagenum", 1), pagesize=data.get("pagesize", 10))
count = Apps.select().where(**temp).count()
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, exclude=["app_annex", "app_build_log", "is_delete", "delete_by", "delete_at"])
t.update({
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"]),
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S") if item.create_at else None,
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S") if item.update_at else None,
})
temp.append(t)
result = temp
return result, count, "get app {}.".format("success" if result else "no data")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "app can not be null."
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Apps, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update app {}.".format("success" if result else "fail")
appsManager = AppsManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import copy
import time
import types
import json
import shutil
import logging
import traceback
from urllib.parse import urlparse, urljoin
from datetime import datetime
from pony.orm import *
from flask import request
from app.setting import config
from model import fullStackDB
from model.apps import Apps
from model.annex import Annex
from model.build_logs import BuildLogs
from model.user import User
from utils import sql_filter
from utils.tools_epk import EpkApp
logger = logging.getLogger("BuildLogsManager")
class BuildLogsManager(object):
def __init__(self):
super(BuildLogsManager, self).__init__()
def add(self, app_id):
with db_session:
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
# 根据app_id查询应用,获取应用有哪些文件
# 按格式创建文件夹,将这些文件移动到这个文件夹
# 将这些零散文件进行打包
# 更新数据库对应文件的路径
app = Apps.get(uuid=app_id)
if not app:
return None, "app not found"
source_files = Annex.select().filter(app_id=app)
if not source_files:
return None, "apps file not found"
dir_format = "{}-{}-{}".format(app.app_name, app.app_version, int(time.time()))
upload_dir = os.sep.join([config.get("UPLOAD_PATH"), config.get("UPLOAD_DIR"), "evueapps"])
target_dir = os.sep.join([upload_dir, editor.account, dir_format])
dest_dir = os.sep.join([target_dir, "src"])
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
app_files = []
for sf in source_files:
parsed_result = urlparse(sf.path)
target_file = os.sep.join([config.get("UPLOAD_PATH"), parsed_result.path.replace('/', '\\')])
shutil.move(target_file, dest_dir)
app_files.append([sf.id, os.sep.join([dest_dir, os.path.basename(parsed_result.path)])])
# if os.path.exists(target_file):
# shutil.move(target_file, dest_dir)
# app_files.append([sf.id, os.sep.join([dest_dir, os.path.basename(parsed_result.path)])])
# else:
# print("file not found: %s" % target_file)
# break
# 打包成EPK文件
epk = EpkApp(appName=dir_format, appDir=dest_dir, appVersion=app.app_version, output=target_dir)
app_info = epk.pack()
# 更新数据库对应文件路径
for sf in source_files:
for af in app_files:
if sf.id == af[0]:
t = os.path.normpath(af[1].replace(config.get("UPLOAD_PATH"), "")).replace('\\', '/')
sf.set(path=urljoin(config.get("UPLOAD_SERVER"), t))
flush()
commit()
epk_path = os.sep.join([target_dir.replace(config.get("UPLOAD_PATH"), ""), "{}.epk".format(dir_format)])
epk_path = urljoin(config.get("UPLOAD_SERVER"), epk_path.replace('\\', '/'))
app_info['md5'] = str(app_info['md5'])
result = BuildLogs(app_id=app, app_path=epk_path, app_info=app_info, create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
commit()
return epk_path, "add build_logs {}.".format("success" if result else "fail")
def delete(self, uuid):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(BuildLogs, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete build_logs {}.".format("success" if result else "fail")
def get(self, data):
result = BuildLogs.get(**data)
if result:
result = result.to_dict(only=["uuid", "name", "create_at", "update_at"])
return result, "get build_logs {}.".format("success" if result else "no data")
def getList(self, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
temp.setdefault("is_delete", False)
if "scope_type" in data and data.get("scope_type") == "list":
result = BuildLogs.select().where(**temp).order_by(desc(BuildLogs.create_at))
temp = []
for item in result:
temp.append(item.to_dict(only=["uuid"]))
return temp, len(temp), "get build_logs {}.".format("success" if temp else "fail")
result = fullStackDB.pagination(BuildLogs, BuildLogs.create_at, pagenum=data.get("pagenum", 1), pagesize=data.get("pagesize", 10), **temp)
count = fullStackDB.count(BuildLogs, **temp)
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, exclude=["is_delete", "delete_by", "delete_at"])
t.update({
"app_id": item.app_id.to_dict(exclude=["is_delete", "delete_by", "delete_at"]),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"]),
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S") if item.create_at else None,
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S") if item.update_at else None,
})
temp.append(t)
result = temp
return result, count, "get build_logs {}.".format("success" if result else "no data")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(BuildLogs, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update permission {}.".format("success" if result else "fail")
buildLogsManager = BuildLogsManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import time
import types
import json
import logging
import traceback
from datetime import datetime
from pony.orm import select, desc
from flask import request
from model import fullStackDB
from model.dictionary import Dict
from model.user import User
from utils import sql_filter
logger = logging.getLogger("DictManager")
class DictManager(object):
def __init__(self):
super(DictManager, self).__init__()
def add(self, data):
# 判断相同的类别和标签是否存在
result = Dict.get(label=data.get("label"), value=data.get("value"), category=data.get("category"))
if result:
return False, "dictionary has been exists."
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = fullStackDB.add(Dict, **data)
return result, "add dictionary {}.".format("success" if result else "fail")
def delete(self, uuid):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = Dict.get(uuid=uuid)
if not result:
return False, "dict does not exists"
else:
if result.is_system:
return False, "dict can not delete"
result = fullStackDB.update(Dict, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete dictionary {}.".format("success" if result else "fail")
def get(self, data):
result = Dict.get(**data)
if result:
result = result.to_dict(only=["uuid", "label", "create_at", "update_at"])
return result, "get dictionary {}.".format("success" if result else "no data")
def getList(self, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
if 'is_category' in temp:
temp.pop('is_category')
if 'category' in temp and isinstance(data.get("category"), list):
temp.pop("category")
temp.setdefault("is_delete", False)
if "scope_type" in data and data.get("scope_type") == "list":
result = Dict.select().where(**temp).order_by(Dict.sort)
temp = []
for item in result:
if item.category in data.get("category"):
temp.append(item.to_dict(only=["uuid", "label", "value", "category"]))
return temp, len(temp), "get dictionary list {}.".format("success" if temp else "no data")
elif "is_category" in data and data.get("is_category") == 1:
result = select(d.category for d in Dict)
# result = Dict.select_by_sql("SELECT DISTINCT(`category`) FROM `{}`".format(Dict._table_))
return list(result), len(result), "get select {}.".format("success" if result else "fail")
result = Dict.select().where(**temp).order_by(desc(Dict.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = Dict.select().where(**temp).count()
if result:
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True,)
t.update({
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S"),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"])
})
temp.append(t)
result = temp
return result, count, "get dictionary {}.".format("success" if result else "fail")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Dict, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update dictionary {}.".format("success" if result else "fail")
dictManager = DictManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import time
import types
import json
import logging
import traceback
from threading import Thread
from werkzeug.security import check_password_hash
from model import fullStackDB
from model.user import User
from fullstack.login import Auth
from fullstack.response import ResponseCode
from utils import md5_salt
logger = logging.getLogger("LoginManager")
class LoginManager(object):
'''
用户管理的单例类
'''
def __init__(self):
super(LoginManager, self).__init__()
# Thread(target=self.dashboard).start()
def login(self, data):
'''
用户登录
:param data:登录的用户信息json如 { "account": "xx", "password": "xx" }
:return ret: dict类型的登录相关信息
'''
try:
# 判断用户名是否存在
result = User.get(account=data.get("account"))
if not result:
return False, ResponseCode.NO_DATA_FOUND
# 判断密码是否正确
result = User.get(account=data.get("account"), password=md5_salt(data.get("password")))
if not result:
return False, ResponseCode.PASSWORD_ERROR
# 判断用户是否禁用
if result.is_delete:
return False, ResponseCode.ACCOUNT_DISABLED
# 返回token
token = Auth.encode_auth_token(result.id, result.username) # 生成 token
# setattr(result, 'token', token)
return { 'token': token, 'id': result.id, 'username': result.username }, ResponseCode.OK
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return False, str(e)
def logout(self):
'''
用户登出
'''
try:
return True, "User logout success."
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return False, str(e)
def register(self, data):
'''
用户注册
'''
try:
# 判断账号是否存在
result = User.get(account=data.get("account"))
if result:
return False, "User already exists"
result = fullStackDB.add(User, **data)
return result, "User registration is {}.".format("success" if result else "fail")
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return False, str(e)
loginManager = LoginManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import copy
import time
import types
import json
import logging
import traceback
from datetime import datetime
from pony.orm import *
from flask import request
from model import fullStackDB
from model.netdisc import Netdisc
from model.user import User
from app.setting import config
logger = logging.getLogger("NetDiscManager")
class NetDiscManager(object):
def __init__(self):
super(NetDiscManager, self).__init__()
def add(self, data):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = fullStackDB.add(Netdisc, **data)
return result, "add netdisc {}.".format("success" if result else "fail")
def delete(self, data):
# 通过uuid查询出所有的文件列表,然后全部删除
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
count = 0
result = []
with db_session:
for uuid in data.get("uuids"):
nd = Netdisc.get(uuid=uuid)
if nd:
# nd.is_delete = True
# nd.delete_at = datetime.now()
# nd.delete_by = editor
nd.set(is_delete = True, delete_at = datetime.now(), delete_by = editor)
count = count + 1
result.append([nd.is_dir, nd.real_path])
commit()
return result, "delete {} netdisc {}.".format(count, "success" if result else "fail")
def get(self, data):
result = Netdisc.get(**data)
if result:
result = result.to_dict(only=["uuid", "name", "real_path"])
return result, "get netdisc {}.".format("success" if result else "no data")
def getList(self, data):
data.update({ "is_delete": False })
count = 0
result = []
with db_session:
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
if editor.role.name != "超级管理员":
data.update({ "create_by": editor })
result = Netdisc.select().where(**data).order_by(Netdisc.name)
count = len(result)
files = []
folders = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, only=["uuid", "name", "size", "is_dir", "parent_dir", "file_type", "create_at", "update_at"])
if item.is_dir:
t.update({
"is_dir": 1 if item.is_dir else 0,
"real_path": os.path.relpath(item.real_path, config.get("UPLOAD_PATH")).replace('\\', '/'),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"]),
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S")
})
folders.append(t)
else:
t.update({
"is_dir": 1 if item.is_dir else 0,
"real_path": os.path.relpath(item.real_path, config.get("UPLOAD_PATH")).replace('\\', '/'),
"create_by": item.create_by.to_dict(only=["uuid", "username"]),
"update_by": item.update_by.to_dict(only=["uuid", "username"]),
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S")
})
files.append(t)
result = folders + files
return result, count, "get netdisc {}.".format("success" if result else "no data")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
result = None
with db_session:
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = Netdisc.get(uuid=uuid)
if result:
_real = result.real_path
result.set(update_at=datetime.now(), update_by=editor, **data)
commit()
_ext = os.path.splitext(result.real_path)[-1]
_dir = os.path.dirname(result.real_path)
filename = data.get("name") + _ext
data.update({ "real_path": os.path.normpath(os.sep.join([_dir, filename])) })
result = { "src": _real, "dst": data.get("real_path") }
return result, "update netdisc {}.".format("success" if result else "fail")
netDiscManager = NetDiscManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import time
import types
import json
import logging
import traceback
from datetime import datetime
from pony.orm import *
from flask import request
from model import fullStackDB
from model.depot import Depot
from model.role import Role
from model.user import User
from utils import sql_filter
logger = logging.getLogger("RoleManager")
class RoleManager(object):
def __init__(self):
super(RoleManager, self).__init__()
def add(self, data):
# 判断角色名是否存在
result = Role.get(name=data.get("name"))
if result:
return False, "role name has been exists."
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = fullStackDB.add(Role, **data)
return result, "add role {}.".format("success" if result else "fail")
def delete(self, uuid):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Role, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete role {}.".format("success" if result else "fail")
def get(self, data):
result = Role.get(**data)
if result:
result = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "name", "create_at", "update_at", "delete_at"])
return result, "get role {}.".format("success" if result else "fail")
def getList(self, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
temp.setdefault("is_delete", False)
if "scope_type" in data and data.get("scope_type") == "list":
result = Role.select().where(**temp).order_by(desc(Role.create_at))
temp = []
for item in result:
temp.append(item.to_dict(only=["uuid", "name"]))
return temp, len(temp), "get select {}.".format("success" if temp else "no data")
result = fullStackDB.pagination(Role, Role.create_at, pagenum=data.get("pagenum", 1), pagesize=data.get("pagesize", 10), **temp)
count = fullStackDB.count(Role, **temp)
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, only=["uuid", "name", "permission", "is_system", "create_by", "update_by"])
t.update({ "create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S") })
t.update({ "update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S") })
t.update({ "create_by": item.create_by.to_dict(only=["uuid", "username"]) })
t.update({ "update_by": item.update_by.to_dict(only=["uuid", "username"]) })
temp.append(t)
result = temp
return result, count, "get role {}.".format("success" if result else "no data")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = None
with db_session:
result = Role.get(uuid=uuid)
if result:
result.set(update_at=datetime.now(), update_by=editor, **data)
commit()
# result = fullStackDB.update(Role, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update role {}.".format("success" if result else "fail")
roleManager = RoleManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import copy
import time
import types
import json
import logging
import traceback
from datetime import datetime
from pony.orm import *
from flask import request
from model import fullStackDB
from model.summary import Summary
from model.user import User
from utils import sql_filter
logger = logging.getLogger("SummaryManager")
class SummaryManager(object):
def __init__(self):
super(SummaryManager, self).__init__()
def add(self, data):
# 判断角色名是否存在
result = Summary.get(name=data.get("name"))
if result:
return False, "summary name has been exists."
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = fullStackDB.add(Summary, **data)
return result, "add summary {}.".format("success" if result else "fail")
def delete(self, uuid):
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Summary, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete summary {}.".format("success" if result else "fail")
def get(self, data):
result = Summary.get(**data)
if result:
result = result.to_dict(only=["uuid", "name", "create_at", "update_at"])
return result, "get summary {}.".format("success" if result else "no data")
def getList(self, data):
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
if 'props' in temp:
temp.pop('props')
temp.setdefault("is_delete", False)
if "scope_type" in data and data.get("scope_type") == "list":
result = Summary.select().where(**temp).order_by(desc(Summary.create_at))
temp = []
fields = ["uuid", "name"]
if "props" in data and isinstance(data.get("props"), list):
fields = data.get("props")
for item in result:
temp.append(item.to_dict(only=fields))
return temp, len(temp), "get summary {}.".format("success" if temp else "fail")
result = fullStackDB.pagination(Summary, Summary.create_at, pagenum=data.get("pagenum", 1), pagesize=data.get("pagesize", 10), **temp)
count = fullStackDB.count(Summary, **temp)
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True)
t.update({ "create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S") })
t.update({ "update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S") })
t.update({ "create_by": item.create_by.to_dict(only=["uuid", "username"]) })
t.update({ "update_by": item.update_by.to_dict(only=["uuid", "username"]) })
temp.append(t)
result = temp
return result, count, "get summary {}.".format("success" if result else "no data")
def update(self, uuid, data):
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Summary, { 'uuid': uuid }, update_at=datetime.now(), update_by=editor, **data)
return result, "update summary {}.".format("success" if result else "fail")
summaryManager = SummaryManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import sys
import copy
import time
import types
import json
import logging
import traceback
import re
import tempfile
import shutil
import base64
import uuid
from hashlib import md5 as fmd5
from urllib import parse
from datetime import datetime
from threading import Thread
from werkzeug.security import check_password_hash
from flask import request
from app.setting import config
from utils import md5_salt, random_string
logger = logging.getLogger("UploadManager")
FileStoragePath = os.getcwd()
# 判断目录是否存在,不存在则创建
# if not os.path.exists(os.path.join(FileStoragePath, config.get("UPLOAD_DIR"))):
# os.makedirs(os.path.join(FileStoragePath, config.get("UPLOAD_DIR")))
def ajaxCheckAccess(path):
realpath = os.path.realpath(path)
if not realpath.startswith(FileStoragePath):
return False
return True
def checkPath(path):
if not path:
return False, {"code": -1, "data": None, "message": "[%s] arg missed!" % path}
fpath = os.path.abspath(os.sep.join(
[os.path.abspath(FileStoragePath), path]))
if not ajaxCheckAccess(fpath):
return False, {"code": -1, "data": None, "message": "You have no access to [%s]!" % fpath}
if not os.path.exists(fpath):
return False, {"code": -1, "data": None, "message": "[%s] is not existed!" % fpath}
return True, os.path.abspath(fpath)
def saveToFile(saveFile, content):
try:
tfn = tempfile.mktemp()
tf = open(tfn, 'w+b')
tf.write(content)
tf.close()
os.rename(tfn, saveFile)
return True
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return False
def getFileInfo(infofile):
info = dict()
info.update({
"isfile": os.path.isfile(infofile),
"isdir": os.path.isdir(infofile),
"size": os.path.getsize(infofile),
"atime": os.path.getatime(infofile),
"mtime": os.path.getmtime(infofile),
"ctime": os.path.getctime(infofile),
"name": os.path.basename(infofile)
})
return info
class UploadManager(object):
def __init__(self):
super(UploadManager, self).__init__()
def download(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if not os.path.isfile(path):
return {"code": -1, "data": None, "message": "Path [%s] is not a valid file!" % path}
try:
with open(path, "rb") as f:
content = base64.b64encode(f.read())
md5code = fmd5(content).hexdigest()
return {
"data": {
"content": content,
"md5": md5code,
"filename": os.path.basename(path)
},
"code": 0,
"message": "download file [%s] successfully!" % obj['path']
}
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return {
"data": None,
"code": -1,
"message": "upload file [%s] failed!\n %s" % (obj['path'], repr(e))
}
def upload(self):
try:
binfile = request.files.get("binfile")
if not binfile:
return None, "file can not be null"
obj = dict()
obj['filename'] = binfile.filename
obj['content'] = binfile.stream.read()
# 目录结构:模块类型/年/月/项目名/文件名_时间日期.文件后缀
# 模块类型:项目管理模块、资质管理模块、
# filename = random_string() + os.path.splitext(obj['filename'])[-1]
current = datetime.now() # 文件重命名后缀
# 拼接文件名
filename = os.path.splitext(obj['filename'])[0] + "_{}".format(current.strftime("%Y%m%d%H%M%S")) + os.path.splitext(obj['filename'])[-1]
# 获取相对路径
relative_path = os.path.join(config.get("UPLOAD_DIR"))
# 获取最终存储的绝对路径
savePath = os.path.normpath(os.sep.join([config.get("UPLOAD_PATH"), relative_path]))
# 获取最终存储的文件路径
saveFile = os.path.normpath(os.sep.join([savePath, filename]))
if not os.path.exists(savePath):
os.makedirs(savePath)
with open(saveFile, 'wb') as f: # 保存文件
f.write(obj['content'])
return {
"uuid": str(uuid.uuid4()), # 附件唯一编号
"filename": obj['filename'], # 附件名称
"filesize": os.path.getsize(saveFile), # 附件大小
"filepath": parse.urljoin(config.get("UPLOAD_SERVER"), '/'.join(os.path.join(relative_path, filename).split('\\'))), # 附件存储路径
}, "upload file [%s] successfully!" % obj['filename']
except Exception as e: # repr(e)
traceback.print_exc()
logger.error(str(e))
return None, repr(e)
def delete(self, data):
try:
isAccessed, path = checkPath(data["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if os.path.isfile(path):
os.remove(path)
return {"code": 0, "data": None, "message": "delete file [%s] successfully!" % path}
elif os.path.isdir(path):
os.rmdir(path)
return {"code": 0, "data": None, "message": "delete dir [%s] successfully!" % path}
else:
return {"code": 0, "data": None, "message": "Path [%s] is not a valid file or path!" % path}
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return {"code": -1, "data": None, "message": repr(e)}
def dirlist(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
result = []
for p in os.listdir(path):
result.append(getFileInfo(os.path.join(FileStoragePath, p)))
return {"code": 0, "result": result, "message": "Get [%s] successfully!" % path}
def filemd5(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if not os.path.isfile(path):
return {"code": -1, "data": None, "message": "Path [%s] is not a valid file!" % path}
with open(path, "rb") as f:
filemd5 = fmd5(f.read()).hexdigest()
return {"code": 0, "result": filemd5, "message": "Get md5 of [%s] successfully!" % path}
def fileinfo(self, data):
obj = json.loads(data)
isAccessed, path = checkPath(obj["path"])
if not isAccessed:
return {"code": -1, "data": None, "message": "invaild access"}
if not os.path.isfile(path):
return {"code": -1, "data": None, "message": "Path [%s] is not a valid file!" % path}
return {"code": 0, "result": getFileInfo(path), "message": "Get md5 of [%s] successfully!" % path}
uploadManager = UploadManager()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import time
import json
import logging
import traceback
import copy
import uuid
from datetime import datetime
from pony.orm import *
from flask import request
from app.setting import config
from model import fullStackDB
from model.user import User
from utils import md5_salt, filter_dict, sql_filter
logger = logging.getLogger("UserManager")
class UserManager(object):
'''
用户管理的单例类
'''
def __init__(self):
super(UserManager, self).__init__()
def add(self, data):
'''
添加用户
'''
# 判断账号是否存在
isExists = select(u for u in User if u.account == data['account'] and u.is_delete == False).exists()
if isExists:
return False, "user already exists"
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
if "role" in data:
role = Role.get(uuid=data.get("role"))
if not role:
return False, "role does not exists"
data.update({ "role": role.id })
if "depot" in data:
# depot = Depot.select().where(uuid=data["depot"]).first()
depot = Depot.get(uuid=data.get("depot"))
if not depot:
return False, "depot does not exists"
data.update({ "depot": depot.id })
if "username" not in data or not data.get("username"):
data.update({ "username": data.get("account") })
# 密码加密
data['password'] = md5_salt(data['password'])
data.update({
"create_by": editor.id,
"create_at": datetime.now(),
"update_by": editor.id,
"update_at": datetime.now()
})
# 添加用户时,是否考虑将该用户的过期时间加入预警
result = fullStackDB.add(User, **data)
return result, "add user {}.".format("success" if result else "fail")
def delete(self, uuid):
'''
删除用户
'''
with db_session:
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
result = User.get(uuid=uuid)
if result:
result.delete()
commit()
result = True
return result, "delete user {}.".format("success" if result else "fail")
def update(self, uuid, data):
'''
更新用户
'''
# 当参数为空时,直接返回错误
if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
return False, "parameters can not be null."
with db_session:
# 查询请求者是否存在
editor = User.get(id=request.current_user.get("id"))
if not editor:
return False, "current user is not exists"
if "password" in data:
data["password"] = md5_salt(data['password'])
if "role" in data:
role = Role.get(uuid=data.get("role"))
if not role:
return False, "role does not exists"
data.update({ "role": role.id })
if "depot" in data:
depot = Depot.get(uuid=data.get("depot"))
if not depot:
return False, "depot does not exists"
data.update({ "depot": depot.id })
user = User.get(uuid=uuid)
if user:
user.set(update_at=datetime.now(), update_by=editor.id, **data)
result = user.to_dict(only=["account", "gender", "birthday", "hometown", "contact", "email",])
if result.get("birthday"):
result.update({ "birthday": result.get("birthday").strftime("%Y-%m-%d") })
return result, "update user success"
else:
return None, "user does not exists"
def get(self, data):
'''
查询单用户
'''
result = User.get(id=request.current_user.get("id"), is_delete=False)
if result:
temp = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "username", "account", "contact", "email", "hometown", "gender", "birthday", "entry_time", "expire_date", "create_at", "update_at"])
temp.update({
"birthday": result.birthday.strftime("%Y-%m-%d") if result.birthday else None,
"create_at": result.create_at.strftime("%Y-%m-%d %H:%M:%S") if result.create_at else None,
"entry_time": result.entry_time.strftime("%Y-%m-%d %H:%M:%S") if result.entry_time else None,
"expire_date": result.expire_date.strftime("%Y-%m-%d %H:%M:%S") if result.expire_date else None,
"update_at": result.update_at.strftime("%Y-%m-%d %H:%M:%S") if result.update_at else None,
})
result = temp
return result, "get user {}.".format("success" if result else "not found")
def getList(self, data):
'''
查询多用户
'''
# 当参数为空时,直接返回错误
if not data or len(data) <= 0:
return False, 0, "parameters can not be null."
# select_sql = "select `id`, `account`, `username` from `{}`".format(User._table_)
# conditions = []
# globals_dict = dict()
# if "id" in data and data.get("id"):
# conditions.append(" id = $id")
# globals_dict.update({ "id": data.get("id") })
# if "account" in data and data.get("account"):
# conditions.append("account = \"$account\"")
# globals_dict.update({ "account": sql_filter(data.get("account")) })
# if "username" in data and data.get("username"):
# conditions.append("username = \"$username\"")
# globals_dict.update({ "username": sql_filter(data.get("username")) })
# if len(conditions):
# select_sql = select_sql + " where " + " and ".join(conditions)
# conditions = []
# select_sql = select_sql + " "
# conditions.append("order by $order")
# globals_dict.update({ "order": sql_filter(data.get("order", "create_at")) })
# conditions.append("limit $limit")
# globals_dict.update({ "limit": data.get("pagesize", 10) })
# conditions.append("offset $offset")
# globals_dict.update({ "offset": (data.get("pagenum", 1) - 1) * data.get("pagesize", 10) })
# result = User.select_by_sql(select_sql + " ".join(conditions), globals=globals_dict)
temp = copy.deepcopy(data)
if 'pagenum' in temp:
temp.pop('pagenum')
if 'pagesize' in temp:
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
if 'role' in temp:
role = Role.get(uuid=temp.get('role'))
if role:
temp.update({ "role": role })
else:
temp.pop('pagenum')
if 'depot' in temp:
depot = Depot.get(uuid=temp.get('depot'))
if depot:
temp.update({ "depot": depot })
else:
temp.pop('pagenum')
temp.setdefault("is_delete", False)
if "scope_type" in data and data.get("scope_type") == "list":
result = User.select().where(**temp).order_by(desc(User.create_at))
temp = []
for item in result:
t = item.to_dict(only=["id", "uuid", "username", "account"])
temp.append(t)
return temp, len(temp), "get select {}.".format("success" if temp else "no data")
result = User.select().where(**temp).order_by(desc(User.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = User.select().where(**temp).count()
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, only=["uuid", "username", "account", "contact", "email", "hometown", "gender", "birthday", "entry_time", "expire_date", "create_at", "update_at", "remarks"])
t.update({
"email": "" if item.email == "user@example.com" else item.email,
"birthday": item.birthday.strftime("%Y-%m-%d") if item.birthday else None,
"create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S"),
"entry_time": item.entry_time.strftime("%Y-%m-%d %H:%M:%S"),
"expire_date": item.expire_date.strftime("%Y-%m-%d %H:%M:%S"),
"update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S"),
})
temp.append(t)
result = temp
return result, count, "get users {}.".format("success" if result else "no data")
userManager = UserManager()
import os
import sys
import getopt
import shutil
import configparser
import PySimpleGUI as sg
iniFilePath = os.path.join(os.getcwd(), "config.ini")
conf = configparser.ConfigParser()
conf.read(iniFilePath)
current_dir = os.getcwd()
project_dir = os.path.dirname(current_dir)
def init_dirs():
new_dirs = [
os.path.join(project_dir, "wwwroot"),
os.path.join(project_dir, "wwwroot", "kxpms"),
os.path.join(project_dir, "wwwroot", "kxpms", conf.get('uploads', 'upload_dir')),
os.path.join(project_dir, "wwwroot", "kxpms", conf.get('uploads', 'netdisc'))
]
for d in new_dirs:
if not os.path.exists(d):
os.mkdir(d)
def update_app_config():
upload_path = os.path.join(project_dir, "wwwroot", "kxpms")
temp = os.path.join(os.getcwd(), "config1.ini")
# fd = open(temp, mode="w", encoding="utf-8")
# fd.close()
shutil.copy(iniFilePath, temp)
cp2 = configparser.ConfigParser()
cp2.read(temp)
sections = conf.sections()
for section in sections:
for item in conf.items(section):
cp2.set(section, item[0], item[1])
cp2.set("uploads", "upload_path", upload_path)
with open(temp, "w+") as f:
cp2.write(f)
shutil.move(temp, iniFilePath)
# os.remove(temp)
conf.read(iniFilePath)
def update_nginx_conf():
source_file = os.path.join(current_dir, "nginx.conf.template")
target_file = os.path.join(project_dir, "nginx-1.18.0", "conf", "nginx.conf")
if os.path.exists(target_file):
os.remove(target_file)
with open(source_file, 'r', encoding="utf8") as src, open(target_file, 'w', encoding="utf8") as dst:
lines = src.readlines()
for content in lines:
if content.find(" listen 80;") != -1:
dst.write(" listen {};\n".format(conf.get('uploads', 'port')))
elif content.find(" server_name localhost;") != -1:
dst.write(" server_name {};\n".format(conf.get('uploads', 'host')))
elif content.find(" root html;") != -1:
dst.write(" root {};\n".format(conf.get('uploads', 'upload_path')))
else:
dst.write(content)
print(target_file, source_file)
# shutil.move(source_file, target_file)
def install_nssm(app_name, app_path):
return os.system("nssm.exe install {} {}".format(app_name, app_path))
# http://nssm.cc/usage
def manage_nssm_service(app_name, cmd):
'''
nssm start <servicename> 启动服务
nssm stop <servicename> 停止服务
nssm restart <servicename> 重启服务
nssm remove <servicename> 删除服务,需要确认
nssm remove <servicename> confirm 删除服务,无需确认
nssm status <servicename>
nssm statuscode <servicename>
nssm rotate <servicename> 服务日志文件滚动
nssm processes <servicename>
'''
services = ['start', 'stop', 'restart', 'remove', 'status', 'processes']
if cmd not in services:
return False
return os.system("nssm.exe {} {}".format(cmd, app_name))
def exec_nssm_env_cmd(app_name, param_dict = {}):
'''
nssm set <servicename> AppParameters -jar slave.jar -secret redacted 服务启动时携带的参数
nssm set <servicename> AppDirectory C:\\Jenkins 服务启动的文件路径
nssm set <servicename> AppStdout C:\\Jenkins\\jenkins.log 服务标准日志输出
nssm set <servicename> AppStderr C:\\Jenkins\\jenkins.log 服务错误日志输出
nssm set <servicename> AppStopMethodSkip 0 在崩溃后或服务正常停止时清理应用程序时使用的各种停止方法和超时
nssm set <servicename> AppStopMethodConsole 1000
nssm set <servicename> AppThrottle 5000 如果app运行时间少于5秒,延迟启动
'''
for key, value in param_dict.items():
res = os.system("nssm.exe set {} {} {}".format(app_name, key, value))
print(res)
def start_nginx_service():
'''
./nginx 启动
./nginx -s stop 停止
./nginx -s quit 退出
./nginx -s reload 重载
'''
nginx_dir = os.path.join(project_dir, "nginx-1.18.0", "nginx.exe")
res = install_nssm(conf.get('application', 'nginx'), nginx_dir)
print(res)
# exec_nssm_env_cmd(conf.get('application', 'nginx'), {
# 'AppParameters': '-s start'
# })
res = manage_nssm_service(conf.get('application', 'nginx'), "start")
print(res)
def start_app_service():
app_dir = os.path.join(current_dir, "start.exe")
res = install_nssm(conf.get('application', 'name'), app_dir)
print(res)
exec_nssm_env_cmd(conf.get('application', 'name'), {
'AppThrottle': '5000'
})
res = manage_nssm_service(conf.get('application', 'name'), "start")
print(res)
def start_service():
start_nginx_service()
start_app_service()
def stop_app_service():
app_dir = os.path.join(current_dir, "start.exe")
res = install_nssm(conf.get('application', 'name'), app_dir)
print(res)
exec_nssm_env_cmd(conf.get('application', 'name'), {
'AppThrottle': '5000'
})
res = manage_nssm_service(conf.get('application', 'name'), "stop")
print(res)
def stop_nginx_service():
nginx_dir = os.path.join(project_dir, "nginx-1.18.0", "nginx.exe")
res = install_nssm(conf.get('application', 'nginx'), nginx_dir)
print(res)
res = manage_nssm_service(conf.get('application', 'nginx'), "start")
print(res)
def stop_service():
stop_app_service()
stop_nginx_service()
def set_nssm_env():
if sys.platform == 'win32':
os.chdir(current_dir)
start_service()
else:
# res = os.system("ls -a")
# print(res)
print("暂不支持在非windows平台部署")
def user_command(argv):
flag = False
value = None
opts, args = getopt.getopt(argv[1:], "a:c:h", ["app=", "cmd=", "help"])
for opt_name, opt_value in opts:
if opt_name in ('-h','--help'):
print('''
usage:
nssm start <servicename> 启动服务
nssm stop <servicename> 停止服务
nssm restart <servicename> 重启服务
nssm remove <servicename> 删除服务,需要确认
nssm remove <servicename> confirm 删除服务,无需确认
nssm status <servicename>
nssm statuscode <servicename>
nssm rotate <servicename> 服务日志文件滚动
nssm processes <servicename>
''')
sys.exit()
if opt_name in ('-a','--app'):
if flag == False:
flag = True
value = opt_value
else:
res = manage_nssm_service(opt_value, value)
if res: print(res)
else: print("[*] unsupport command")
if opt_name in ('-c','--cmd'):
if flag == False:
flag = True
value = opt_value
else:
res = manage_nssm_service(value, opt_value)
if res: print(res)
else: print("[*] unsupport command")
print(argv)
# =======================GUI==========================
start_text = "启动应用"
stop_text = "关闭应用"
restart_text = "重启应用"
start_btn = sg.Button(start_text, button_color=('white', 'springgreen4'))
stop_btn = sg.Button(stop_text, button_color=('white', 'firebrick3'))
restart_btn = sg.Button(restart_text)
layout = [
[start_btn, stop_btn, restart_btn]
]
# Create the Window
window = sg.Window('KXPMS项目管理系统', layout, auto_size_buttons=False, default_button_element_size=(15, 3))
def start_project():
update_app_config()
init_dirs()
update_nginx_conf()
set_nssm_env()
def stop_project():
stop_service()
def run():
# Create the event loop
while True:
event, values = window.read()
if event in (None, start_text): # User closed the Window or hit the Cancel button
start_project()
elif event in (None, stop_text):
stop_project()
elif event in (None, restart_text):
stop_project()
start_project()
else:
continue
if event == sg.WIN_CLOSED:
break
print(f'Event: {event}')
window.close()
def main(argv):
if len(argv) > 1:
user_command(argv)
else:
update_app_config()
init_dirs()
update_nginx_conf()
set_nssm_env()
if __name__ == "__main__":
# main(sys.argv)
run()
\ No newline at end of file
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['deploy.py'],
pathex=['F:\\Wanli\\projects\\kxpms\\backend'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='deploy',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False )
#!/usr/bin/env python
# -*- coding: utf_8 -*-
class PySignal(object):
"""
Simple event class used to provide hooks for different types of events in Locust.
Here's how to use the EventHook class::
my_event = PySignal()
def on_my_event(a, b, **kw):
print "Event was fired with arguments: %s, %s" % (a, b)
my_event += on_my_event
my_event.fire(a="foo", b="bar")
my_event.emit(a="foo", b="bar")
"""
def __init__(self):
self._handlers = []
def __iadd__(self, handler):
return self.connect(handler)
def __isub__(self, handler):
return self.disconnect(handler)
def connect(self, handler):
self._handlers.append(handler)
return self
def disconnect(self, handler):
self._handlers.remove(handler)
return self
def fire(self, *args, **kwargs):
return self.emit(*args, **kwargs)
def emit(self, *args, **kwargs):
rets = {}
for handler in self._handlers:
ret = handler(*args, **kwargs)
rets[handler.__name__] = ret
if len(rets) == 1:
return list(rets.values())[0] # list()用来兼容python3
return rets
if __name__ == '__main__':
my_event = PySignal()
def on_my_event(a, b, **kw):
print(a, b)
print(kw)
my_event.connect(on_my_event)
my_event.fire(1, 2, c="foo", d="bar")
my_event.emit(3, 4, e="foo", f="bar")
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import logging
from logging.handlers import RotatingFileHandler
import os
logPath = os.getcwd() + os.path.sep + "logs"
if not os.path.exists(logPath):
os.makedirs(logPath)
fh = RotatingFileHandler("logs/webapiscraper.log",
maxBytes=10 * 1024 * 1024, backupCount=100)
fh.setLevel(logging.DEBUG)
# log write in console
ch = logging.StreamHandler()
ch.setLevel(logging.WARNING)
# log formatter
formatter = logging.Formatter(
'[%(asctime)s][%(levelname)7s] [%(filename)15s%(funcName)15s%(lineno)06s] %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger = logging.root
logger.setLevel(logging.INFO)
logger.addHandler(fh)
logger.addHandler(ch)
from .auth import Auth
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import sys
import re
import logging
import traceback
import time
from datetime import datetime, timedelta, timezone
from functools import wraps
import jwt
from flask import jsonify, current_app, request
logger = logging.getLogger("auth")
class Auth(object):
def __init__(self):
super(Auth, self).__init__()
@staticmethod
def auth_required(func):
'''
api接口的登录鉴权装饰器
包括cookie和jwt_token鉴权
'''
@wraps(func)
def inner(*args, **kwargs):
if current_app.config.get('LOGIN_DISABLED'):
return func(*args, **kwargs)
auth = Auth()
isSuccess, message = auth.identify(request)
if isSuccess:
return func(*args, **kwargs)
return current_app.unauthorized(message)
return inner
@staticmethod
def encode_auth_token(user_id, username):
"""
生成认证Token
:param user_id: int
:param username: str
:return: bytes
"""
payload = {
'iat': datetime.now(),
'exp': datetime.now() + timedelta(hours=2), # 两个小时后过期
'iss': 'bytecode', # token签发者
'aud': 'bytecode', # token接收者
'sub': user_id, # token所属者
'data': { # payload
'id': user_id,
'username': username
}
}
token = jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256')
if isinstance(token, bytes): # dict 转成json传输时, value中为byte类型会报错
token = str(token, 'utf8')
return token
@staticmethod
def decode_auth_token(auth_token):
"""
验证Token
:param auth_token:
:return: dict|string
"""
try:
# result = re.match(r'[+-/*\w]+\.[+-/*\w]+\.[+/*-\w]+', auth_token, re.I)
# if not result or not result.group():
# return False, "token invaild"
payload = jwt.decode(auth_token, current_app.config['SECRET_KEY'], verify=True, algorithms=['HS256'], options={'require': ['exp', 'iss', 'sub', 'aud', 'iat', 'data']}, audience="bytecode")
if payload:
return True, payload
else:
return False, "payload invaild"
# except jwt.ExpiredSignatureError:
# return 'token expire'
# except jwt.InvalidTokenError:
# return 'token invaild'
except Exception as e:
traceback.print_exc()
return False, str(e)
def identify(self, request):
"""
用户鉴权
:param request: flask的requst全局对象
:return: bool
"""
try:
auth_token = request.headers.get('Authorization')
if auth_token:
isSuccess, result = self.decode_auth_token(auth_token)
print(result)
if isSuccess:
if "data" in result and "id" in result["data"] and "username" in result["data"]:
setattr(request, 'current_user', result['data'])
return True, result['data']
return False, "data invaild"
else:
return False, result
return False, "authorization token can not be none"
except Exception as e:
traceback.print_exc()
logger.error(str(e))
return False, str(e)
class ResponseCode(object):
OK = (200, 'OK')
NO_DATA = (204, 'No data')
NO_DATA_FOUND = (404, 'No data found')
NOTHING_CHANGE = (304, 'Nothing change')
REQUEST_ERROR = (400, 'Request error')
PARAMETER_ERROR = (4001, 'Parameter error')
PARAMETER_NULL = (4002, 'Parameter is null')
PASSWORD_ERROR = (4003, 'Password error')
EXISTS_ERROR = (4004, 'Record already exists')
INVAILD_ROLE_ERROR = (4005, 'Invaild role error')
ACCOUNT_DISABLED = (4006, 'Account is disabled')
AUTHORIZATION_ERROR = (401, 'Authentication error')
INVAILD_REQUEST = (403, 'Invaild request')
DB_ERROR = (5001, 'Database error')
SERVER_ERROR = (5002, 'Server error')
UNKNOWN_ERROR = (5003, 'Unknown error')
def response_result(code, msg=None, data=None, **kwargs):
if msg is None:
msg = code[1]
result = { 'code': code[0], 'message': msg, 'data': data }
result.update(kwargs)
return result
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from app import config
from apscheduler.schedulers.background import BackgroundScheduler
# from apscheduler.jobstores.mongodb import MongoDBJobStore
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
jobstores = {
# 'mongo': MongoDBJobStore(),
'default': SQLAlchemyJobStore(url='sqlite:///{}'.format(config.get("DATABASE_FILE")), engine_options={ 'connect_args': { 'timeout': 15 } })
}
executors = {
'default': ThreadPoolExecutor(20),
'processpool': ProcessPoolExecutor(1)
}
job_defaults = {
'coalesce': False,
'max_instances': 1
}
scheduler = BackgroundScheduler(executors=executors, job_defaults=job_defaults,)
scheduler.start()
\ No newline at end of file
import functools
from flask import request
from marshmallow import Schema, ValidationError
from fullstack.response import ResponseCode, response_result
from app.setting import config
def validate_schema(schema_class: Schema):
def decorator(view_func):
@functools.wraps(view_func)
def inner(*args, **kwargs):
if request.method == 'GET':
form_data = request.args
else:
if request.json:
form_data = request.json
else:
form_data = request.form
try:
data = schema_class().load(form_data)
request.schema_data = data
except ValidationError as e:
if config['DEBUG']:
return response_result(ResponseCode.PARAMETER_ERROR, e.messages if config['DEBUG'] else None)
return view_func(*args, **kwargs)
return inner
return decorator
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import traceback
import logging
from pony.orm import *
from pony.orm.serialization import to_json
from pony.flask import Pony
logger = logging.getLogger("database")
class FullStackDB(object):
def __init__(self):
super(FullStackDB, self).__init__()
self._db = Database()
@property
def db(self):
return self._db
def __call__(self, app=None, drop_tables=[]):
if app:
Pony(app)
self.db.bind(**app.config['PONY'])
for name in drop_tables:
# 删除表,演示实体声明时用于快速清除旧表
self.db.drop_table(name, if_exists=True, with_all_data=True)
self.db.generate_mapping(create_tables=True)
def get(self, table, **kwargs):
'''
得到条目
'''
with db_session():
item = table.get(**kwargs)
return item
def add(self, table, **kwargs):
'''
增加条目
:param table: 操作的数据表
:param **kwargs: 新增条目的属性和值
'''
with db_session():
item = table(**kwargs)
commit()
return item
def delete(self, table, **kwargs):
'''
删除条目
:param table: 操作的数据表
:param **kwargs: 删除条目的属性和值
'''
with db_session():
target = table.get(**kwargs)
if target:
target.delete()
commit()
return True
else:
return False
def update(self, table, filters, **kwargs):
'''
:param item: 需要更新的条目,如 User[1]
:param **kwargs: 更新后条目的属性和值
'''
with db_session():
item = table.get(**filters)
if item:
for key, value in kwargs.items():
if value != None and hasattr(item, key):
setattr(item, key, value)
commit()
return item
else:
return False
def display(self, table):
'''
展示表格的所有条目信息
:param table: 操作的数据表
:return 成功则返回一个包含所有条目的列表 | 失败返回False
'''
with db_session():
items = select(item for item in table)[:]
items.show()
return items
def select(self, table, **kwargs):
with db_session():
return table.select(**kwargs)
def pagination(self, table, order, pagenum=1, pagesize=10, **kwargs):
if not isinstance(pagenum, int):
pagenum = int(pagenum)
if not isinstance(pagesize, int):
pagesize = int(pagesize)
with db_session():
return table.select().where(**kwargs).order_by(desc(order)).page(pagenum, pagesize)
def pagination_dict(self, table, order, pagenum=1, pagesize=10, **kwargs):
if not isinstance(pagenum, int):
pagenum = int(pagenum)
if not isinstance(pagesize, int):
pagesize = int(pagesize)
with db_session():
result = table.select().where(**kwargs).order_by(desc(order)).page(pagenum, pagesize)
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True)
for key in t:
if isinstance(t[key], self.db.Entity):
t[key] = t[key].to_dict()
temp.append(t)
return temp
def count(self, table, **kwargs):
with db_session():
return table.select().where(**kwargs).count()
fullStackDB = FullStackDB()
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set, LongStr, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class Annex(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "annex"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app_id = Optional("Apps", reverse="app_annex")
title = Required(str, max_len=200) # 文件名
path = Required(LongStr) # 文件路径
type = Required(int, default=0) # 文件类型 PNG/JPG/GIF/MP3/MP4/DOCX/XLSX/PPT/PDF...
size = Required(float, default=0) # 文件大小
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse="annex_creator") # Annex与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse="annex_updater") # Annex与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse="annex_deleter") # Annex与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set, LongStr, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class Apps(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "apps"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app_name = Required(str, max_len=200)
app_version = Optional(str, default="")
app_logo = Optional(str, default="")
app_desc = Optional(str, default="")
app_annex = Set("Annex", reverse="app_id")
app_build_log = Set("BuildLogs", reverse="app_id")
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='apps_creator') # BuildLogs与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='apps_updater') # BuildLogs与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='apps_deleter') # BuildLogs与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set, LongStr, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class BuildLogs(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "build_logs"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app_id = Optional("Apps", reverse="app_build_log")
app_path = Optional(str, default="")
app_info = Optional(Json, default={})
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='build_logs_creator') # BuildLogs与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='build_logs_updater') # BuildLogs与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='build_logs_deleter') # BuildLogs与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set
from app import config
from . import fullStackDB
db = fullStackDB.db
class Dict(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "dictionary"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
label = Required(str)
value = Required(str)
category = Required(str)
# project_type = Optional("Project", reverse="type") # Project的type字段引用Dict模型,一对一关系
# project_status = Optional("Project", reverse="status") # Project的status字段引用Dict模型,一对一关系
# flow_status = Optional("Flow", reverse="status") # 流程节点状态
# payback_status = Optional("Payback", reverse="status") # 回款节点状态
is_system = Required(bool, default=False) # 能否删除
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='dict_creator') # Dict与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='dict_updater') # Dict与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='dict_deleter') # Dict与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set, LongStr, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class Netdisc(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "netdisc"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
name = Required(str, max_len=200) # 文件名
size = Required(int, default=0) # 文件大小
file_type = Required(str) # 文件类型
is_dir = Required(bool, default=False) # 是否是目录
parent_dir = Required(str, default='/') # 上级目录
real_path = Required(str) # 真实路径
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='netdisc_creator') # NetDisc与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='netdisc_updater') # NetDisc与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='netdisc_deleter') # NetDisc与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime
from pony.orm import PrimaryKey, Required, Optional, Set, LongStr, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class Summary(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "summary"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
name = Required(str, max_len=200) # 总结标题
year_supervise_churn_rate = Required(float) # 年度监督流失率
year_recert_churn_rate = Required(float) # 年度再认证流失率
year_satis_churn_rate = Required(float) # 年度顾客满意率
year_dispatch_site_days = Required(int) # 年度调派技术现场总人天数
year_receiv_collection_rate = Required(float) # 年度应收款回款率
year_bad_project = Required(int) # 年度列入坏账并终止项目数
year_bad_debt_amount = Required(float) # 年度坏账金额
indus_project_rate = Required(float) # 行业项目比率
indus_project_count = Required(int) # 行业项目数量
channel_project_rate = Required(float) # 渠道开发项目比率
channel_project_count = Required(int) # 渠道开发项目数量
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='summary_creator') # Summary与User一对一关系
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='summary_updater') # Summary与User一对一关系
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='summary_deleter') # Summary与User一对一关系
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import uuid
from datetime import datetime, date
from pony.orm import PrimaryKey, Required, Optional, Set, Json
from app import config
from . import fullStackDB
db = fullStackDB.db
class User(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "user"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
account = Required(str, unique=True) # 账号
username = Required(str, max_len=100) # 用户名
password = Required(str, max_len=64)
gender = Required(int, size=8) # 性别,未知0 男1 女2
birthday = Optional(date, default=date.today()) # 使用age会带来age无法随时间变化问题
contact = Required(str, max_len=11) # 联系方式
email = Optional(str, max_len=100) # 邮箱
hometown = Optional(str, max_len=50) # 籍贯
entry_time = Required(datetime, default=datetime.now) # 入职时间
expire_date = Required(datetime, default=datetime.now) # 劳动合同到期时间
create_at = Required(datetime, default=datetime.now)
create_by = Required(int)
update_at = Required(datetime, default=datetime.now)
update_by = Required(int)
delete_at = Optional(datetime)
delete_by = Optional(int)
is_delete = Required(bool, default=False)
sort = Optional(int, size=32, default=0)
remarks = Optional(str, max_len=255, default="", nullable=True)
annex_creator = Set('Annex', reverse='create_by')
annex_updater = Set('Annex', reverse='update_by')
annex_deleter = Set('Annex', reverse='delete_by')
apps_creator = Set('Apps', reverse='create_by')
apps_updater = Set('Apps', reverse='update_by')
apps_deleter = Set('Apps', reverse='delete_by')
build_logs_creator = Set('BuildLogs', reverse='create_by')
build_logs_updater = Set('BuildLogs', reverse='update_by')
build_logs_deleter = Set('BuildLogs', reverse='delete_by')
\ No newline at end of file
{
"count": 84
}
\ No newline at end of file
from marshmallow import Schema
class BaseSchema(Schema):
pass
\ No newline at end of file
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
flow = fields.UUID(required=False)
project = fields.UUID(required=False)
title = fields.String(required=True)
path = fields.String(required=True)
size = fields.Float(required=True)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
flow = fields.UUID(required=False)
title = fields.String(required=False)
path = fields.String(required=False)
type = fields.Int(required=False)
size = fields.Float(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
title = fields.String(required=False)
project = fields.Int(required=False)
flow = fields.Int(required=False)
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
title = fields.String(required=False)
path = fields.String(required=False)
type = fields.Int(required=False)
size = fields.Float(required=False)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
name = fields.String(required=True, validate=validate.Length(min=2, max=50))
class Meta:
unknown = EXCLUDE
class UpdatePasswordSchema(BaseSchema):
uuid = fields.UUID(required=True)
password = fields.String(required=True, validate=validate.Length(min=6, max=50))
newPassword = fields.String(required=True, validate=validate.Length(min=6, max=50))
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
name = fields.String(required=False, validate=validate.Length(min=2, max=20))
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
name = fields.String(required=True, validate=validate.Length(min=2, max=50))
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
class GetRoleUser(BaseSchema):
roles = fields.List(fields.String, required=True)
class Meta:
unknown = EXCLUDE
class ExportProject(BaseSchema):
project = fields.List(fields.String, required=True)
production = fields.List(fields.String, required=True)
condition = fields.Dict(required=False)
class Meta:
unknown = EXCLUDE
\ No newline at end of file
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
app_name = fields.String(required=True)
app_version = fields.String(required=False)
app_logo = fields.String(required=False)
app_desc = fields.String(required=False)
app_files = fields.List(fields.Dict, required=False)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
app_name = fields.String(required=False)
app_version = fields.String(required=False)
app_logo = fields.String(required=False)
app_desc = fields.String(required=False)
app_files = fields.List(fields.Dict, required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
app_name = fields.String(required=False)
scope_type = fields.String(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
app_name = fields.String(required=False)
scope_type = fields.String(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
label = fields.String(required=True, validate=validate.Length(min=1, max=50))
value = fields.String(required=True, validate=validate.Length(min=1, max=50))
category = fields.String(required=True, validate=validate.Length(min=1, max=50))
sort = fields.Integer(required=False, default=0, allow_none=True)
remarks = fields.String(required=False, default=" ", allow_none=True)
is_system = fields.Boolean(required=False, default=False, allow_none=True)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
label = fields.String(required=False, validate=validate.Length(min=1, max=50))
value = fields.String(required=False, validate=validate.Length(min=1, max=50))
category = fields.String(required=False, validate=validate.Length(min=1, max=50))
sort = fields.Integer(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
is_category = fields.Integer(required=False)
label = fields.String(required=False, validate=validate.Length(min=1, max=20))
value = fields.String(required=False, validate=validate.Length(min=1, max=20))
category = fields.List(fields.String(validate=validate.Length(min=1, max=50)), required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
enabld_delete = fields.Boolean(required=True,)
label = fields.String(required=False, validate=validate.Length(min=1, max=50))
value = fields.String(required=False, validate=validate.Length(min=1, max=50))
category = fields.String(required=False, validate=validate.Length(min=1, max=50))
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class LoginSchema(BaseSchema):
account = fields.String(required=True, validate=validate.Length(min=3, max=64))
password = fields.String(required=True, validate=validate.Length(min=3, max=64))
class Meta:
unknown = EXCLUDE
class RegisterSchema(BaseSchema):
account = fields.String(required=True, validate=validate.Length(min=3, max=20))
username = fields.String(required=True, validate=validate.Length(min=3, max=20))
password = fields.String(required=True, validate=validate.Length(min=3, max=18))
email = fields.Email(required=False, missing="user@example.com")
contact = fields.String(required=True, validate=validate.Length(min=11, max=11))
gender = fields.Int(required=True,)
birthday = fields.DateTime(missing=None)
hometown = fields.String(missing="")
role = fields.Int(required=True)
depot = fields.Int(required=True)
entry_time = fields.DateTime(required=True)
expire_date = fields.DateTime(required=True)
class Meta:
unknown = EXCLUDE
\ No newline at end of file
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
name = fields.String(required=False)
parent_dir = fields.String(required=False)
file_type = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
name = fields.String(required=True)
parent_dir = fields.String(required=False)
file_type = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
uuids = fields.List(fields.UUID, required=True)
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
name = fields.String(required=False)
parent_dir = fields.String(required=False)
file_type = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
name = fields.String(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
title = fields.String(required=True, validate=validate.Length(min=2, max=50))
funds = fields.Float(required=True)
type = fields.Int(required=True)
status = fields.Int(required=True, default=1)
project = fields.UUID(required=False)
plan_time = fields.DateTime(required=False)
real_time = fields.DateTime(required=True)
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
title = fields.String(required=False, validate=validate.Length(min=2, max=50))
funds = fields.Float(required=False)
type = fields.Int(required=False)
status = fields.Int(required=False) # 回款状态
plan_time = fields.DateTime(required=False)
real_time = fields.DateTime(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
title = fields.String(required=False, validate=validate.Length(min=2, max=20))
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=False)
funds = fields.Float(required=True)
type = fields.Int(required=False)
project = fields.Int(required=False)
title = fields.String(required=True, validate=validate.Length(min=2, max=50))
plan_time = fields.DateTime(required=True)
real_time = fields.DateTime(required=True)
create_at = fields.DateTime(required=False, default=datetime.now)
update_at = fields.DateTime(required=False, default=datetime.now)
class Meta:
unknown = INCLUDE
from datetime import datetime
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddProjectSchema(BaseSchema):
type = fields.String(required=False, allow_none=True)
title = fields.String(required=True, validate=validate.Length(min=2, max=50))
code = fields.String(required=False, allow_none=True)
amount = fields.Decimal(required=False, default=0, allow_none=True) # 总金额
consult_type = fields.String(required=False, allow_none=True) # 咨询项目类型
contract_sign_at = fields.String(required=False, allow_none=True) # 项目签订日期
party_a = fields.String(required=False, allow_none=True) # 项目甲方
party_b = fields.String(required=False, allow_none=True) # 项目乙方
leader = fields.String(required=False, allow_none=True) # 项目开发人
level = fields.String(required=False, allow_none=True) # 项目开发级别
source = fields.String(required=False, allow_none=True) # 项目来源
introducer = fields.String(required=False, allow_none=True) # 同业引进人
standard_type = fields.String(required=False, allow_none=True) # 体系类型
review_type = fields.String(required=False, allow_none=True) # 审核类型
customer_addr = fields.String(required=False, allow_none=True) # 客户地址
customer_contact = fields.String(required=False, allow_none=True) # 客户联系人
customer_phone = fields.String(required=False, allow_none=True) # 客户联系电话
ascription = fields.String(required=False, allow_none=True) # 项目归属
risk = fields.String(required=False, allow_none=True) # 风险级别
people_nums = fields.Int(required=False, allow_none=True) # 人数
start_time = fields.DateTime(required=True, default=datetime.now) # 项目开始时间
end_time = fields.DateTime(required=True, default=datetime.now) # 项目结束时间
users = fields.List(fields.String(), required=True) # 项目参与者
flow = fields.List(fields.Dict(), required=False, allow_none=True) # 流程节点列表
payback = fields.List(fields.Dict(), required=False, allow_none=True) # 回款计划列表
production = fields.Dict(required=False, allow_none=True) # 项目费用相关
remarks = fields.String(required=False, allow_none=True) # 备注
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class QueryPaybackSchema(BaseSchema):
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class DeleteProjectUserSchema(BaseSchema):
uuid = fields.UUID(required=True)
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class ModifyProjectUserSchema(BaseSchema):
users = fields.List(fields.UUID, required=True)
project = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class UpdateFlowSchema(BaseSchema):
flow = fields.List(fields.Dict(required=True), required=True)
uuid = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class UpdatePaybackSchema(BaseSchema):
payback = fields.List(fields.Dict(required=True), required=True)
uuid = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
class UpdateProductionSchema(BaseSchema):
production = fields.Dict(required=True)
uuid = fields.UUID(required=True)
class Meta:
unknown = EXCLUDE
\ No newline at end of file
from . import BaseSchema
class TokenSchema(BaseSchema):
pass
\ No newline at end of file
from . import BaseSchema
from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
'''
默认情况下,如果在架构中遇到不匹配的键,load将引发a 。ValidationErrorField
可以使用unknown选项修改此行为,该选项接受以下之一:
RAISE(默认):ValidationError 如果存在未知字段,则引发
EXCLUDE:排除未知字段
INCLUDE:接受并包含未知字段
您可以unknown在类的Meta中指定Schema
'''
class AddSchema(BaseSchema):
account = fields.String(required=True, validate=validate.Length(min=2, max=20))
username = fields.String(required=False, validate=validate.Length(min=2, max=20))
password = fields.String(required=True, validate=validate.Length(min=6, max=18))
email = fields.Email(required=False)
contact = fields.String(required=True, validate=validate.Length(min=11, max=11))
gender = fields.Int(required=True)
birthday = fields.Date(missing=None)
hometown = fields.String(missing="")
role = fields.UUID(required=True)
depot = fields.UUID(required=True)
entry_time = fields.DateTime(required=False, nullable=True)
expire_date = fields.DateTime(required=False, nullable=True)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class DeleteSchema(BaseSchema):
class Meta:
unknown = EXCLUDE
class UpdateSchema(BaseSchema):
uuid = fields.UUID(required=False)
account = fields.String(required=False, validate=validate.Length(min=2, max=20))
username = fields.String(required=False, validate=validate.Length(min=2, max=20))
email = fields.Email(required=False)
contact = fields.String(required=False, validate=validate.Length(min=11, max=11))
gender = fields.Int(required=False)
birthday = fields.Date(required=False)
hometown = fields.String(required=False)
role = fields.UUID(required=False)
depot = fields.UUID(required=False)
entry_time = fields.DateTime(required=False)
expire_date = fields.DateTime(required=False)
remarks = fields.String(required=False)
class Meta:
unknown = EXCLUDE
class QuerySchema(BaseSchema):
uuid = fields.UUID(required=False)
scope_type = fields.String(required=False)
role = fields.UUID(required=False)
depot = fields.UUID(required=False)
pagenum = fields.Int(required=False)
pagesize = fields.Int(required=False, max=50) # 防止用户传特别大的数,导致数据库查询阻塞
class Meta:
unknown = EXCLUDE
class ResponseSchema(BaseSchema):
uuid = fields.UUID(required=True)
account = fields.String(required=True, validate=validate.Length(min=2, max=20))
username = fields.String(required=True, validate=validate.Length(min=2, max=20))
password = fields.String(required=True, validate=validate.Length(min=6, max=18))
email = fields.Email(required=False)
contact = fields.String(required=True, validate=validate.Length(min=11, max=11))
gender = fields.Int(required=True)
birthday = fields.Date(required=False)
hometown = fields.String(required=False)
role = fields.Int(required=True)
depot = fields.Int(required=True)
entry_time = fields.DateTime(required=True)
expire_date = fields.DateTime(required=True)
remarks = fields.String(required=True)
class Meta:
unknown = INCLUDE
\ No newline at end of file
# -*- coding: utf-8 -*-
from cx_Freeze import setup, Executable
executables = [
Executable("./start.py")
]
setup(
name="kxpms",
version="1.0",
description="a project manager system",
executables=executables
)
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import sys
import os
import signal
from fullstack.log import logger
from tornado.wsgi import WSGIContainer
from tornado.web import Application, RequestHandler, FallbackHandler
from tornado.ioloop import IOLoop
from tornado.autoreload import watch
from view import app, NotifyHandler, ThreadNotifyHandler
from datetime import datetime
from app import config, signalManager
def terminal_application(a, b):
IOLoop.instance().stop()
print("Good Bye!!!")
class VueHandler(RequestHandler):
def get(self):
remote_ip = self.request.remote_ip
logger.info("remote_ip %s" % remote_ip)
self.render("index.html")
def start():
settings = {
'debug': config['DEBUG'],
'template_path': config['TEMPLATE_PATH'],
'static_path': config['STATIC_PATH'],
'static_url_path': '',
}
watch(os.sep.join([os.getcwd(), "restart.json"]))
wsgi_app = WSGIContainer(app)
application = Application([
(r'/', VueHandler),
(r'/index', VueHandler),
(r'/ws/api/v1/notify', NotifyHandler),
(r'/ws/api/v1/threadnotify', ThreadNotifyHandler),
(r'.*', FallbackHandler, dict(fallback=wsgi_app))
], **settings)
if len(sys.argv) == 2:
port = int(sys.argv[1])
application.listen(port, address=config['HOST'])
else:
port = config['PORT']
application.listen(port, address=config['HOST'])
print(config['LOGO'])
print("server running at %s:%d" % (config['HOST'], port))
if sys.platform == "linux":
# 子进程退出后向父进程发送的信号
signal.signal(signal.SIGCHLD, terminal_application)
# 主进程退出信号
signal.signal(signal.SIGINT, terminal_application)
signal.signal(signal.SIGTERM, terminal_application)
IOLoop.instance().start()
if __name__ == '__main__':
start()
\ No newline at end of file
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['start.py'],
pathex=['F:\\Wanli\\projects\\kxpms\\backend'],
binaries=[],
datas=[],
hiddenimports=['pony', 'pony.orm.dbproviders', 'pony.orm.dbproviders.sqlite'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='start',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True )
This source diff could not be displayed because it is too large. You can view the blob instead.
.app-container>div.page-wrapper[data-v-100bc932]{margin:10px 0}
\ No newline at end of file
.wscn-http404-container[data-v-5b545914]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-5b545914]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-5b545914]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-5b545914]{width:100%}.wscn-http404 .pic-404__child[data-v-5b545914]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-5b545914]{width:80px;top:17px;left:220px;opacity:0;-webkit-animation-name:cloudLeft-data-v-5b545914;animation-name:cloudLeft-data-v-5b545914;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-5b545914]{width:46px;top:10px;left:420px;opacity:0;-webkit-animation-name:cloudMid-data-v-5b545914;animation-name:cloudMid-data-v-5b545914;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1.2s;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-5b545914]{width:62px;top:100px;left:500px;opacity:0;-webkit-animation-name:cloudRight-data-v-5b545914;animation-name:cloudRight-data-v-5b545914;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}@-webkit-keyframes cloudLeft-data-v-5b545914{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudLeft-data-v-5b545914{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@-webkit-keyframes cloudMid-data-v-5b545914{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudMid-data-v-5b545914{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@-webkit-keyframes cloudRight-data-v-5b545914{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}@keyframes cloudRight-data-v-5b545914{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-5b545914]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-5b545914]{font-size:32px;line-height:40px;color:#1482f0;margin-bottom:20px;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-5b545914],.wscn-http404 .bullshit__oops[data-v-5b545914]{font-weight:700;opacity:0;-webkit-animation-name:slideUp-data-v-5b545914;animation-name:slideUp-data-v-5b545914;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__headline[data-v-5b545914]{font-size:20px;line-height:24px;color:#222;margin-bottom:10px;-webkit-animation-delay:.1s;animation-delay:.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-5b545914]{font-size:13px;line-height:21px;color:grey;margin-bottom:30px;-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-5b545914],.wscn-http404 .bullshit__return-home[data-v-5b545914]{opacity:0;-webkit-animation-name:slideUp-data-v-5b545914;animation-name:slideUp-data-v-5b545914;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__return-home[data-v-5b545914]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;font-size:14px;line-height:36px;cursor:pointer;-webkit-animation-delay:.3s;animation-delay:.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes slideUp-data-v-5b545914{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slideUp-data-v-5b545914{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-0aa5646b]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-f226f22c]{margin:10px 0}
\ No newline at end of file
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}.user-login .user-login-bg{position:absolute;top:0;left:0;right:0;bottom:0;background-size:cover}.user-login .el-checkbox__label{color:#999;font-size:13px}.user-login .content-wrapper{position:absolute;top:-100px;left:0;right:0;bottom:0;max-width:1080px;margin:0 auto;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.user-login .content-wrapper .slogan{text-align:center;color:#409eff;font-size:36px;letter-spacing:2px;line-height:48px}.user-login .form-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:30px 40px;background-color:#fff;border-radius:6px;-webkit-box-shadow:1px 1px 2px #eee;box-shadow:1px 1px 2px #eee}.user-login .el-form-item{margin-bottom:15px}.user-login .form-Item{position:relative;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.user-login .form-line{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.user-login .form-line:after{content:"";position:absolute;bottom:3px;left:0;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;border-width:1px;border-style:solid;border-top:0;border-left:0;border-right:0;border-color:#dcdcdc;border-radius:0}.user-login .el-input{width:240px}.user-login .el-input input{border:none;margin:0;padding-left:10px;font-size:13px}.user-login .form-title{margin:0 0 20px;text-align:center;color:#3080fe;letter-spacing:12px}.user-login .input-icon{color:#999}.user-login .checkbox{margin-left:5px}.user-login .submit-btn{margin-bottom:25px;width:100%;background:#3080fe;border-radius:28px}.user-login .link{color:#999;text-decoration:none;font-size:13px}.user-login .line{color:#dcd6d6;margin:0 8px}@media screen and (max-width:720px){.user-login .content-wrapper{margin:20px auto;top:40px;max-width:300px;display:block}.user-login .content-wrapper .slogan{color:#666;font-size:22px;line-height:30px}}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-bc6c305e]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-7c8657b2]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-bb35bc92]{margin:10px 0}
\ No newline at end of file
.panel-group .card-panel-col[data-v-fc50af00]{margin-bottom:32px}.panel-group .card-panel[data-v-fc50af00]{height:108px;cursor:pointer;font-size:12px;position:relative;overflow:hidden;color:#666;background:#fff;-webkit-box-shadow:4px 4px 40px rgba(0,0,0,.05);box-shadow:4px 4px 40px rgba(0,0,0,.05);border-color:rgba(0,0,0,.05)}.panel-group .card-panel:hover .icon-people[data-v-fc50af00]{color:#40c9c6}.panel-group .card-panel:hover .icon-message[data-v-fc50af00]{color:#36a3f7}.panel-group .card-panel:hover .icon-money[data-v-fc50af00]{color:#f4516c}.panel-group .card-panel:hover .icon-shopping[data-v-fc50af00]{color:#ff8000}.panel-group .card-panel .card-panel-icon-wrapper[data-v-fc50af00]{color:#fff}.panel-group .card-panel .icon-people[data-v-fc50af00]{background:#40c9c6}.panel-group .card-panel .icon-message[data-v-fc50af00]{background:#36a3f7}.panel-group .card-panel .icon-money[data-v-fc50af00]{background:#f4516c}.panel-group .card-panel .icon-shopping[data-v-fc50af00]{background:#ff8000}.panel-group .card-panel .card-panel-icon-wrapper[data-v-fc50af00]{float:left;padding:18px;-webkit-transition:all .38s ease-out;transition:all .38s ease-out}.panel-group .card-panel .card-panel-icon[data-v-fc50af00]{float:left;font-size:48px}.panel-group .card-panel .card-panel-description[data-v-fc50af00]{float:right;font-weight:700;margin:26px;margin-left:0}.panel-group .card-panel .card-panel-description .card-panel-text[data-v-fc50af00]{line-height:18px;color:rgba(0,0,0,.45);font-size:16px;margin-bottom:12px}.panel-group .card-panel .card-panel-description .card-panel-num[data-v-fc50af00]{font-size:20px}@media (max-width:550px){.card-panel-description[data-v-fc50af00]{display:none}.card-panel-icon-wrapper[data-v-fc50af00]{float:none!important;width:100%;height:100%;margin:0!important}.card-panel-icon-wrapper .svg-icon[data-v-fc50af00]{display:block;margin:14px auto!important;float:none!important}}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-6dbc3a21]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-82e9c920]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-91c4f7f4]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-77162fb0]{margin:10px 0}
\ No newline at end of file
.panel-group .card-panel-col[data-v-fc50af00]{margin-bottom:32px}.panel-group .card-panel[data-v-fc50af00]{height:108px;cursor:pointer;font-size:12px;position:relative;overflow:hidden;color:#666;background:#fff;-webkit-box-shadow:4px 4px 40px rgba(0,0,0,.05);box-shadow:4px 4px 40px rgba(0,0,0,.05);border-color:rgba(0,0,0,.05)}.panel-group .card-panel:hover .icon-people[data-v-fc50af00]{color:#40c9c6}.panel-group .card-panel:hover .icon-message[data-v-fc50af00]{color:#36a3f7}.panel-group .card-panel:hover .icon-money[data-v-fc50af00]{color:#f4516c}.panel-group .card-panel:hover .icon-shopping[data-v-fc50af00]{color:#ff8000}.panel-group .card-panel .card-panel-icon-wrapper[data-v-fc50af00]{color:#fff}.panel-group .card-panel .icon-people[data-v-fc50af00]{background:#40c9c6}.panel-group .card-panel .icon-message[data-v-fc50af00]{background:#36a3f7}.panel-group .card-panel .icon-money[data-v-fc50af00]{background:#f4516c}.panel-group .card-panel .icon-shopping[data-v-fc50af00]{background:#ff8000}.panel-group .card-panel .card-panel-icon-wrapper[data-v-fc50af00]{float:left;padding:18px;-webkit-transition:all .38s ease-out;transition:all .38s ease-out}.panel-group .card-panel .card-panel-icon[data-v-fc50af00]{float:left;font-size:48px}.panel-group .card-panel .card-panel-description[data-v-fc50af00]{float:right;font-weight:700;margin:26px;margin-left:0}.panel-group .card-panel .card-panel-description .card-panel-text[data-v-fc50af00]{line-height:18px;color:rgba(0,0,0,.45);font-size:16px;margin-bottom:12px}.panel-group .card-panel .card-panel-description .card-panel-num[data-v-fc50af00]{font-size:20px}@media (max-width:550px){.card-panel-description[data-v-fc50af00]{display:none}.card-panel-icon-wrapper[data-v-fc50af00]{float:none!important;width:100%;height:100%;margin:0!important}.card-panel-icon-wrapper .svg-icon[data-v-fc50af00]{display:block;margin:14px auto!important;float:none!important}}.dashboard-editor-container[data-v-be22dad2]{padding:32px;background-color:#f0f2f5;position:relative}.dashboard-editor-container .github-corner[data-v-be22dad2]{position:absolute;top:0;border:0;right:0}.dashboard-editor-container .grid-content[data-v-be22dad2]{font-size:13px;background:#fff;min-height:210px}.dashboard-editor-container .grid-content>p.title[data-v-be22dad2]{color:#303133;margin-top:15px;margin-bottom:0;background:#f2f6fc;border-bottom:1px solid #ebeef5;padding:10px}.dashboard-editor-container .grid-content>div.content[data-v-be22dad2]{padding:10px;overflow:auto}.dashboard-editor-container .grid-content>div.content>p[data-v-be22dad2]{margin:10px 0}.dashboard-editor-container .grid-content>div.content>table tr td[data-v-be22dad2]{min-width:70px;height:24px}.dashboard-editor-container .chart-wrapper[data-v-be22dad2]{height:332px;background:#fff;padding:16px 16px 0}@media (max-width:1024px){.chart-wrapper[data-v-be22dad2]{padding:8px}}
\ No newline at end of file
.box-center[data-v-7c8c832a]{margin:0 auto;display:table}.text-muted[data-v-7c8c832a]{color:#777}.user-profile .user-name[data-v-7c8c832a]{font-weight:700}.user-profile .box-center[data-v-7c8c832a]{padding-top:10px}.user-profile .user-role[data-v-7c8c832a]{padding-top:10px;font-weight:400;font-size:14px}.user-profile .box-social[data-v-7c8c832a]{padding-top:30px}.user-profile .box-social .el-table[data-v-7c8c832a]{border-top:1px solid #dfe6ec}.user-profile .user-follow[data-v-7c8c832a]{padding-top:20px}.user-bio[data-v-7c8c832a]{margin-top:20px;color:#606266}.user-bio span[data-v-7c8c832a]{padding-left:4px}.user-bio .user-bio-section[data-v-7c8c832a]{font-size:14px;padding:15px 0}.user-bio .user-bio-section .user-bio-section-header[data-v-7c8c832a]{border-bottom:1px solid #dfe6ec;padding-bottom:10px;margin-bottom:10px;font-weight:700}
\ No newline at end of file
@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.eot?t=1601822003589);src:url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.eot?t=1601822003589#iefix) format("embedded-opentype"),url("data:application/x-font-woff2;charset=utf-8;base64,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") format("woff2"),url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.woff?t=1601822003589) format("woff"),url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.ttf?t=1601822003589) format("truetype"),url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.svg?t=1601822003589#iconfont) format("svg")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-file:before{content:"\e61a"}.icon-compressed-file:before{content:"\e61b";color:#f4c446}.icon-xml:before{content:"\e66e";color:#fc7b24}.icon-audio:before{content:"\e8a4";color:#379fd3}.icon-text:before{content:"\e60d";color:#f9ca06}.icon-video:before{content:"\e609";color:#8095ff}.icon-zip:before{content:"\e60b"}.icon-excel:before{content:"\e6d6";color:#107b0f}.icon-pdf:before{content:"\e64f";color:#dc2e1b}.icon-ppt:before{content:"\e642";color:#d24625}.icon-html:before{content:"\e667";color:#f7622c}.icon-psd:before{content:"\e66a"}.icon-rtf:before{content:"\e66b"}.icon-image:before{content:"\e606";color:#1296db}.icon-doc:before{content:"\e623";color:#0d47a1}.icon-grid:before{content:"\e6ef"}.icon-list:before{content:"\e67a"}.matter-icon[data-v-5a60069c]{font-size:25px}.matter-title[data-v-5a60069c]{top:-5px;display:inline;margin-left:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:relative}
\ No newline at end of file
.user-activity .user-block .description[data-v-1066d76c],.user-activity .user-block .username[data-v-1066d76c]{display:block;margin-left:50px;padding:2px 0}.user-activity .user-block .username[data-v-1066d76c]{font-size:16px;color:#000}.user-activity .user-block[data-v-1066d76c] :after{clear:both}.user-activity .user-block .img-circle[data-v-1066d76c]{border-radius:50%;width:40px;height:40px;float:left}.user-activity .user-block span[data-v-1066d76c]{font-weight:500;font-size:12px}.user-activity .post[data-v-1066d76c]{font-size:14px;border-bottom:1px solid #d2d6de;margin-bottom:15px;padding-bottom:15px;color:#666}.user-activity .post .image[data-v-1066d76c]{width:100%;height:100%}.user-activity .post .user-images[data-v-1066d76c]{padding-top:20px}.user-activity .list-inline[data-v-1066d76c]{padding-left:0;margin-left:-5px;list-style:none}.user-activity .list-inline li[data-v-1066d76c]{display:inline-block;padding-right:5px;padding-left:5px;font-size:13px}.user-activity .list-inline .link-black[data-v-1066d76c]:focus,.user-activity .list-inline .link-black[data-v-1066d76c]:hover{color:#999}.box-center[data-v-1066d76c]{margin:0 auto;display:table}.text-muted[data-v-1066d76c]{color:#777}
\ No newline at end of file
@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.eot?t=1601822003589);src:url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.eot?t=1601822003589#iefix) format("embedded-opentype"),url("data:application/x-font-woff2;charset=utf-8;base64,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") format("woff2"),url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.woff?t=1601822003589) format("woff"),url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.ttf?t=1601822003589) format("truetype"),url(//at.alicdn.com/t/font_2113109_7bz8s7j187s.svg?t=1601822003589#iconfont) format("svg")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-file:before{content:"\e61a"}.icon-compressed-file:before{content:"\e61b";color:#f4c446}.icon-xml:before{content:"\e66e";color:#fc7b24}.icon-audio:before{content:"\e8a4";color:#379fd3}.icon-text:before{content:"\e60d";color:#f9ca06}.icon-video:before{content:"\e609";color:#8095ff}.icon-zip:before{content:"\e60b"}.icon-excel:before{content:"\e6d6";color:#107b0f}.icon-pdf:before{content:"\e64f";color:#dc2e1b}.icon-ppt:before{content:"\e642";color:#d24625}.icon-html:before{content:"\e667";color:#f7622c}.icon-psd:before{content:"\e66a"}.icon-rtf:before{content:"\e66b"}.icon-image:before{content:"\e606";color:#1296db}.icon-doc:before{content:"\e623";color:#0d47a1}.icon-grid:before{content:"\e6ef"}.icon-list:before{content:"\e67a"}
\ No newline at end of file
.container[data-v-6a6d8781]{width:100%;height:100vh;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.container>img[data-v-6a6d8781]{display:block}
\ No newline at end of file
@supports (-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-25c99d8c]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-25c99d8c]{position:relative;width:520px;max-width:100%;padding:35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-25c99d8c]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-25c99d8c]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-25c99d8c]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-25c99d8c]{position:relative}.login-container .title-container .title[data-v-25c99d8c]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-25c99d8c]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-0704539c]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-740a3454]{margin:10px 0}
\ No newline at end of file
.block>div.radio[data-v-d0e52fe6]{margin:20px 0}.block div.flow-form[data-v-d0e52fe6]{margin:25px 0}.block div.flow-form>div.form-footer[data-v-d0e52fe6]{display:block}.block div.timeline-wrapper[data-v-d0e52fe6]{margin:0 10px}.block div.timeline-wrapper h4 label[data-v-d0e52fe6]{color:red}.block div.pay-div[data-v-d0e52fe6]{padding:15px;border-radius:20px;border:1px solid grey}
\ No newline at end of file
[data-v-63a89c90]{-webkit-box-sizing:border-box;box-sizing:border-box}body[data-v-63a89c90]{background:#f6f5f7;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;font-family:Montserrat,sans-serif;height:100vh;margin:-20px 0 50px}h1[data-v-63a89c90]{font-weight:700;margin:0}h2[data-v-63a89c90]{text-align:center}p[data-v-63a89c90]{font-size:14px;font-weight:100;line-height:20px;letter-spacing:.5px;margin:20px 0 30px}span[data-v-63a89c90]{font-size:12px}a[data-v-63a89c90]{color:#333;font-size:14px;margin:15px 0}button[data-v-63a89c90]{border-radius:20px;border:1px solid #3c97bf;background-color:#3c97bf;color:#fff;font-size:12px;font-weight:700;padding:12px 45px;letter-spacing:1px;text-transform:uppercase;-webkit-transition:-webkit-transform 80ms ease-in;transition:-webkit-transform 80ms ease-in;transition:transform 80ms ease-in;transition:transform 80ms ease-in,-webkit-transform 80ms ease-in}button[data-v-63a89c90]:active{-webkit-transform:scale(.95);transform:scale(.95)}button[data-v-63a89c90]:focus{outline:none}button.ghost[data-v-63a89c90]{background-color:transparent;border-color:#fff}form[data-v-63a89c90]{background-color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:0 50px;height:100%;text-align:center}input[data-v-63a89c90]{background-color:#eee;border:none;padding:12px 15px;margin:8px 0;width:100%}.container-wrapper[data-v-63a89c90]{width:100%;height:100vh;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.container[data-v-63a89c90]{background-color:#fff;border-radius:10px;-webkit-box-shadow:0 14px 28px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.22);box-shadow:0 14px 28px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.22);position:relative;overflow:hidden;width:768px;max-width:100%;min-height:480px}.form-container[data-v-63a89c90]{position:absolute;top:0;height:100%;-webkit-transition:all .6s ease-in-out;transition:all .6s ease-in-out}.sign-in-container[data-v-63a89c90]{left:0;width:50%;z-index:2}.container.right-panel-active .sign-in-container[data-v-63a89c90]{-webkit-transform:translateX(100%);transform:translateX(100%)}.sign-up-container[data-v-63a89c90]{left:0;width:50%;opacity:0;z-index:1}.container.right-panel-active .sign-up-container[data-v-63a89c90]{-webkit-transform:translateX(100%);transform:translateX(100%);opacity:1;z-index:5;-webkit-animation:show-data-v-63a89c90 .6s;animation:show-data-v-63a89c90 .6s}@-webkit-keyframes show-data-v-63a89c90{0%,49.99%{opacity:0;z-index:1}50%,to{opacity:1;z-index:5}}@keyframes show-data-v-63a89c90{0%,49.99%{opacity:0;z-index:1}50%,to{opacity:1;z-index:5}}.overlay-container[data-v-63a89c90]{position:absolute;top:0;left:50%;width:50%;height:100%;overflow:hidden;-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out;z-index:100}.container.right-panel-active .overlay-container[data-v-63a89c90]{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.overlay[data-v-63a89c90]{background:#3c97bf;background:-webkit-gradient(linear,left top,right top,from(#3c97bf),to(#13dbe2));background:linear-gradient(90deg,#3c97bf,#13dbe2);background-repeat:no-repeat;background-size:cover;background-position:0 0;color:#fff;position:relative;left:-100%;height:100%;width:200%;-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}.container.right-panel-active .overlay[data-v-63a89c90]{-webkit-transform:translateX(50%);transform:translateX(50%)}.overlay-panel[data-v-63a89c90]{position:absolute;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:0 40px;text-align:center;top:0;height:100%;width:50%;-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}.overlay-left[data-v-63a89c90]{-webkit-transform:translateX(-20%);transform:translateX(-20%)}.container.right-panel-active .overlay-left[data-v-63a89c90],.overlay-right[data-v-63a89c90]{-webkit-transform:translateX(0);transform:translateX(0)}.overlay-right[data-v-63a89c90]{right:0}.container.right-panel-active .overlay-right[data-v-63a89c90]{-webkit-transform:translateX(20%);transform:translateX(20%)}.social-container[data-v-63a89c90]{margin:20px 0}.social-container a[data-v-63a89c90]{border:1px solid #ddd;border-radius:50%;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:0 5px;height:40px;width:40px}footer[data-v-63a89c90]{background-color:#222;color:#fff;font-size:14px;bottom:0;position:fixed;left:0;right:0;text-align:center;z-index:999}footer p[data-v-63a89c90]{margin:10px 0}footer i[data-v-63a89c90]{color:red}footer a[data-v-63a89c90]{color:#3c97bf;text-decoration:none}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-1b2625c3]{margin:10px 0}
\ No newline at end of file
.pan-item[data-v-799537af]{width:200px;height:200px;border-radius:50%;display:inline-block;position:relative;cursor:default;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.2);box-shadow:0 1px 3px rgba(0,0,0,.2)}.pan-info-roles-container[data-v-799537af]{padding:20px;text-align:center}.pan-thumb[data-v-799537af]{width:100%;height:100%;background-position:50%;background-size:cover;border-radius:50%;overflow:hidden;position:absolute;-webkit-transform-origin:95% 40%;transform-origin:95% 40%;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.pan-info[data-v-799537af]{position:absolute;width:inherit;height:inherit;border-radius:50%;overflow:hidden;-webkit-box-shadow:inset 0 0 0 5px rgba(0,0,0,.05);box-shadow:inset 0 0 0 5px rgba(0,0,0,.05)}.pan-info h3[data-v-799537af]{color:#fff;text-transform:uppercase;position:relative;letter-spacing:2px;font-size:18px;margin:0 60px;padding:22px 0 0 0;height:85px;font-family:Open Sans,Arial,sans-serif;text-shadow:0 0 1px #fff,0 1px 2px rgba(0,0,0,.3)}.pan-info p[data-v-799537af]{color:#fff;padding:10px 5px;font-style:italic;margin:0 30px;font-size:12px;border-top:1px solid hsla(0,0%,100%,.5)}.pan-info p a[data-v-799537af]{display:block;color:#333;width:80px;height:80px;background:hsla(0,0%,100%,.3);border-radius:50%;color:#fff;font-style:normal;font-weight:700;text-transform:uppercase;font-size:9px;letter-spacing:1px;padding-top:24px;margin:7px auto 0;font-family:Open Sans,Arial,sans-serif;opacity:0;-webkit-transition:opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;transition:opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;transition:transform .3s ease-in-out .2s,opacity .3s ease-in-out .2s,background .2s linear 0s;transition:transform .3s ease-in-out .2s,opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;-webkit-transform:translateX(60px) rotate(90deg);transform:translateX(60px) rotate(90deg)}.pan-info p a[data-v-799537af]:hover{background:hsla(0,0%,100%,.5)}.pan-item:hover .pan-thumb[data-v-799537af]{-webkit-transform:rotate(-110deg);transform:rotate(-110deg)}.pan-item:hover .pan-info p a[data-v-799537af]{opacity:1;-webkit-transform:translateX(0) rotate(0deg);transform:translateX(0) rotate(0deg)}.box-center[data-v-14a8e445]{margin:0 auto;display:table}.text-muted[data-v-14a8e445]{color:#777}.user-profile .user-name[data-v-14a8e445]{font-weight:700}.user-profile .box-center[data-v-14a8e445]{padding-top:10px}.user-profile .user-role[data-v-14a8e445]{padding-top:10px;font-weight:400;font-size:14px}.user-profile .box-social[data-v-14a8e445]{padding-top:30px}.user-profile .box-social .el-table[data-v-14a8e445]{border-top:1px solid #dfe6ec}.user-profile .user-follow[data-v-14a8e445]{padding-top:20px}.user-bio[data-v-14a8e445]{margin-top:20px;color:#606266}.user-bio span[data-v-14a8e445]{padding-left:4px}.user-bio .user-bio-section[data-v-14a8e445]{font-size:14px;padding:15px 0}.user-bio .user-bio-section .user-bio-section-header[data-v-14a8e445]{border-bottom:1px solid #dfe6ec;padding-bottom:10px;margin-bottom:10px;font-weight:700}
\ No newline at end of file
This diff is collapsed.
.app-container>div.page-wrapper[data-v-ed8b56c8]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-c5e2f406]{margin:10px 0}
\ No newline at end of file
.app-container>div.page-wrapper[data-v-ae83d6fe]{margin:10px 0}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
.app-container>div.page-wrapper[data-v-31fd68e1]{margin:10px 0}
\ No newline at end of file
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;-webkit-box-shadow:0 0 10px #29d,0 0 5px #29d;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translateY(-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;-webkit-box-sizing:border-box;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
\ No newline at end of file
<!DOCTYPE html><html lang="cn"><head id="head"><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon"><link rel="png" href="/static/favicon.png"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.2/css/all.min.css"><title>web-creator-pro</title><link href="/static/css/chunk-elementUI.c549afcf.css" rel="stylesheet"><link href="/static/css/chunk-libs.7232a12a.css" rel="stylesheet"><link href="/static/css/app.5e24d41a.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but web-creator-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>(function(e){function c(c){for(var u,d,f=c[0],t=c[1],r=c[2],k=0,b=[];k<f.length;k++)d=f[k],Object.prototype.hasOwnProperty.call(a,d)&&a[d]&&b.push(a[d][0]),a[d]=0;for(u in t)Object.prototype.hasOwnProperty.call(t,u)&&(e[u]=t[u]);o&&o(c);while(b.length)b.shift()();return h.push.apply(h,r||[]),n()}function n(){for(var e,c=0;c<h.length;c++){for(var n=h[c],u=!0,d=1;d<n.length;d++){var f=n[d];0!==a[f]&&(u=!1)}u&&(h.splice(c--,1),e=t(t.s=n[0]))}return e}var u={},d={runtime:0},a={runtime:0},h=[];function f(e){return t.p+"js/"+({}[e]||e)+"."+{"chunk-0308f56e":"fdeafec5","chunk-0bda7808":"f60907d7","chunk-12bc4fd2":"110b8f8e","chunk-18a18b41":"73ea4b32","chunk-1cb19c5b":"6b399d74","chunk-1cd86b7f":"62311364","chunk-2390eb08":"73d2186a","chunk-2ccfeca3":"df9227d8","chunk-2d0ab84e":"d69b1552","chunk-2d0b6889":"da1db46e","chunk-2d0e4547":"f5a5e167","chunk-2d0e51c2":"89b3265c","chunk-2d20efc1":"265c4565","chunk-2d2214ae":"f5282af5","chunk-2d224aee":"783f5a1c","chunk-2d2262fd":"a4303f37","chunk-2d230289":"f050b19f","chunk-2d2375de":"d847ed6a","chunk-2d23777c":"7b81936d","chunk-312770ae":"ad7a7211","chunk-3925513c":"ab1cf31e","chunk-3cde30aa":"7827cf1f","chunk-3de98b3e":"b71003a5","chunk-44327d52":"541b9751","chunk-49ebb315":"3a43d7e0","chunk-4fcbc998":"dcab11de","chunk-5737f968":"f2598327","chunk-5e4a1016":"65ed3caa","chunk-6a14e92a":"1e6a88ac","chunk-6fbea197":"112efa41","chunk-7553fdbb":"b732c46e","chunk-771a9939":"57c180ed","chunk-7fc8fafe":"b4d6e9f3","chunk-80d4b084":"555167cd","chunk-8b2f269c":"b4ace073","chunk-982eb4d8":"d63235d7","chunk-a5a900ee":"4a7b1ebc","chunk-a70d9760":"4ac8da47","chunk-c2ae52ec":"5e6f17b7","chunk-b5ae6272":"355d8189","chunk-b93ef20c":"a11d650b","chunk-bc493424":"7bff83fc","chunk-c04e89f6":"0c075b9c","chunk-02e7185d":"e0b098dd","chunk-d074b11a":"008955a5","chunk-dc5ebe7e":"535728ef","chunk-2d0b3a48":"64e195cf","chunk-2d0c8db9":"5b774d96","chunk-2d0e980d":"e74864a2","chunk-6811135c":"3dd4cebb","chunk-7b4dccd2":"3252f89e","chunk-e3d964e2":"be81e29d","chunk-462ca286":"9f5aa29d","chunk-72626882":"ec85d74c","chunk-fd8f4e2a":"0fbd1402"}[e]+".js"}function t(c){if(u[c])return u[c].exports;var n=u[c]={i:c,l:!1,exports:{}};return e[c].call(n.exports,n,n.exports,t),n.l=!0,n.exports}t.e=function(e){var c=[],n={"chunk-0bda7808":1,"chunk-12bc4fd2":1,"chunk-18a18b41":1,"chunk-1cb19c5b":1,"chunk-2390eb08":1,"chunk-312770ae":1,"chunk-3925513c":1,"chunk-3cde30aa":1,"chunk-44327d52":1,"chunk-49ebb315":1,"chunk-4fcbc998":1,"chunk-5737f968":1,"chunk-5e4a1016":1,"chunk-6fbea197":1,"chunk-7553fdbb":1,"chunk-771a9939":1,"chunk-7fc8fafe":1,"chunk-80d4b084":1,"chunk-8b2f269c":1,"chunk-982eb4d8":1,"chunk-a70d9760":1,"chunk-c2ae52ec":1,"chunk-b5ae6272":1,"chunk-b93ef20c":1,"chunk-bc493424":1,"chunk-c04e89f6":1,"chunk-02e7185d":1,"chunk-d074b11a":1,"chunk-6811135c":1,"chunk-e3d964e2":1,"chunk-72626882":1,"chunk-fd8f4e2a":1};d[e]?c.push(d[e]):0!==d[e]&&n[e]&&c.push(d[e]=new Promise((function(c,n){for(var u="css/"+({}[e]||e)+"."+{"chunk-0308f56e":"31d6cfe0","chunk-0bda7808":"2780f4d3","chunk-12bc4fd2":"ea22827d","chunk-18a18b41":"d9e1a6b4","chunk-1cb19c5b":"7792e982","chunk-1cd86b7f":"31d6cfe0","chunk-2390eb08":"ee748837","chunk-2ccfeca3":"31d6cfe0","chunk-2d0ab84e":"31d6cfe0","chunk-2d0b6889":"31d6cfe0","chunk-2d0e4547":"31d6cfe0","chunk-2d0e51c2":"31d6cfe0","chunk-2d20efc1":"31d6cfe0","chunk-2d2214ae":"31d6cfe0","chunk-2d224aee":"31d6cfe0","chunk-2d2262fd":"31d6cfe0","chunk-2d230289":"31d6cfe0","chunk-2d2375de":"31d6cfe0","chunk-2d23777c":"31d6cfe0","chunk-312770ae":"2a332a2e","chunk-3925513c":"e4bedf91","chunk-3cde30aa":"c6aade4c","chunk-3de98b3e":"31d6cfe0","chunk-44327d52":"e5bb37be","chunk-49ebb315":"4a644c0e","chunk-4fcbc998":"59a76cf6","chunk-5737f968":"cf55412c","chunk-5e4a1016":"b70b9892","chunk-6a14e92a":"31d6cfe0","chunk-6fbea197":"ae721477","chunk-7553fdbb":"a464dd74","chunk-771a9939":"ad4baf4c","chunk-7fc8fafe":"ea68e6e3","chunk-80d4b084":"78978112","chunk-8b2f269c":"d54a9416","chunk-982eb4d8":"25792a85","chunk-a5a900ee":"31d6cfe0","chunk-a70d9760":"f8a7df77","chunk-c2ae52ec":"1c31cb9e","chunk-b5ae6272":"ec8cc5b1","chunk-b93ef20c":"c8eb127c","chunk-bc493424":"054e633a","chunk-c04e89f6":"ad094cd3","chunk-02e7185d":"205cdf4f","chunk-d074b11a":"65d51286","chunk-dc5ebe7e":"31d6cfe0","chunk-2d0b3a48":"31d6cfe0","chunk-2d0c8db9":"31d6cfe0","chunk-2d0e980d":"31d6cfe0","chunk-6811135c":"76440939","chunk-7b4dccd2":"31d6cfe0","chunk-e3d964e2":"3a48f657","chunk-462ca286":"31d6cfe0","chunk-72626882":"30ff7151","chunk-fd8f4e2a":"aad740dd"}[e]+".css",a=t.p+u,h=document.getElementsByTagName("link"),f=0;f<h.length;f++){var r=h[f],k=r.getAttribute("data-href")||r.getAttribute("href");if("stylesheet"===r.rel&&(k===u||k===a))return c()}var b=document.getElementsByTagName("style");for(f=0;f<b.length;f++){r=b[f],k=r.getAttribute("data-href");if(k===u||k===a)return c()}var o=document.createElement("link");o.rel="stylesheet",o.type="text/css",o.onload=c,o.onerror=function(c){var u=c&&c.target&&c.target.src||a,h=new Error("Loading CSS chunk "+e+" failed.\n("+u+")");h.code="CSS_CHUNK_LOAD_FAILED",h.request=u,delete d[e],o.parentNode.removeChild(o),n(h)},o.href=a;var i=document.getElementsByTagName("head")[0];i.appendChild(o)})).then((function(){d[e]=0})));var u=a[e];if(0!==u)if(u)c.push(u[2]);else{var h=new Promise((function(c,n){u=a[e]=[c,n]}));c.push(u[2]=h);var r,k=document.createElement("script");k.charset="utf-8",k.timeout=120,t.nc&&k.setAttribute("nonce",t.nc),k.src=f(e);var b=new Error;r=function(c){k.onerror=k.onload=null,clearTimeout(o);var n=a[e];if(0!==n){if(n){var u=c&&("load"===c.type?"missing":c.type),d=c&&c.target&&c.target.src;b.message="Loading chunk "+e+" failed.\n("+u+": "+d+")",b.name="ChunkLoadError",b.type=u,b.request=d,n[1](b)}a[e]=void 0}};var o=setTimeout((function(){r({type:"timeout",target:k})}),12e4);k.onerror=k.onload=r,document.head.appendChild(k)}return Promise.all(c)},t.m=e,t.c=u,t.d=function(e,c,n){t.o(e,c)||Object.defineProperty(e,c,{enumerable:!0,get:n})},t.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,c){if(1&c&&(e=t(e)),8&c)return e;if(4&c&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(t.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&c&&"string"!=typeof e)for(var u in e)t.d(n,u,function(c){return e[c]}.bind(null,u));return n},t.n=function(e){var c=e&&e.__esModule?function(){return e["default"]}:function(){return e};return t.d(c,"a",c),c},t.o=function(e,c){return Object.prototype.hasOwnProperty.call(e,c)},t.p="/static/",t.oe=function(e){throw console.error(e),e};var r=window["webpackJsonp"]=window["webpackJsonp"]||[],k=r.push.bind(r);r.push=c,r=r.slice();for(var b=0;b<r.length;b++)c(r[b]);var o=k;n()})([]);</script><script src="/static/js/chunk-elementUI.6be5ef5c.js"></script><script src="/static/js/chunk-libs.ab66c5d4.js"></script><script src="/static/js/app.d4997712.js"></script></body></html>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-0308f56e","chunk-2d230289"],{2907:function(t,e,r){"use strict";r.r(e);var i=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",[r("el-dialog",t._g(t._b({attrs:{visible:t.isVisible,title:t.title,width:t.width},on:{"update:visible":function(e){t.isVisible=e},open:t.onOpen,close:t.onClose}},"el-dialog",t.$attrs,!1),t.$listeners),[r("formpage",{ref:"formpage"}),r("div",{attrs:{slot:"footer"},slot:"footer"},[r("el-button",{attrs:{size:"medium"},on:{click:t.close}},[t._v("取消")]),r("el-button",{attrs:{size:"medium",type:"primary"},on:{click:t.handelConfirm}},[t._v("确定")])],1)],1)],1)},a=[],o=r("eaa8"),n={inheritAttrs:!1,components:{formpage:o["default"]},props:{visible:{type:Boolean,default:function(){return!1}},title:{type:String,default:function(){return"dialog"}},width:{type:String,required:!1,default:function(){return"50%"}}},data:function(){return{}},computed:{isVisible:{get:function(){return this.visible},set:function(t){return t}}},watch:{},created:function(){},mounted:function(){},methods:{update:function(t){var e=this;this.$nextTick((function(){e.$refs["formpage"].formData=t}))},onOpen:function(){},onClose:function(){this.close()},close:function(){this.$emit("close",this.formData)},handelConfirm:function(){var t=this,e=this.$refs["formpage"].$refs["elForm"];e.validate((function(r){r&&(t.$emit("confirm",e.model),t.close())}))}}},l=n,s=r("5d22"),m=Object(s["a"])(l,i,a,!1,null,null,null);e["default"]=m.exports},eaa8:function(t,e,r){"use strict";r.r(e);var i=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("el-form",{ref:"elForm",attrs:{model:t.formData,rules:t.rules,size:"medium","label-width":"100px"}},[r("el-form-item",{attrs:{label:"事件标题",prop:"title"}},[r("el-input",{style:{width:"100%"},attrs:{placeholder:"请输入设备名称事件标题",clearable:""},model:{value:t.formData.title,callback:function(e){t.$set(t.formData,"title",e)},expression:"formData.title"}})],1),r("el-form-item",{attrs:{label:"开始时间",prop:"start_time"}},[r("el-date-picker",{style:{width:"100%"},attrs:{type:"datetime",format:"yyyy-MM-dd HH:mm:ss","value-format":"yyyy-MM-dd HH:mm:ss",placeholder:"请选择开始时间",clearable:""},model:{value:t.formData.start_time,callback:function(e){t.$set(t.formData,"start_time",e)},expression:"formData.start_time"}})],1),r("el-form-item",{attrs:{label:"结束时间",prop:"end_time"}},[r("el-date-picker",{style:{width:"100%"},attrs:{type:"datetime",format:"yyyy-MM-dd HH:mm:ss","value-format":"yyyy-MM-dd HH:mm:ss",placeholder:"请选择结束时间",clearable:""},model:{value:t.formData.end_time,callback:function(e){t.$set(t.formData,"end_time",e)},expression:"formData.end_time"}})],1),r("el-form-item",{attrs:{size:"large"}},[r("el-button",{attrs:{type:"primary"},on:{click:t.submitForm}},[t._v("提交")]),r("el-button",{on:{click:t.resetForm}},[t._v("重置")])],1)],1)},a=[],o={inheritAttrs:!1,components:{},props:{data:{type:Object},isReadOnly:{type:Boolean,default:!1}},data:function(){return{formData:{title:void 0,start_time:null,end_time:null},rules:{title:[{required:!0,message:"请输入设备名称事件标题",trigger:"blur"}],start_time:[{required:!0,message:"请选择开始时间",trigger:"change"}],end_time:[{required:!0,message:"请选择结束时间",trigger:"change"}]}}},computed:{},watch:{},created:function(){},mounted:function(){this.data&&(this.formData=this.data)},methods:{submitForm:function(){this.$refs["elForm"].validate((function(t){if(!t)return!1}))},resetForm:function(){this.$refs["elForm"].resetFields()}}},n=o,l=r("5d22"),s=Object(l["a"])(n,i,a,!1,null,null,null);e["default"]=s.exports}}]);
\ No newline at end of file
This diff is collapsed.
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-12bc4fd2"],{"3dfc":function(t,s,a){t.exports=a.p+"img/404.a57b6f31.png"},"7e27":function(t,s,a){"use strict";a.r(s);var e=function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"wscn-http404-container"},[a("div",{staticClass:"wscn-http404"},[t._m(0),a("div",{staticClass:"bullshit"},[a("div",{staticClass:"bullshit__oops"},[t._v("OOPS!")]),t._m(1),a("div",{staticClass:"bullshit__headline"},[t._v(t._s(t.message))]),a("div",{staticClass:"bullshit__info"},[t._v("Please check that the URL you entered is correct, or click the button below to return to the homepage.")]),a("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[t._v("Back to home")])])])])},i=[function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("div",{staticClass:"pic-404"},[e("img",{staticClass:"pic-404__parent",attrs:{src:a("3dfc"),alt:"404"}}),e("img",{staticClass:"pic-404__child left",attrs:{src:a("a190"),alt:"404"}}),e("img",{staticClass:"pic-404__child mid",attrs:{src:a("a190"),alt:"404"}}),e("img",{staticClass:"pic-404__child right",attrs:{src:a("a190"),alt:"404"}})])},function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"bullshit__info"},[t._v("All rights reserved "),a("a",{staticStyle:{color:"#20a0ff"},attrs:{href:"https://wallstreetcn.com",target:"_blank"}},[t._v("wallstreetcn")])])}],c={name:"Page404",computed:{message:function(){return"The webmaster said that you can not enter this page..."}}},l=c,n=(a("bad4"),a("5d22")),r=Object(n["a"])(l,e,i,!1,null,"5b545914",null);s["default"]=r.exports},a190:function(t,s,a){t.exports=a.p+"img/404_cloud.0f4bc32b.png"},bad4:function(t,s,a){"use strict";a("fb72")},fb72:function(t,s,a){}}]);
\ No newline at end of file
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-18a18b41","chunk-a5a900ee","chunk-2d2214ae"],{"066f":function(e,t,a){"use strict";a("758d")},6574:function(e,t,a){"use strict";a.r(t);var i=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"app-container"},[a("el-form",{ref:"query",attrs:{inline:!0,model:e.query,size:"mini"}},[a("el-form-item",{attrs:{label:e.queryTitle,prop:"uuid"}},[a("el-select",{attrs:{filterable:"",placeholder:e.queryPlaceHolder},model:{value:e.query.uuid,callback:function(t){e.$set(e.query,"uuid",t)},expression:"query.uuid"}},e._l(e.queryList,(function(e,t){return a("el-option",{key:t,attrs:{label:e.name,value:e.uuid}})})),1)],1),a("el-form-item",[a("el-button",{attrs:{type:"primary"},on:{click:e.onQuery}},[e._v("查询")])],1),a("el-form-item",[a("el-button",{on:{click:function(t){return e.onReset("query")}}},[e._v("重置")])],1),a("el-form-item",[a("el-button",{attrs:{type:"warning"},on:{click:e.onAdd}},[e._v("添加")])],1)],1),a("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.isLoading,expression:"isLoading"}],attrs:{"element-loading-text":"Loading",data:e.tableData,size:"mini",border:"",stripe:"",fit:"","highlight-current-row":""}},[e._l(e.tableHeader,(function(e,t){return a("el-table-column",{key:t,attrs:{prop:e.prop,label:e.label,align:e.align,"min-width":e.width,"show-overflow-tooltip":e.overflow}})})),a("el-table-column",{attrs:{label:"操作",align:"center",width:"180",fixed:"right"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-button",{attrs:{size:"mini",type:"success"},on:{click:function(a){return e.handleEdit(t.$index,t.row)}}},[e._v("编辑")]),a("el-button",{attrs:{size:"mini",type:"danger"},on:{click:function(a){return e.handleDelete(t.$index,t.row)}}},[e._v("删除")])]}}])})],2),a("div",{staticClass:"page-wrapper"},[a("el-pagination",{attrs:{"current-page":e.query.pagenum,background:"",small:"","page-size":e.query.pagesize,"pager-count":5,layout:"pager, prev, next, total",total:e.total},on:{"current-change":e.handleCurrentChange,"update:currentPage":function(t){return e.$set(e.query,"pagenum",t)},"update:current-page":function(t){return e.$set(e.query,"pagenum",t)}}})],1),a("formdialog",{ref:"formdialog",attrs:{title:e.dialogTitle,visible:e.dialogVisible},on:{close:function(t){e.dialogVisible=!1},confirm:e.submitForm}})],1)},n=[],r=(a("4914"),a("2a39"),a("b775")),o=a("ed08"),l=a("7bf3"),s={name:"EquipmentQualification",components:{formdialog:l["default"]},data:function(){return{queryTitle:"查询条件",queryPlaceHolder:"输入查询字段",total:0,tableData:[],isLoading:!1,queryList:[],query:{uuid:null,pagesize:15,pagenum:1},dialogTitle:"",dialogVisible:!1,urlPrefix:"/api/v1/kxpms/qualification/equipment",tableHeader:[{label:"设备名称",prop:"name",align:"center",width:"150"},{label:"检测日期",prop:"test_date",align:"center",width:"150"},{label:"有效期",prop:"validity",align:"center",width:"120"}]}},methods:{addItem:function(e){return Object(r["a"])({url:this.urlPrefix+"/add",method:"post",data:e})},getItemList:function(e){return Object(r["a"])({url:this.urlPrefix+"/list",method:"post",data:e})},updateItem:function(e,t){return Object(r["a"])({url:"".concat(this.urlPrefix,"/update/").concat(e),method:"post",data:t})},deleteItem:function(e){return Object(r["a"])({url:"".concat(this.urlPrefix,"/delete/").concat(e),method:"post"})},fetchQueryList:function(){var e=this;this.getItemList({scope_type:"list"}).then((function(t){e.queryList=t.data})).catch((function(e){console.log(e.message)}))},fetchData:function(e){var t=this;this.isLoading=!0,this.getItemList(e).then((function(e){t.total=e.count,t.tableData=e.data})).catch((function(e){console.log(e.message)})).finally((function(){t.isLoading=!1}))},handleSizeChange:function(e){this.query.pagesize=e,this.fetchData(Object(o["e"])(this.query))},handleCurrentChange:function(e){this.query.pagenum=e,this.fetchData(Object(o["e"])(this.query))},handleEdit:function(e,t){this.dialogTitle="编辑",this.dialogVisible=!0,this.$refs["formdialog"].update(t)},handleDelete:function(e,t){var a=this;this.$alert("您确定要删除么?删除操作将不可恢复。如需取消操作,请点击右上角关闭按钮。","删除提醒",{confirmButtonText:"确定",callback:function(i){"confirm"==i&&a.deleteItem(t.uuid).then((function(t){console.log(t),a.total-=1,a.$delete(a.tableData,e),a.$message({type:"success",message:"成功删除第".concat(e+1,"")})})).catch((function(e){a.$message.error(e.message)}))}})},submitForm:function(e){var t=this;"添加"===this.dialogTitle?this.addItem(e).then((function(e){console.log(e),t.$message({type:"success",message:"添加成功"}),t.fetchData(Object(o["e"])(t.query))})).catch((function(e){t.$message.error(e.message)})):"编辑"===this.dialogTitle&&this.updateItem(e.uuid,e).then((function(e){console.log(e),t.$message({type:"success",message:"更新成功"}),t.fetchData(Object(o["e"])(t.query))})).catch((function(e){t.$message.error(e.message)}))},onAdd:function(){this.dialogTitle="添加",this.dialogVisible=!0},onQuery:function(){this.query.pagenum=1,this.query.pagesize=15,this.fetchData(Object(o["e"])(this.query))},onReset:function(e){this.query.pagenum=1,this.query.pagesize=15,this.$refs[e].resetFields(),this.fetchData(Object(o["e"])(this.query))}},mounted:function(){},created:function(){this.fetchData(Object(o["e"])(this.query)),this.fetchQueryList()}},u=s,c=(a("066f"),a("5d22")),d=Object(c["a"])(u,i,n,!1,null,"0aa5646b",null);t["default"]=d.exports},"758d":function(e,t,a){},"7bf3":function(e,t,a){"use strict";a.r(t);var i=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("el-dialog",e._g(e._b({attrs:{visible:e.isVisible,title:e.title,width:e.width},on:{"update:visible":function(t){e.isVisible=t},open:e.onOpen,close:e.onClose}},"el-dialog",e.$attrs,!1),e.$listeners),[a("formpage",{ref:"formpage"}),a("div",{attrs:{slot:"footer"},slot:"footer"},[a("el-button",{attrs:{size:"medium"},on:{click:e.close}},[e._v("取消")]),a("el-button",{attrs:{size:"medium",type:"primary"},on:{click:e.handelConfirm}},[e._v("确定")])],1)],1)],1)},n=[],r=a("ca71"),o={inheritAttrs:!1,components:{formpage:r["default"]},props:{visible:{type:Boolean,default:function(){return!1}},title:{type:String,default:function(){return"dialog"}},width:{type:String,required:!1,default:function(){return"50%"}}},data:function(){return{}},computed:{isVisible:{get:function(){return this.visible},set:function(e){return e}}},watch:{},created:function(){},mounted:function(){},methods:{update:function(e){var t=this;this.$nextTick((function(){t.$refs["formpage"].formData=e}))},onOpen:function(){},onClose:function(){this.close()},close:function(){this.$emit("close",this.formData)},handelConfirm:function(){var e=this,t=this.$refs["formpage"].$refs["elForm"];t.validate((function(a){a&&(e.$emit("confirm",t.model),e.close())}))}}},l=o,s=a("5d22"),u=Object(s["a"])(l,i,n,!1,null,null,null);t["default"]=u.exports},ca71:function(e,t,a){"use strict";a.r(t);var i=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("el-form",{ref:"elForm",attrs:{model:e.formData,rules:e.rules,size:"medium","label-width":"100px"}},[a("el-form-item",{attrs:{label:"设备名称",prop:"name"}},[a("el-input",{style:{width:"100%"},attrs:{placeholder:"请输入设备名称",readonly:e.isReadOnly,clearable:""},model:{value:e.formData.name,callback:function(t){e.$set(e.formData,"name",t)},expression:"formData.name"}})],1),a("el-form-item",{attrs:{label:"检测日期",prop:"test_date"}},[a("el-date-picker",{style:{width:"100%"},attrs:{type:"datetime",format:"yyyy-MM-dd HH:mm:ss","value-format":"yyyy-MM-dd HH:mm:ss",placeholder:"请选择检测日期",readonly:e.isReadOnly,clearable:""},model:{value:e.formData.test_date,callback:function(t){e.$set(e.formData,"test_date",t)},expression:"formData.test_date"}})],1),a("el-form-item",{attrs:{label:"有效期",prop:"validity"}},[a("el-date-picker",{style:{width:"100%"},attrs:{type:"datetime",format:"yyyy-MM-dd HH:mm:ss","value-format":"yyyy-MM-dd HH:mm:ss",placeholder:"请选择有效期",clearable:""},model:{value:e.formData.validity,callback:function(t){e.$set(e.formData,"validity",t)},expression:"formData.validity"}})],1)],1)},n=[],r={inheritAttrs:!1,components:{},props:{data:{type:Object},isReadOnly:{type:Boolean,default:!1}},data:function(){return{formData:{name:void 0,test_date:null,validity:null},rules:{name:[{required:!0,message:"请输入设备名称",trigger:"blur"}],test_date:[{required:!0,message:"请选择检测日期",trigger:"change"}],validity:[{required:!0,message:"请选择有效期",trigger:"change"}]}}},computed:{},watch:{},created:function(){},mounted:function(){this.data&&(this.formData=this.data)},methods:{}},o=r,l=a("5d22"),s=Object(l["a"])(o,i,n,!1,null,null,null);t["default"]=s.exports}}]);
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This image diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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