Commit d327191f authored by wanli's avatar wanli

update

parent 4c7657f8
......@@ -54,11 +54,11 @@ class SignalManager(object):
actionUpdateAnnex = PySignal()
# 系统框架模块
actionAddFramework = PySignal()
actionDeleteFramework = PySignal()
actionGetFramework = PySignal()
actionGetFrameworkList = PySignal()
actionUpdateFramework = PySignal()
actionAddDevice = PySignal()
actionDeleteDevice = PySignal()
actionGetDevice = PySignal()
actionGetDeviceList = PySignal()
actionUpdateDevice = PySignal()
# 应用下载统计模块
actionAddDownload = PySignal()
......
......@@ -4,14 +4,15 @@ import os
import json
import logging
from app import signalManager
from .api_manager import apiManager
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 .menu_manager import menuManager
from .device_manager import deviceManager
from .download_manager import downloadManager
from .framework_manager import frameworkManager
from .build_logs_manager import buildLogsManager
logger = logging.getLogger("controller")
......@@ -19,6 +20,7 @@ logger = logging.getLogger("controller")
def initConnect():
# 系统模块
signalManager.actionUploadFile.connect(uploadManager.upload)
signalManager.actionUpdatePassword.connect(apiManager.update_user_password)
# 登录模块
signalManager.actionLogin.connect(loginManager.login)
......@@ -32,6 +34,13 @@ def initConnect():
signalManager.actionGetAppList.connect(appsManager.getList)
signalManager.actionUpdateApp.connect(appsManager.update)
# 设备管理
signalManager.actionAddDevice.connect(deviceManager.add)
signalManager.actionDeleteDevice.connect(deviceManager.delete)
signalManager.actionGetDevice.connect(deviceManager.get)
signalManager.actionGetDeviceList.connect(deviceManager.getList)
signalManager.actionUpdateDevice.connect(deviceManager.update)
# 打包记录
signalManager.actionAddBuildLog.connect(buildLogsManager.add)
signalManager.actionDeleteBuildLog.connect(buildLogsManager.delete)
......@@ -53,13 +62,6 @@ def initConnect():
signalManager.actionGetAnnexList.connect(annexManager.getList)
signalManager.actionUpdateAnnex.connect(annexManager.update)
# 系统框架模块
signalManager.actionAddFramework.connect(frameworkManager.add)
signalManager.actionDeleteFramework.connect(frameworkManager.delete)
signalManager.actionGetFramework.connect(frameworkManager.get)
signalManager.actionGetFrameworkList.connect(frameworkManager.getList)
signalManager.actionUpdateFramework.connect(frameworkManager.update)
# 应用下载统计模块
signalManager.actionAddDownload.connect(downloadManager.add)
signalManager.actionDeleteDownload.connect(downloadManager.delete)
......
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import time
import json
import logging
import traceback
import uuid
from datetime import datetime
from pony.orm import *
from flask import request
from model import fullStackDB
from model.user import User
from utils import md5_salt
logger = logging.getLogger("ApiManager")
class ApiManager(object):
def __init__(self):
super(ApiManager, self).__init__()
def update_user_password(self, data):
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=data.get("uuid"), password=md5_salt(data['password']))
if not result:
return None, "user does not exists"
data.pop("uuid")
data['password'] = md5_salt(data['newPassword'])
data.pop('newPassword')
data.update({
"create_by": editor.id,
"create_at": datetime.now(),
"update_by": editor.id,
"update_at": datetime.now()
})
result = result.set(**data)
commit()
return True, "success"
apiManager = ApiManager()
......@@ -2,6 +2,7 @@
# -*- coding: utf_8 -*-
import os
import re
import shutil
import copy
import time
......@@ -43,14 +44,11 @@ class AppsManager(object):
'update_at': datetime.now(),
})
icon = Annex(title=data.get("app_icon").get("filename"), path=data.get("app_icon").get("filepath"), size=data.get("app_icon").get("filesize"), create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
commit()
app_files = []
if data.get("app_files"):
app_files = data.get("app_files")
data.pop("app_files")
data.update({ "app_icon": icon })
data.update({ "app_icon": data.get("app_icon").get("filepath") })
app = Apps(**data)
commit()
......@@ -68,7 +66,11 @@ class AppsManager(object):
for f in app_files:
filename = os.path.basename(f.get("filepath"))
target_f = copy.deepcopy(f)
target_filepath = os.sep.join([target_path, filename])
name, suffix = os.path.splitext(filename)
name = re.sub(r"_\d{14}$", "", name)
target_filepath = os.sep.join([target_path, name + suffix])
target_f['filepath'] = target_filepath
target_files.append(target_f)
shutil.copy(f.get("filepath"), target_f['filepath'])
......@@ -102,7 +104,6 @@ class AppsManager(object):
result = Apps.get(uuid=uuid)
if result:
result.app_icon.delete()
result.delete()
return result, "delete app {}.".format("success" if result else "fail")
......@@ -124,9 +125,17 @@ class AppsManager(object):
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
temp.setdefault("is_delete", False)
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
if editor.role == "ADMIN":
temp.update({"is_delete": False})
else:
temp.update({ "create_by": editor, "is_delete": False })
if "scope_type" in data and data.get("scope_type") == "list":
result = Apps.select().where(**temp).order_by(desc(Apps.create_at))
temp = []
......@@ -140,9 +149,9 @@ class AppsManager(object):
if result and len(result):
temp = []
for item in result:
t = item.to_dict(with_collections=True, related_objects=True, exclude=["app_annex", "app_download", "app_icon", "is_delete", "delete_by", "delete_at"])
t = item.to_dict(with_collections=True, related_objects=True, exclude=["app_annex", "app_download", "is_delete", "delete_by", "delete_at"])
t.update({
"app_build_log": item.app_build_log.to_dict(exclude=["is_delete", "delete_by", "delete_at", "create_by", "update_by"]),
"app_build_log": item.app_build_log.to_dict(exclude=["is_delete", "delete_by", "delete_at", "create_by", "update_by"]) if item.app_build_log else None,
"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,
......
......@@ -123,17 +123,26 @@ class BuildLogsManager(object):
temp.pop('pagesize')
if 'scope_type' in temp:
temp.pop('scope_type')
temp.setdefault("is_delete", False)
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
if editor.role == "USER":
temp.update({"create_by": editor, "is_delete": False})
else:
temp.update({"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"]))
temp.append({ "name": item.app.app_name, "uuid": str(item.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)
result = BuildLogs.select().where(**temp).order_by(desc(BuildLogs.create_at)).page(data.get("pagenum", 1), pagesize=data.get("pagesize", 10))
count = BuildLogs.select().where(**temp).count()
if result and len(result):
temp = []
......@@ -162,6 +171,6 @@ class BuildLogsManager(object):
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")
return result, "update build log {}.".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 *
from model import fullStackDB
from model.device import Device
from model.user import User
from utils import sql_filter
logger = logging.getLogger("DeviceManager")
class DeviceManager(object):
def __init__(self):
super(DeviceManager, self).__init__()
def add(self, user, data):
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
device = Device.select().where(imei=data.get("imei")).first()
if device:
return False, "device has been exists"
data.update({
'create_by': editor,
'create_at': datetime.now(),
'update_by': editor,
'update_at': datetime.now(),
})
result = Device(**data)
commit()
return result, "add Device {}.".format("success" if result else "fail")
def delete(self, user, uuid):
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
result = fullStackDB.update(Device, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete Device {}.".format("success" if result else "fail")
def get(self, user, data):
result = Device.get(**data)
if result:
result = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "create_at", "update_at", "delete_at"])
return result, "get Device {}.".format("success" if result else "fail")
def getList(self, user, 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')
with db_session:
editor = User.get(id=user)
if not editor:
return False, "current user is not exists"
if editor.role == "ADMIN":
temp.update({ "is_delete": False })
else:
temp.update({"create_by": editor, "is_delete": False})
if "scope_type" in data and data.get("scope_type") == "list":
result = Device.select().where(**temp).order_by(desc(Device.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 = Device.select().where(**temp).order_by(desc(Device.create_at)).page(data.get("pagenum", 1), data.get("pagesize", 10))
count = Device.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=["is_delete", "delete_at", "delete_by"])
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 Device {}.".format("success" if result else "no data")
def update(self, user, 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=user)
if not editor:
return False, "current user is not exists"
if data.get("imei"):
device = Device.select().where(imei=data.get("imei")).first()
if device:
return False, "device has been exists"
result = Device.get(uuid=uuid)
if result:
result.set(update_at=datetime.now(), update_by=editor, **data)
commit()
return result, "update role {}.".format("success" if result else "fail")
deviceManager = DeviceManager()
......@@ -18,7 +18,7 @@ from flask import request
from app.setting import config, conf
from model import fullStackDB
from model.download import AppDownload
from model.framework import Framework
from model.device import Device
from model.apps import Apps
from model.user import User
from utils import sql_filter
......@@ -91,16 +91,23 @@ class DownloadManager(object):
# 此次下载将生成一次下载记录
# 当前还没有校验前端传来的IMEI是否是合法的
epk_path = ""
# 根据IMEI查找设备,根据设备查找用户,根据用户查找应用
app = None
with db_session:
# 根据应用UUID查找相关应用
app = Apps.select(app_name=data.get("id")).order_by(desc(Apps.create_at)).first()
# 根据IMEI查找设备
device = Device.select().where(imei=data.get("imei")).first()
if not device:
return False, "device not found"
if not device.create_by:
return False, "create user is null"
app = Apps.select(app_name=data.get("id"), create_by=device.create_by).order_by(desc(Apps.create_at)).first()
if not app:
return False, "app not found"
tmp = app.to_dict(with_collections=True, related_objects=True)
epk_path = ""
if app.app_build_log:
epk_path = os.sep.join([os.getcwd(), app.app_build_log.app_path])
if not os.path.exists(epk_path):
......
#!/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.framework import Framework
from model.user import User
from utils import sql_filter
logger = logging.getLogger("FrameworkManager")
class FrameworkManager(object):
def __init__(self):
super(FrameworkManager, 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(Framework, **data)
return result, "add framework {}.".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(Framework, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
return result, "delete framework {}.".format("success" if result else "fail")
def get(self, data):
result = Framework.get(**data)
if result:
result = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "create_at", "update_at", "delete_at"])
return result, "get framework {}.".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 = Framework.select().where(**temp).order_by(desc(Framework.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(Framework, Framework.create_at, pagenum=data.get("pagenum", 1), pagesize=data.get("pagesize", 10), **temp)
count = fullStackDB.count(Framework, **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_at", "delete_by"])
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 framework {}.".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 = Framework.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")
frameworkManager = FrameworkManager()
......@@ -7,9 +7,10 @@ import types
import json
import logging
import traceback
from datetime import datetime
from threading import Thread
from werkzeug.security import check_password_hash
from pony.orm import *
from model import fullStackDB
from model.user import User
from fullstack.login import Auth
......@@ -35,7 +36,7 @@ class LoginManager(object):
:return ret: dict类型的登录相关信息
'''
try:
with db_session:
# 判断用户名是否存在
result = User.get(account=data.get("account"))
if not result:
......@@ -54,38 +55,36 @@ class LoginManager(object):
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)
return True, "user logout success."
def register(self, data):
'''
用户注册
'''
try:
with db_session:
# 判断账号是否存在
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)
editor = User.get(account=data.get("account"))
if editor:
return False, "user already exists"
data.update({
"password": md5_salt(data['password']),
"create_by": 0,
"create_at": datetime.now(),
"update_by": 0,
"update_at": datetime.now()
})
result = User(**data)
commit()
result.create_by = result.id
result.update_by = result.id
commit()
return result, "user register {}.".format("success" if result else "fail")
loginManager = LoginManager()
......@@ -125,8 +125,8 @@ class UploadManager(object):
obj['content'] = binfile.stream.read()
# 目录结构:模块类型/年/月/项目名/文件名_时间日期.文件后缀
# 模块类型:项目管理模块、资质管理模块
# filename = random_string() + os.path.splitext(obj['filename'])[-1]
# 模块类型:项目管理模块、资质管理模块
filename = os.path.splitext(obj['filename'])[0] + "_{}".format(datetime.now().strftime("%Y%m%d%H%M%S")) + os.path.splitext(obj['filename'])[-1]
# 获取相对路径
relative_path = config.get("UPLOAD_DIR")
......@@ -134,7 +134,7 @@ class UploadManager(object):
# 获取最终存储的绝对路径
savePath = os.path.normpath(os.sep.join([config.get("UPLOAD_PATH"), relative_path]))
# 获取最终存储的文件路径
saveFile = os.path.normpath(os.sep.join([savePath, obj['filename']]))
saveFile = os.path.normpath(os.sep.join([savePath, filename]))
if not os.path.exists(savePath):
os.makedirs(savePath)
......@@ -146,7 +146,7 @@ class UploadManager(object):
"uuid": str(uuid.uuid4()), # 附件唯一编号
"filename": obj['filename'], # 附件名称
"filesize": os.path.getsize(saveFile), # 附件大小
"filepath": os.sep.join([relative_path, obj['filename']]).replace("\\", "/"), # 附件存储路径
"filepath": os.sep.join([relative_path, filename]).replace("\\", "/"), # 附件存储路径
}, "upload file [%s] successfully!" % obj['filename']
except Exception as e: # repr(e)
traceback.print_exc()
......
......@@ -42,8 +42,6 @@ class UserManager(object):
if "username" not in data or not data.get("username"):
data.update({ "username": data.get("account") })
print(data)
# 密码加密
data['password'] = md5_salt(data['password'])
data.update({
......@@ -108,25 +106,6 @@ class UserManager(object):
result = User.get(id=request.current_user.get("id"), is_delete=False)
if result:
# 根据用户账号类型,返回不同的菜单
menus = [
{'id': 1, 'path': '/', 'name': None, 'redirect': '/home', 'component': 'Layout', 'title': None, 'icon': None, 'parent_id': 0},
{'id': 2, 'path': 'home', 'name': 'AppIndex', 'redirect': None, 'component': 'Home', 'title': '应用管理', 'icon': 'gongzuotai', 'parent_id': 1},
{'id': 3, 'path': '/', 'name': None, 'redirect': '/build', 'component': 'Layout', 'title': None, 'icon': None, 'parent_id': 0},
{'id': 4, 'path': 'build', 'name': 'AppBuild', 'redirect': None, 'component': 'Build', 'title': '打包日志', 'icon': 'gongzuotai', 'parent_id': 3},
{'id': 5, 'path': '/', 'name': None, 'redirect': '/profile', 'component': 'Layout', 'title': None, 'icon': None, 'parent_id': 0},
{'id': 6, 'path': 'profile', 'name': 'Profile', 'redirect': None, 'component': 'Profile', 'title': '个人中心', 'icon': 'shangcheng', 'parent_id': 5},
]
if result.role == "ADMIN":
menus = menus + [
{'id': 7, 'path': '/', 'name': None, 'redirect': '/download', 'component': 'Layout', 'title': None, 'icon': None, 'parent_id': 0},
{'id': 8, 'path': 'download', 'name': 'Download', 'redirect': None, 'component': 'Download', 'title': '下载记录', 'icon': 'gongzuotai', 'parent_id': 7},
{'id': 9, 'path': '/', 'name': None, 'redirect': '/framework', 'component': 'Layout', 'title': None, 'icon': None, 'parent_id': 0},
{'id': 10, 'path': 'framework', 'name': 'Framework', 'redirect': None, 'component': 'Framework', 'title': '系统页面', 'icon': 'gongzuotai', 'parent_id': 9},
{'id': 11, 'path': '/', 'name': None, 'redirect': '/users', 'component': 'Layout', 'title': None, 'icon': None, 'parent_id': 0},
{'id': 12, 'path': 'users', 'name': 'User', 'redirect': None, 'component': 'User', 'title': '用户管理', 'icon': 'user', 'parent_id': 11},
]
temp = result.to_dict(with_collections=True, related_objects=True, only=["uuid", "username", "account", "role", "phone", "email", "gender", "create_at", "update_at"])
temp.update({
"create_at": result.create_at.strftime("%Y-%m-%d %H:%M:%S") if result.create_at else None,
......
......@@ -14,7 +14,6 @@ class Annex(db.Entity):
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app = Optional("Apps", reverse="app_annex")
app_icon = Optional("Apps", reverse="app_icon")
title = Required(str, max_len=200) # 文件名
path = Required(LongStr) # 文件路径
type = Required(int, default=0) # 文件类型 PNG/JPG/GIF/MP3/MP4/DOCX/XLSX/PPT/PDF...
......
......@@ -15,7 +15,7 @@ class AppUser(db.Entity):
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
app = Required("Apps", reverse="app_user")
imei = Optional(str)
device = Required("Device", reverse="app_user")
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='app_users_creator')
update_at = Required(datetime, default=datetime.now)
......
......@@ -21,7 +21,7 @@ class Apps(db.Entity):
app_version = Optional(str, default="")
app_url = Optional(str, default="")
category = Optional(str, default="")
app_icon = Optional("Annex", reverse="app_icon")
app_icon = Optional(str)
app_desc = Optional(str, default="")
app_annex = Set("Annex", reverse="app", cascade_delete=True)
app_user = Optional("AppUser", reverse="app", cascade_delete=True)
......
......@@ -9,21 +9,21 @@ from . import fullStackDB
db = fullStackDB.db
class Framework(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "framework"
class Device(db.Entity):
_table_ = "{}".format(config['TABLE_PREFIX']) + "device"
id = PrimaryKey(int, auto=True)
uuid = Required(uuid.UUID, unique=True, default=uuid.uuid1, index=True)
name = Required(str) # 名称
url = Required(str) # 路径
imei = Required(str) # IMEI
desc = Required(str) # 描述信息
type = Required(str) # 模板类型
assets = Optional(Json, default={}) # 静态资源文件
type = Required(str) # 设备类型
app_user = Set("AppUser", reverse="device")
create_at = Required(datetime, default=datetime.now)
create_by = Required("User", reverse='framework_creator')
create_by = Required("User", reverse='device_creator')
update_at = Required(datetime, default=datetime.now)
update_by = Required("User", reverse='framework_updater')
update_by = Required("User", reverse='device_updater')
delete_at = Optional(datetime)
delete_by = Optional("User", reverse='framework_deleter')
delete_by = Optional("User", reverse='device_deleter')
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
......@@ -13,14 +13,14 @@ 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)
role = Required(str, default="User") # 角色
role = Required(str, default="USER") # 角色
account = Required(str, unique=True) # 账号
username = Required(str, max_len=100) # 用户名
password = Required(str, max_len=64)
gender = Optional(int, size=8) # 性别,未知0 男1 女2
password = Required(str, max_len=64) # 密码
gender = Optional(int, size=8, default=1) # 性别,未知0 男1 女2
birthday = Optional(date, default=date.today()) # 使用age会带来age无法随时间变化问题
phone = Optional(str, max_len=11) # 联系方式
email = Optional(str, max_len=100) # 邮箱
phone = Optional(str, max_len=11, default="") # 联系方式
email = Optional(str, max_len=100, default="") # 邮箱
create_at = Required(datetime, default=datetime.now)
create_by = Required(int)
update_at = Required(datetime, default=datetime.now)
......@@ -42,9 +42,9 @@ class User(db.Entity):
build_logs_creator = Set('BuildLogs', reverse='create_by')
build_logs_updater = Set('BuildLogs', reverse='update_by')
build_logs_deleter = Set('BuildLogs', reverse='delete_by')
framework_creator = Set('Framework', reverse='create_by')
framework_updater = Set('Framework', reverse='update_by')
framework_deleter = Set('Framework', reverse='delete_by')
device_creator = Set('Device', reverse='create_by')
device_updater = Set('Device', reverse='update_by')
device_deleter = Set('Device', reverse='delete_by')
menu_creator = Set('Menu', reverse='create_by')
menu_updater = Set('Menu', reverse='update_by')
menu_deleter = Set('Menu', reverse='delete_by')
......@@ -16,7 +16,6 @@ class DeleteSchema(BaseSchema):
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) # 防止用户传特别大的数,导致数据库查询阻塞
......
......@@ -4,12 +4,11 @@ from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class AddSchema(BaseSchema):
name = fields.String(required=True)
url = fields.String(required=True)
imei = fields.String(required=True)
desc = fields.String(required=True)
type = fields.String(required=True)
assets = fields.Dict(required=False)
sort = fields.Integer(required=False, default=0, allow_none=True)
remarks = fields.String(required=False, default=" ", 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:
......@@ -17,10 +16,9 @@ class AddSchema(BaseSchema):
class UpdateSchema(BaseSchema):
name = fields.String(required=False)
url = fields.String(required=False)
imei = fields.String(required=False)
desc = fields.String(required=False)
type = fields.String(required=False)
assets = fields.Dict(required=False)
sort = fields.Integer(required=False)
remarks = fields.String(required=False)
......
......@@ -2,24 +2,15 @@ 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))
account = fields.String(required=True)
password = fields.String(required=True)
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")
phone = 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)
account = fields.String(required=True)
username = fields.String(required=True)
password = fields.String(required=True)
class Meta:
unknown = EXCLUDE
\ No newline at end of file
......@@ -12,7 +12,7 @@ from .login import login_api
from .user import user_api
from .annex import annex_api
from .apps import apps_api
from .framework import framework_api
from .device import device_api
from .download import download_api
from .ws import NotifyHandler, ThreadNotifyHandler
from model import fullStackDB
......@@ -44,8 +44,8 @@ def create_app():
app.register_blueprint(user_api)
app.register_blueprint(annex_api)
app.register_blueprint(apps_api)
app.register_blueprint(framework_api)
app.register_blueprint(download_api)
app.register_blueprint(device_api)
@app.errorhandler(InternalServerError)
def handle_500(e):
......
......@@ -10,18 +10,19 @@ from app import config, signalManager
from fullstack.login import Auth
from fullstack.validation import validate_schema
from fullstack.response import ResponseCode, response_result
from schema.framework import AddSchema, DeleteSchema, QuerySchema, UpdateSchema
from schema.device import AddSchema, DeleteSchema, QuerySchema, UpdateSchema
logger = logging.getLogger("frameworkApi")
logger = logging.getLogger("deviceApi")
framework_api = Blueprint("framework_api", __name__, url_prefix="/api/v1/%s/framework" % config['NAME'])
device_api = Blueprint("device_api", __name__, url_prefix="/api/v1/%s/device" % config['NAME'])
@framework_api.route("/add", methods=['POST'])
@device_api.route("/add", methods=['POST'])
@validate_schema(AddSchema)
@Auth.auth_required
def add():
try:
isSuccess, message = signalManager.actionAddFramework.emit(request.schema_data)
user = request.current_user.get("id")
isSuccess, message = signalManager.actionAddDevice.emit(user, request.schema_data)
if isSuccess:
return response_result(ResponseCode.OK, msg=message)
else:
......@@ -32,12 +33,13 @@ def add():
return response_result(ResponseCode.SERVER_ERROR, msg=str(e))
@framework_api.route("/delete/<uuid:id>", methods=['POST'])
@device_api.route("/delete/<uuid:id>", methods=['POST'])
@validate_schema(DeleteSchema)
@Auth.auth_required
def delete(id):
try:
isSuccess, message = signalManager.actionDeleteFramework.emit(id)
user = request.current_user.get("id")
isSuccess, message = signalManager.actionDeleteDevice.emit(user, id)
if isSuccess:
return response_result(ResponseCode.OK, msg=message)
else:
......@@ -48,12 +50,13 @@ def delete(id):
return response_result(ResponseCode.SERVER_ERROR)
@framework_api.route("/get", methods=["POST"])
@device_api.route("/get", methods=["POST"])
@validate_schema(QuerySchema)
@Auth.auth_required
def get():
try:
result, message = signalManager.actionGetFramework.emit(request.schema_data)
user = request.current_user.get("id")
result, message = signalManager.actionGetDevice.emit(user, request.schema_data)
if result:
return response_result(ResponseCode.OK, data=result, msg=message)
else:
......@@ -64,12 +67,13 @@ def get():
return response_result(ResponseCode.SERVER_ERROR, msg=str(e))
@framework_api.route("/list", methods=['POST'])
@device_api.route("/list", methods=['POST'])
@validate_schema(QuerySchema)
@Auth.auth_required
def get_list():
try:
result, count, message = signalManager.actionGetFrameworkList.emit(request.schema_data)
user = request.current_user.get("id")
result, count, message = signalManager.actionGetDeviceList.emit(user, request.schema_data)
if result:
return response_result(ResponseCode.OK, data=result, msg=message, count=count)
else:
......@@ -80,12 +84,13 @@ def get_list():
return response_result(ResponseCode.SERVER_ERROR)
@framework_api.route("/update/<uuid:id>", methods=['POST'])
@device_api.route("/update/<uuid:id>", methods=['POST'])
@validate_schema(UpdateSchema)
@Auth.auth_required
def update(id):
try:
isSuccess, message = signalManager.actionUpdateFramework.emit(id, request.schema_data)
user = request.current_user.get("id")
isSuccess, message = signalManager.actionUpdateDevice.emit(user, id, request.schema_data)
if isSuccess:
return response_result(ResponseCode.OK, msg=message)
else:
......
......@@ -3,7 +3,6 @@
import logging
from flask import json
# import websocket
from tornado.websocket import WebSocketHandler, WebSocketClosedError
from utils import ObjectDict
from app import config
......@@ -35,6 +34,7 @@ def pushmessage(func):
else:
self.write_message(repr(msg), binary)
except WebSocketClosedError as e:
print(e)
self.on_close()
return send
......
This diff is collapsed.
......@@ -8,32 +8,20 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@fullcalendar/core": "^5.5.0",
"@fullcalendar/daygrid": "^5.5.0",
"@fullcalendar/interaction": "^5.5.0",
"@fullcalendar/timegrid": "^5.5.0",
"@fullcalendar/vue": "^5.5.0",
"@riophae/vue-treeselect": "^0.4.0",
"axios": "^0.19.0",
"clipboard": "^2.0.6",
"codemirror": "^5.50.0",
"core-js": "^3.9.0",
"dateformat": "^3.0.3",
"echarts": "^4.8.0",
"el-table-infinite-scroll": "^1.0.10",
"element-ui": "^2.13.0",
"file-saver": "^2.0.5",
"hey-utils": "^1.0.2",
"js-cookie": "^2.2.1",
"js-md5": "^0.7.3",
"jszip": "^3.5.0",
"local-storage": "^2.0.0",
"mockjs": "^1.1.0",
"moment": "^2.29.1",
"node-sass": "^4.14.1",
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
"photoswipe": "^4.1.3",
"sass-loader": "^8.0.0",
"vue": "^2.6.12",
"vue-codemirror": "^4.0.6",
......@@ -41,9 +29,7 @@
"vue-grid-layout": "^2.3.8",
"vue-plyr": "^7.0.0",
"vue-router": "^3.1.3",
"vue-simple-calendar": "^5.0.0",
"vuex": "^3.1.2",
"xlsx": "^0.16.9"
"vuex": "^3.1.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.8",
......
......@@ -116,3 +116,110 @@ export function deleteDownload(params) {
data: params,
});
}
export function addDevice(params) {
return request({
url: "/api/v1/evm_store/device/add",
method: "post",
data: params,
});
}
export function deleteDevice(params) {
return request({
url: "/api/v1/evm_store/device/delete",
method: "post",
data: params,
});
}
export function getDeviceList(params) {
return request({
url: "/api/v1/evm_store/device/list",
method: "post",
data: params,
});
}
export function updateDevice(params) {
return request({
url: "/api/v1/evm_store/device/update",
method: "post",
data: params,
});
}
export function addUser(params) {
// 增
return request({
url: "/api/v1/evm_store/user/add",
method: "post",
data: params,
});
}
export function deleteUser(id) {
// 删
return request({
url: `/api/v1/evm_store/user/delete/${id}`,
method: "post",
});
}
export function getUser(params) {
return request({
url: "/api/v1/evm_store/user/get",
method: "post",
data: params,
});
}
export function getUserList(params) {
// 查
return request({
url: "/api/v1/evm_store/user/list",
method: "post",
data: params,
});
}
export function updateUser(id, params) {
// 改
return request({
url: `/api/v1/evm_store/user/update/${id}`,
method: "post",
data: params,
});
}
export function updateUserPassword(params) {
return request({
url: "/api/v1/evm_store/updatePassword",
method: "post",
data: params,
});
}
export function doLogin(params) {
return request({
url: "/api/v1/evm_store/login/login",
method: "post",
data: params,
});
}
export function doLogout(params) {
return request({
url: "/api/v1/evm_store/login/logout",
method: "post",
data: params,
});
}
export function doRegister(params) {
return request({
url: "/api/v1/evm_store/login/register",
method: "post",
data: params,
});
}
import request from "@/utils/request";
export function addTechResources(params) {
return request({
url: "/api/v1/evm_store/techResources/add",
method: "post",
data: params,
});
}
export function getTechResourcesList(params) {
return request({
url: "/api/v1/evm_store/techResources/list",
method: "post",
data: params,
});
}
export function updateTechResource(id, params) {
return request({
url: `/api/v1/evm_store/techResources/update/${id}`,
method: "post",
data: params,
});
}
export function deleteTechResource(id, params) {
return request({
url: `/api/v1/evm_store/techResources/delete/${id}`,
method: "post",
data: params,
});
}
\ No newline at end of file
import request from '@/utils/request'
export function login(data) {
return request({
url: '/user/login',
method: 'post',
data
})
}
export function getInfo(token) {
return request({
url: '/user/info',
method: 'get',
params: { token }
})
}
export function logout() {
return request({
url: '/user/logout',
method: 'post'
})
}
import request from "@/utils/request";
export function addWarningRule(params) {
return request({
url: "/api/v1/evm_store/warningrule/add",
method: "post",
data: params,
});
}
export function getWarningRuleList(params) {
return request({
url: "/api/v1/evm_store/warningrule/list",
method: "post",
data: params,
});
}
export function getWarningLogList(params) {
return request({
url: "/api/v1/evm_store/warninglog/list",
method: "post",
data: params,
});
}
export function getWarnings(params) {
return request({
url: "/api/v1/evm_store/profile/warnings",
method: "post",
data: params,
});
}
export function ignoreWarnings(params) {
return request({
url: "/api/v1/evm_store/profile/ignoreWarnings",
method: "post",
data: params,
});
}
<template>
<div>
<el-row>
<el-col :span="24">
<el-menu default-active="2" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">EVM应用开发者中心</el-menu-item>
<el-menu-item index="2">首页</el-menu-item>
<el-submenu index="3">
<template slot="title">管理应用</template>
<el-menu-item index="3-1">我的应用</el-menu-item>
<el-menu-item index="3-2">上传新应用</el-menu-item>
<el-menu-item index="3-3">认领应用</el-menu-item>
</el-submenu>
<el-submenu index="4">
<template slot="title">开发者身份管理</template>
<el-menu-item index="4-1">开发者实名认证</el-menu-item>
<el-menu-item index="4-2">查看开发者身份</el-menu-item>
<el-menu-item index="4-3">更换认证支付宝账号</el-menu-item>
<el-menu-item index="4-4">修改联系人信息</el-menu-item>
</el-submenu>
<el-submenu index="5">
<template slot="title">推广</template>
<el-menu-item index="5-1">申请推广</el-menu-item>
<el-menu-item index="5-2">应用推广</el-menu-item>
<el-menu-item index="5-3">礼包权益</el-menu-item>
</el-submenu>
<el-submenu index="6">
<template slot="title">我的账户</template>
<el-menu-item index="6-1">我的充值记录</el-menu-item>
<el-menu-item index="6-2">我的收益</el-menu-item>
<el-menu-item index="6-3">开发票</el-menu-item>
</el-submenu>
</el-menu>
</el-col>
</el-row>
<div class="content-wrap">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "DevLayout",
data: () => {
return {};
},
mounted() {},
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath);
},
},
};
</script>
<style lang="scss" scope>
@import "../styles/developer/combineCss.min.css";
</style>
<template>
<div class="app">
<newSidebar class="app-aside" :class="asideClass" />
<section :class="sectionClass" class="app-wrapper">
<div v-if="isFullScreen" class="zoomIn" @click="showNormal" title="缩小">
<IconFont icon="suoxiao" size="22" color="#333" />
</div>
<baseHeader
:userSetIsShow="isVisible"
@changeUserSet="changeUserSet"
@handleDrawerBar="handleDrawerBar"
/>
<div class="app-content">
<div :class="contentClass">
<template v-if="appTheme == 'three'">
<bottomBar v-if="!isFullScreen" />
</template>
<navbar v-if="!isFullScreen" />
</div>
<app-main />
</div>
<div class="app-layout-footer">
<img src="../assets/layout/copy-right.png" alt="" />
Copyright @ 2020 By 武汉迎风聚智科技有限公司
</div>
</section>
<userSetting :isVisible="isVisible" @changeVisible="changeVisible" />
<el-drawer
:custom-class="appStyle == 'dark' ? 'change-drawer-dark' : ''"
direction="ltr"
size="220px"
:visible.sync="isDrawerOpen"
:with-header="false"
>
<drawerBar />
</el-drawer>
</div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
import { Navbar, newSidebar, AppMain } from "./components";
import ResizeMixin from "./mixin/ResizeHandler";
import userSetting from "@/views/users/userSetting.vue";
import bottomBar from "./components/bottomBar/index.vue";
import drawerBar from "./components/drawerBar/index.vue";
import baseHeader from "./components/header/baseHeader.vue";
export default {
name: "Layout",
components: {
Navbar,
newSidebar,
AppMain,
userSetting,
bottomBar,
drawerBar,
baseHeader,
},
mixins: [ResizeMixin],
computed: {
...mapGetters(["isFullScreen"]),
...mapState("settings", ["headerTitle", "userblockShow"]),
...mapState("user", [
"appStyle",
"appTheme",
"isFixedSide",
"isFixedWidth",
]),
sidebar() {
return this.$store.state.app.sidebar;
},
device() {
return this.$store.state.app.device;
},
fixedHeader() {
return this.$store.state.settings.fixedHeader;
},
sectionClass() {
return {
// hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === "mobile",
fullExpand: this.isFullScreen,
};
},
asideClass() {
return {
"el-hide": this.isFullScreen || this.appTheme != "one",
"fixed-aside": this.appTheme == "one" && this.isFixedSide,
"fixed-aside-open":
this.appTheme == "one" &&
this.isFixedSide &&
this.sidebar.opened == true,
"fixed-aside-close":
this.appTheme == "one" &&
this.isFixedSide &&
this.sidebar.opened == false,
};
},
contentClass() {
return {
"app-content-setWidth": this.isFixedWidth,
};
},
userName() {
return this.$store.getters.name;
},
},
data: () => {
return {
isVisible: false,
isDrawerOpen: false,
};
},
mounted() {
// console.log('this.$store',this.$store);
document.addEventListener("keyup", (e) => {
if (e.keyCode == 27) {
this.$store.dispatch("settings/handleFullScreen", false);
}
});
},
methods: {
handleClickOutside() {
this.$store.dispatch("app/closeSideBar", { withoutAnimation: false });
},
logout() {
var url = this.$client.apiUrlprefix() + "/logout";
var that = this;
this.$axios.post(url, {}, function(res) {
console.log(res);
that.$store.dispatch("user/removeToken");
that.$router.push({ path: "/login" });
});
},
changeVisible(msg) {
this.isVisible = msg;
},
handleDrawerBar() {
this.isDrawerOpen = !this.isDrawerOpen;
},
changeUserSet(msg) {
this.isVisible = msg;
},
showNormal() {
this.$store.dispatch("settings/handleFullScreen", false);
},
},
};
</script>
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";
.app >>> {
.change-drawer-dark {
.el-drawer__body {
background-color: #04142a;
}
.el-menu {
border-right: none;
}
}
}
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
.zoomIn {
position: fixed;
z-index: 1;
top: 5px;
right: 5px;
color: #fff;
cursor: pointer;
// background: #52c41a;
background: #fff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(2, 48, 101, 0.2);
padding: 5px;
}
</style>
<template>
<router-view></router-view>
</template>
\ No newline at end of file
......@@ -2,16 +2,12 @@ import Vue from "vue";
import "normalize.css/normalize.css"; // A modern alternative to CSS resets
// hey-ui framework
// import HeyUI from "heyui";
// import "@/styles/heyui/app.less";
// elementu-ui framework
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
//import locale from 'element-ui/lib/locale/lang/en' // lang i18n
import "@/styles/elementui/index.scss"; // global css
import "@/styles/elementui/theme-blue/index.css"; // blue theme css
import "@/styles/index.scss"; // global css
import "@/styles/theme-blue/index.css"; // blue theme css
import App from "./App";
import store from "./store";
......@@ -39,12 +35,10 @@ import IconFont from "@/components/IconFont";
// import CollapseTransition from "element-ui/lib/transitions/collapse-transition";
// The second argument is optional and sets the default config values for every player.
// Vue.component(CollapseTransition.name, CollapseTransition);
Vue.component("IconFont", IconFont);
// Vue.component(CollapseTransition.name, CollapseTransition);
// Vue.use(HeyUI);
// set ElementUI lang to EN
//Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui,按如下方式声明
......
......@@ -5,6 +5,7 @@ Vue.use(Router);
/* Layout */
import Layout from "@/layout";
import DevLayot from "@/layout/developer";
/**
* Note: sub-menu only appear when route children.length >= 1
......@@ -53,6 +54,17 @@ export const constantRoutes = [
meta: { title: '应用管理', icon: 'home' }
}]
},
{
path: '/',
redirect: '/dev',
component: DevLayot,
children: [{
path: 'dev',
name: 'Developer',
component: () => import('@/views/developer/index.vue'),
meta: { title: '开发者中心', icon: 'home' }
}]
},
{
path: '/',
redirect: '/build',
......@@ -77,13 +89,13 @@ export const constantRoutes = [
},
{
path: '/',
redirect: '/framework',
redirect: '/device',
component: Layout,
children: [{
path: 'framework',
name: 'Framework',
component: () => import('@/views/app-store/framework.vue'),
meta: { title: '系统页面', icon: 'gongzuotai' }
path: 'device',
name: 'Device',
component: () => import('@/views/app-store/device.vue'),
meta: { title: '设备管理', icon: 'gongzuotai' }
}]
},
{
......@@ -97,6 +109,17 @@ export const constantRoutes = [
meta: { title: '个人中心', icon: 'shangcheng' }
}]
},
{
path: '/',
redirect: '/docs',
component: Layout,
children: [{
path: 'docs',
name: 'Document',
component: () => import('@/views/app-store/docs.vue'),
meta: { title: '开发文档', icon: 'shangcheng' }
}]
},
{
path: '/',
redirect: '/user',
......
......@@ -34,7 +34,6 @@ export default {
name: "AppIndex",
icon: "gongzuotai",
path: "home",
hidden: false,
},
{
vue: "app-store/build.vue",
......@@ -42,7 +41,27 @@ export default {
name: "AppBuild",
icon: "gongzuotai",
path: "build",
hidden: false,
},
{
vue: "app-store/device.vue",
title: "设备管理",
name: "Device",
icon: "gongzuotai",
path: "device",
},
{
vue: "profile/docs.vue",
title: "个人中心",
name: "Profile",
icon: "gongzuotai",
path: "profile",
},
{
vue: "app-store/docs.vue",
title: "开发文档",
name: "Document",
icon: "gongzuotai",
path: "docs",
},
],
};
This diff is collapsed.
@import (less) "~heyui/themes/common.less";
@import (less) "./overwrite.less";
@import (less) "./fonts/style.less";
@import (less) "./frame.less";
@import (less) "./var.less";
@import (less) "./markdown.less";
@import (less) "./common.less";
body {
background: #f3f6f8;
color: rgb(47, 47, 47);
font-weight: 400;
}
p {
margin: 8px 0;
}
pre {
white-space: pre-wrap;
}
\ No newline at end of file
.font-size(@var, @size) {
.font@{var} {
font-size: @size !important;
}
}
.font-size(12, 12px);
.font-size(13, 13px);
.font-size(14, 14px);
.font-size(15, 15px);
.font-size(16, 16px);
.font-size(18, 18px);
.font-size(20, 20px);
.font-size(22, 22px);
.font-size(28, 28px);
.font-bold {
font-weight: bold;
}
.common-page-tabs-bar {
position: relative;
margin-bottom: 2px;
min-height: 50px;
.h-tabs-default {
min-height: 47px;
}
}
.common-filter-bar {
padding: 17px 0 8px;
min-height: 66px;
}
.common-filter-select {
height:32px;
background:rgba(0,0,0,0.04);
border-radius:2px;
color:rgba(0,0,0,0.65);
.h-select-value-single, .h-select-placeholder {
height:32px;
line-height:32px;
}
}
.common-status-filter-tabs {
border: 1px solid fade( @primary-color, 10%);
background-color: fade( @primary-color, 5%);
border-radius: 2px;
>div {
position: relative;
padding: 20px 22px;
>p {
margin: 0;
line-height: 22px;
text-align: center;
}
.name {
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
}
.code {
color: rgba(0, 0, 0, 0.85);
font-size: 18px;
}
.bold {
font-weight: bold;
}
&:after {
content: "";
border-right: 1px dashed #979797;
position: absolute;
top: 24px;
right: 0;
opacity: 0.3;
bottom: 24px;
}
&:before {
content: "";
background: @primary-color;
position: absolute;
height: 0;
bottom: -1px;
left: 22px;
right: 22px;
border-radius: 3px;
transition: .3s;
}
&:hover,
&.h-tabs-selected {
.code,
.name {
color: @primary-color;
}
}
&.h-tabs-selected {
&:before {
height: 3px;
}
}
}
&.last-float-right {
>div:nth-last-child(2) {
&:after {
content: none;
}
}
>div:last-child {
float: right;
&:after {
content: none;
}
}
}
}
.common-list-container {
.common-list-item {
padding-top: 14px;
padding-bottom: 14px;
align-items: center;
display: flex;
padding: 12px 0;
border-bottom: @border;
.common-list-meta {
flex: 1;
}
}
}
.common-panel-tabs {
border-bottom: 1px solid #eeeeee;
padding: 0 25px;
font-size: 18px;
> .h-tabs-item {
padding: 24px 0px;
+ div {
margin-left: 30px;
}
}
}
.frame-page,
.frame-flex-page {
margin: 30px;
.clearfix;
&.frame-flex-page {
display: flex;
padding: 20px 0;
}
.frame-left {
width: 224px;
border-right: @border;
margin-right: -1px;
}
.frame-main {
flex: 1;
border-left: @border;
padding: 8px 40px;
.subframe-title {
font-size: 20px;
color: rgba(0, 0, 0, .85);
line-height: 28px;
font-weight: 500;
margin-bottom: 12px;
}
}
}
.error-page {
height: calc(~"100vh - @{layout-header-height} -100px");
text-align: center;
.background-image {
height: 35vh;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
margin: 18vh auto 50px;
}
p {
font-size: 22px;
color: #3788ee;
margin-bottom: 20vh;
}
}
::-webkit-scrollbar {
width: 12px;
height: 12px;
}
::-webkit-scrollbar-thumb {
background-color: hsla(0,0%,44%,.06);
border-radius: 12px;
}
::-webkit-scrollbar-thumb:hover {
background-color: @primary-color;
border-radius: 12px
}
\ No newline at end of file
body {
padding: 0;
margin: 0;
font-family: sans-serif;
font-size: 1em;
line-height: 1.5;
color: #555;
background: #fff;
}
h1 {
font-size: 1.5em;
font-weight: normal;
}
small {
font-size: .66666667em;
}
a {
color: #e74c3c;
text-decoration: none;
}
a:hover, a:focus {
box-shadow: 0 1px #e74c3c;
}
.bshadow0, input {
box-shadow: inset 0 -2px #e7e7e7;
}
input:hover {
box-shadow: inset 0 -2px #ccc;
}
input, fieldset {
font-family: sans-serif;
font-size: 1em;
margin: 0;
padding: 0;
border: 0;
}
input {
color: inherit;
line-height: 1.5;
height: 1.5em;
padding: .25em 0;
}
input:focus {
outline: none;
box-shadow: inset 0 -2px #449fdb;
}
.glyph {
font-size: 16px;
width: 15em;
padding-bottom: 1em;
margin-right: 4em;
margin-bottom: 1em;
float: left;
overflow: hidden;
}
.liga {
width: 80%;
width: calc(100% - 2.5em);
}
.talign-right {
text-align: right;
}
.talign-center {
text-align: center;
}
.bgc1 {
background: #f1f1f1;
}
.fgc1 {
color: #999;
}
.fgc0 {
color: #000;
}
p {
margin-top: 1em;
margin-bottom: 1em;
}
.mvm {
margin-top: .75em;
margin-bottom: .75em;
}
.mtn {
margin-top: 0;
}
.mtl, .mal {
margin-top: 1.5em;
}
.mbl, .mal {
margin-bottom: 1.5em;
}
.mal, .mhl {
margin-left: 1.5em;
margin-right: 1.5em;
}
.mhmm {
margin-left: 1em;
margin-right: 1em;
}
.mls {
margin-left: .25em;
}
.ptl {
padding-top: 1.5em;
}
.pbs, .pvs {
padding-bottom: .25em;
}
.pvs, .pts {
padding-top: .25em;
}
.unit {
float: left;
}
.unitRight {
float: right;
}
.size1of2 {
width: 50%;
}
.size1of1 {
width: 100%;
}
.clearfix:before, .clearfix:after {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
.hidden-true {
display: none;
}
.textbox0 {
width: 3em;
background: #f1f1f1;
padding: .25em .5em;
line-height: 1.5;
height: 1.5em;
}
#testDrive {
display: block;
padding-top: 24px;
line-height: 1.5;
}
.fs0 {
font-size: 16px;
}
.fs1 {
font-size: 32px;
}
if (!('boxShadow' in document.body.style)) {
document.body.setAttribute('class', 'noBoxShadow');
}
document.body.addEventListener('click', function (e) {
var target = e.target;
if (target.tagName === 'INPUT' && target.getAttribute('class').indexOf('liga') === -1) {
target.select();
}
});
(function () {
var fontSize = document.getElementById('fontSize');
var testDrive = document.getElementById('testDrive');
var testText = document.getElementById('testText');
function updateTest() {
testDrive.innerHTML = testText.value || String.fromCharCode(160);
if (window.icomoonLiga) {
window.icomoonLiga(testDrive);
}
}
function updateSize() {
testDrive.style.fontSize = fontSize.value + 'px';
}
fontSize.addEventListener('change', updateSize, false);
testText.addEventListener('input', updateTest, false);
testText.addEventListener('change', updateTest, false);
updateSize();
})();
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
@font-face {
font-family: 'heyuiadmin';
src: url('fonts/heyuiadmin.eot?minjmi');
src: url('fonts/heyuiadmin.eot?minjmi#iefix') format('embedded-opentype'),
url('fonts/heyuiadmin.ttf?minjmi') format('truetype'),
url('fonts/heyuiadmin.woff?minjmi') format('woff'),
url('fonts/heyuiadmin.svg?minjmi#heyuiadmin') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'heyuiadmin' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-eye:before {
content: "\e000";
}
.icon-paper-clip:before {
content: "\e001";
}
.icon-mail:before {
content: "\e002";
}
.icon-toggle:before {
content: "\e003";
}
.icon-layout:before {
content: "\e004";
}
.icon-link:before {
content: "\e005";
}
.icon-bell:before {
content: "\e006";
}
.icon-lock:before {
content: "\e007";
}
.icon-unlock:before {
content: "\e008";
}
.icon-ribbon:before {
content: "\e009";
}
.icon-image:before {
content: "\e010";
}
.icon-signal:before {
content: "\e011";
}
.icon-target:before {
content: "\e012";
}
.icon-clipboard:before {
content: "\e013";
}
.icon-clock:before {
content: "\e014";
}
.icon-watch:before {
content: "\e015";
}
.icon-air-play:before {
content: "\e016";
}
.icon-camera:before {
content: "\e017";
}
.icon-video:before {
content: "\e018";
}
.icon-disc:before {
content: "\e019";
}
.icon-printer:before {
content: "\e020";
}
.icon-monitor:before {
content: "\e021";
}
.icon-server:before {
content: "\e022";
}
.icon-cog:before {
content: "\e023";
}
.icon-heart:before {
content: "\e024";
}
.icon-paragraph:before {
content: "\e025";
}
.icon-align-justify:before {
content: "\e026";
}
.icon-align-left:before {
content: "\e027";
}
.icon-align-center:before {
content: "\e028";
}
.icon-align-right:before {
content: "\e029";
}
.icon-book:before {
content: "\e030";
}
.icon-layers:before {
content: "\e031";
}
.icon-stack:before {
content: "\e032";
}
.icon-stack-2:before {
content: "\e033";
}
.icon-paper:before {
content: "\e034";
}
.icon-paper-stack:before {
content: "\e035";
}
.icon-search:before {
content: "\e036";
}
.icon-zoom-in:before {
content: "\e037";
}
.icon-zoom-out:before {
content: "\e038";
}
.icon-reply:before {
content: "\e039";
}
.icon-circle-plus:before {
content: "\e040";
}
.icon-circle-minus:before {
content: "\e041";
}
.icon-circle-check:before {
content: "\e042";
}
.icon-circle-cross:before {
content: "\e043";
}
.icon-square-plus:before {
content: "\e044";
}
.icon-square-minus:before {
content: "\e045";
}
.icon-square-check:before {
content: "\e046";
}
.icon-square-cross:before {
content: "\e047";
}
.icon-microphone:before {
content: "\e048";
}
.icon-record:before {
content: "\e049";
}
.icon-skip-back:before {
content: "\e050";
}
.icon-rewind:before {
content: "\e051";
}
.icon-play:before {
content: "\e052";
}
.icon-pause:before {
content: "\e053";
}
.icon-stop:before {
content: "\e054";
}
.icon-fast-forward:before {
content: "\e055";
}
.icon-skip-forward:before {
content: "\e056";
}
.icon-shuffle:before {
content: "\e057";
}
.icon-repeat:before {
content: "\e058";
}
.icon-folder:before {
content: "\e059";
}
.icon-umbrella:before {
content: "\e060";
}
.icon-moon:before {
content: "\e061";
}
.icon-thermometer:before {
content: "\e062";
}
.icon-drop:before {
content: "\e063";
}
.icon-sun:before {
content: "\e064";
}
.icon-cloud:before {
content: "\e065";
}
.icon-cloud-upload:before {
content: "\e066";
}
.icon-cloud-download:before {
content: "\e067";
}
.icon-upload:before {
content: "\e068";
}
.icon-download:before {
content: "\e069";
}
.icon-location:before {
content: "\e070";
}
.icon-location-2:before {
content: "\e071";
}
.icon-map:before {
content: "\e072";
}
.icon-battery:before {
content: "\e073";
}
.icon-head:before {
content: "\e074";
}
.icon-briefcase:before {
content: "\e075";
}
.icon-speech-bubble:before {
content: "\e076";
}
.icon-anchor:before {
content: "\e077";
}
.icon-globe:before {
content: "\e078";
}
.icon-box:before {
content: "\e079";
}
.icon-reload:before {
content: "\e080";
}
.icon-share:before {
content: "\e081";
}
.icon-marquee:before {
content: "\e082";
}
.icon-marquee-plus:before {
content: "\e083";
}
.icon-marquee-minus:before {
content: "\e084";
}
.icon-tag:before {
content: "\e085";
}
.icon-power:before {
content: "\e086";
}
.icon-command:before {
content: "\e087";
}
.icon-alt:before {
content: "\e088";
}
.icon-esc:before {
content: "\e089";
}
.icon-bar-graph:before {
content: "\e090";
}
.icon-bar-graph-2:before {
content: "\e091";
}
.icon-pie-graph:before {
content: "\e092";
}
.icon-star:before {
content: "\e093";
}
.icon-arrow-left:before {
content: "\e094";
}
.icon-arrow-right:before {
content: "\e095";
}
.icon-arrow-up:before {
content: "\e096";
}
.icon-arrow-down:before {
content: "\e097";
}
.icon-volume:before {
content: "\e098";
}
.icon-mute:before {
content: "\e099";
}
.icon-content-right:before {
content: "\e100";
}
.icon-content-left:before {
content: "\e101";
}
.icon-grid:before {
content: "\e102";
}
.icon-grid-2:before {
content: "\e103";
}
.icon-columns:before {
content: "\e104";
}
.icon-loader:before {
content: "\e105";
}
.icon-bag:before {
content: "\e106";
}
.icon-ban:before {
content: "\e107";
}
.icon-flag:before {
content: "\e108";
}
.icon-trash:before {
content: "\e109";
}
.icon-expand:before {
content: "\e110";
}
.icon-contract:before {
content: "\e111";
}
.icon-maximize:before {
content: "\e112";
}
.icon-minimize:before {
content: "\e113";
}
.icon-plus:before {
content: "\e114";
}
.icon-minus:before {
content: "\e115";
}
.icon-check:before {
content: "\e116";
}
.icon-cross:before {
content: "\e117";
}
.icon-move:before {
content: "\e118";
}
.icon-delete:before {
content: "\e119";
}
.icon-menu:before {
content: "\e120";
}
.icon-archive:before {
content: "\e121";
}
.icon-inbox:before {
content: "\e122";
}
.icon-outbox:before {
content: "\e123";
}
.icon-file:before {
content: "\e124";
}
.icon-file-add:before {
content: "\e125";
}
.icon-file-subtract:before {
content: "\e126";
}
.icon-help:before {
content: "\e127";
}
.icon-open:before {
content: "\e128";
}
.icon-ellipsis:before {
content: "\e129";
}
@import "variables";
@font-face {
font-family: '@{icomoon-font-family}';
src: url('@{icomoon-font-path}/@{icomoon-font-family}.eot?minjmi');
src: url('@{icomoon-font-path}/@{icomoon-font-family}.eot?minjmi#iefix') format('embedded-opentype'),
url('@{icomoon-font-path}/@{icomoon-font-family}.ttf?minjmi') format('truetype'),
url('@{icomoon-font-path}/@{icomoon-font-family}.woff?minjmi') format('woff'),
url('@{icomoon-font-path}/@{icomoon-font-family}.svg?minjmi#@{icomoon-font-family}') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: '@{icomoon-font-family}' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-eye {
&:before {
content: @icon-eye;
}
}
.icon-paper-clip {
&:before {
content: @icon-paper-clip;
}
}
.icon-mail {
&:before {
content: @icon-mail;
}
}
.icon-toggle {
&:before {
content: @icon-toggle;
}
}
.icon-layout {
&:before {
content: @icon-layout;
}
}
.icon-link {
&:before {
content: @icon-link;
}
}
.icon-bell {
&:before {
content: @icon-bell;
}
}
.icon-lock {
&:before {
content: @icon-lock;
}
}
.icon-unlock {
&:before {
content: @icon-unlock;
}
}
.icon-ribbon {
&:before {
content: @icon-ribbon;
}
}
.icon-image {
&:before {
content: @icon-image;
}
}
.icon-signal {
&:before {
content: @icon-signal;
}
}
.icon-target {
&:before {
content: @icon-target;
}
}
.icon-clipboard {
&:before {
content: @icon-clipboard;
}
}
.icon-clock {
&:before {
content: @icon-clock;
}
}
.icon-watch {
&:before {
content: @icon-watch;
}
}
.icon-air-play {
&:before {
content: @icon-air-play;
}
}
.icon-camera {
&:before {
content: @icon-camera;
}
}
.icon-video {
&:before {
content: @icon-video;
}
}
.icon-disc {
&:before {
content: @icon-disc;
}
}
.icon-printer {
&:before {
content: @icon-printer;
}
}
.icon-monitor {
&:before {
content: @icon-monitor;
}
}
.icon-server {
&:before {
content: @icon-server;
}
}
.icon-cog {
&:before {
content: @icon-cog;
}
}
.icon-heart {
&:before {
content: @icon-heart;
}
}
.icon-paragraph {
&:before {
content: @icon-paragraph;
}
}
.icon-align-justify {
&:before {
content: @icon-align-justify;
}
}
.icon-align-left {
&:before {
content: @icon-align-left;
}
}
.icon-align-center {
&:before {
content: @icon-align-center;
}
}
.icon-align-right {
&:before {
content: @icon-align-right;
}
}
.icon-book {
&:before {
content: @icon-book;
}
}
.icon-layers {
&:before {
content: @icon-layers;
}
}
.icon-stack {
&:before {
content: @icon-stack;
}
}
.icon-stack-2 {
&:before {
content: @icon-stack-2;
}
}
.icon-paper {
&:before {
content: @icon-paper;
}
}
.icon-paper-stack {
&:before {
content: @icon-paper-stack;
}
}
.icon-search {
&:before {
content: @icon-search;
}
}
.icon-zoom-in {
&:before {
content: @icon-zoom-in;
}
}
.icon-zoom-out {
&:before {
content: @icon-zoom-out;
}
}
.icon-reply {
&:before {
content: @icon-reply;
}
}
.icon-circle-plus {
&:before {
content: @icon-circle-plus;
}
}
.icon-circle-minus {
&:before {
content: @icon-circle-minus;
}
}
.icon-circle-check {
&:before {
content: @icon-circle-check;
}
}
.icon-circle-cross {
&:before {
content: @icon-circle-cross;
}
}
.icon-square-plus {
&:before {
content: @icon-square-plus;
}
}
.icon-square-minus {
&:before {
content: @icon-square-minus;
}
}
.icon-square-check {
&:before {
content: @icon-square-check;
}
}
.icon-square-cross {
&:before {
content: @icon-square-cross;
}
}
.icon-microphone {
&:before {
content: @icon-microphone;
}
}
.icon-record {
&:before {
content: @icon-record;
}
}
.icon-skip-back {
&:before {
content: @icon-skip-back;
}
}
.icon-rewind {
&:before {
content: @icon-rewind;
}
}
.icon-play {
&:before {
content: @icon-play;
}
}
.icon-pause {
&:before {
content: @icon-pause;
}
}
.icon-stop {
&:before {
content: @icon-stop;
}
}
.icon-fast-forward {
&:before {
content: @icon-fast-forward;
}
}
.icon-skip-forward {
&:before {
content: @icon-skip-forward;
}
}
.icon-shuffle {
&:before {
content: @icon-shuffle;
}
}
.icon-repeat {
&:before {
content: @icon-repeat;
}
}
.icon-folder {
&:before {
content: @icon-folder;
}
}
.icon-umbrella {
&:before {
content: @icon-umbrella;
}
}
.icon-moon {
&:before {
content: @icon-moon;
}
}
.icon-thermometer {
&:before {
content: @icon-thermometer;
}
}
.icon-drop {
&:before {
content: @icon-drop;
}
}
.icon-sun {
&:before {
content: @icon-sun;
}
}
.icon-cloud {
&:before {
content: @icon-cloud;
}
}
.icon-cloud-upload {
&:before {
content: @icon-cloud-upload;
}
}
.icon-cloud-download {
&:before {
content: @icon-cloud-download;
}
}
.icon-upload {
&:before {
content: @icon-upload;
}
}
.icon-download {
&:before {
content: @icon-download;
}
}
.icon-location {
&:before {
content: @icon-location;
}
}
.icon-location-2 {
&:before {
content: @icon-location-2;
}
}
.icon-map {
&:before {
content: @icon-map;
}
}
.icon-battery {
&:before {
content: @icon-battery;
}
}
.icon-head {
&:before {
content: @icon-head;
}
}
.icon-briefcase {
&:before {
content: @icon-briefcase;
}
}
.icon-speech-bubble {
&:before {
content: @icon-speech-bubble;
}
}
.icon-anchor {
&:before {
content: @icon-anchor;
}
}
.icon-globe {
&:before {
content: @icon-globe;
}
}
.icon-box {
&:before {
content: @icon-box;
}
}
.icon-reload {
&:before {
content: @icon-reload;
}
}
.icon-share {
&:before {
content: @icon-share;
}
}
.icon-marquee {
&:before {
content: @icon-marquee;
}
}
.icon-marquee-plus {
&:before {
content: @icon-marquee-plus;
}
}
.icon-marquee-minus {
&:before {
content: @icon-marquee-minus;
}
}
.icon-tag {
&:before {
content: @icon-tag;
}
}
.icon-power {
&:before {
content: @icon-power;
}
}
.icon-command {
&:before {
content: @icon-command;
}
}
.icon-alt {
&:before {
content: @icon-alt;
}
}
.icon-esc {
&:before {
content: @icon-esc;
}
}
.icon-bar-graph {
&:before {
content: @icon-bar-graph;
}
}
.icon-bar-graph-2 {
&:before {
content: @icon-bar-graph-2;
}
}
.icon-pie-graph {
&:before {
content: @icon-pie-graph;
}
}
.icon-star {
&:before {
content: @icon-star;
}
}
.icon-arrow-left {
&:before {
content: @icon-arrow-left;
}
}
.icon-arrow-right {
&:before {
content: @icon-arrow-right;
}
}
.icon-arrow-up {
&:before {
content: @icon-arrow-up;
}
}
.icon-arrow-down {
&:before {
content: @icon-arrow-down;
}
}
.icon-volume {
&:before {
content: @icon-volume;
}
}
.icon-mute {
&:before {
content: @icon-mute;
}
}
.icon-content-right {
&:before {
content: @icon-content-right;
}
}
.icon-content-left {
&:before {
content: @icon-content-left;
}
}
.icon-grid {
&:before {
content: @icon-grid;
}
}
.icon-grid-2 {
&:before {
content: @icon-grid-2;
}
}
.icon-columns {
&:before {
content: @icon-columns;
}
}
.icon-loader {
&:before {
content: @icon-loader;
}
}
.icon-bag {
&:before {
content: @icon-bag;
}
}
.icon-ban {
&:before {
content: @icon-ban;
}
}
.icon-flag {
&:before {
content: @icon-flag;
}
}
.icon-trash {
&:before {
content: @icon-trash;
}
}
.icon-expand {
&:before {
content: @icon-expand;
}
}
.icon-contract {
&:before {
content: @icon-contract;
}
}
.icon-maximize {
&:before {
content: @icon-maximize;
}
}
.icon-minimize {
&:before {
content: @icon-minimize;
}
}
.icon-plus {
&:before {
content: @icon-plus;
}
}
.icon-minus {
&:before {
content: @icon-minus;
}
}
.icon-check {
&:before {
content: @icon-check;
}
}
.icon-cross {
&:before {
content: @icon-cross;
}
}
.icon-move {
&:before {
content: @icon-move;
}
}
.icon-delete {
&:before {
content: @icon-delete;
}
}
.icon-menu {
&:before {
content: @icon-menu;
}
}
.icon-archive {
&:before {
content: @icon-archive;
}
}
.icon-inbox {
&:before {
content: @icon-inbox;
}
}
.icon-outbox {
&:before {
content: @icon-outbox;
}
}
.icon-file {
&:before {
content: @icon-file;
}
}
.icon-file-add {
&:before {
content: @icon-file-add;
}
}
.icon-file-subtract {
&:before {
content: @icon-file-subtract;
}
}
.icon-help {
&:before {
content: @icon-help;
}
}
.icon-open {
&:before {
content: @icon-open;
}
}
.icon-ellipsis {
&:before {
content: @icon-ellipsis;
}
}
@icomoon-font-family: "heyuiadmin";
@icomoon-font-path: "fonts";
@icon-eye: "\e000";
@icon-paper-clip: "\e001";
@icon-mail: "\e002";
@icon-toggle: "\e003";
@icon-layout: "\e004";
@icon-link: "\e005";
@icon-bell: "\e006";
@icon-lock: "\e007";
@icon-unlock: "\e008";
@icon-ribbon: "\e009";
@icon-image: "\e010";
@icon-signal: "\e011";
@icon-target: "\e012";
@icon-clipboard: "\e013";
@icon-clock: "\e014";
@icon-watch: "\e015";
@icon-air-play: "\e016";
@icon-camera: "\e017";
@icon-video: "\e018";
@icon-disc: "\e019";
@icon-printer: "\e020";
@icon-monitor: "\e021";
@icon-server: "\e022";
@icon-cog: "\e023";
@icon-heart: "\e024";
@icon-paragraph: "\e025";
@icon-align-justify: "\e026";
@icon-align-left: "\e027";
@icon-align-center: "\e028";
@icon-align-right: "\e029";
@icon-book: "\e030";
@icon-layers: "\e031";
@icon-stack: "\e032";
@icon-stack-2: "\e033";
@icon-paper: "\e034";
@icon-paper-stack: "\e035";
@icon-search: "\e036";
@icon-zoom-in: "\e037";
@icon-zoom-out: "\e038";
@icon-reply: "\e039";
@icon-circle-plus: "\e040";
@icon-circle-minus: "\e041";
@icon-circle-check: "\e042";
@icon-circle-cross: "\e043";
@icon-square-plus: "\e044";
@icon-square-minus: "\e045";
@icon-square-check: "\e046";
@icon-square-cross: "\e047";
@icon-microphone: "\e048";
@icon-record: "\e049";
@icon-skip-back: "\e050";
@icon-rewind: "\e051";
@icon-play: "\e052";
@icon-pause: "\e053";
@icon-stop: "\e054";
@icon-fast-forward: "\e055";
@icon-skip-forward: "\e056";
@icon-shuffle: "\e057";
@icon-repeat: "\e058";
@icon-folder: "\e059";
@icon-umbrella: "\e060";
@icon-moon: "\e061";
@icon-thermometer: "\e062";
@icon-drop: "\e063";
@icon-sun: "\e064";
@icon-cloud: "\e065";
@icon-cloud-upload: "\e066";
@icon-cloud-download: "\e067";
@icon-upload: "\e068";
@icon-download: "\e069";
@icon-location: "\e070";
@icon-location-2: "\e071";
@icon-map: "\e072";
@icon-battery: "\e073";
@icon-head: "\e074";
@icon-briefcase: "\e075";
@icon-speech-bubble: "\e076";
@icon-anchor: "\e077";
@icon-globe: "\e078";
@icon-box: "\e079";
@icon-reload: "\e080";
@icon-share: "\e081";
@icon-marquee: "\e082";
@icon-marquee-plus: "\e083";
@icon-marquee-minus: "\e084";
@icon-tag: "\e085";
@icon-power: "\e086";
@icon-command: "\e087";
@icon-alt: "\e088";
@icon-esc: "\e089";
@icon-bar-graph: "\e090";
@icon-bar-graph-2: "\e091";
@icon-pie-graph: "\e092";
@icon-star: "\e093";
@icon-arrow-left: "\e094";
@icon-arrow-right: "\e095";
@icon-arrow-up: "\e096";
@icon-arrow-down: "\e097";
@icon-volume: "\e098";
@icon-mute: "\e099";
@icon-content-right: "\e100";
@icon-content-left: "\e101";
@icon-grid: "\e102";
@icon-grid-2: "\e103";
@icon-columns: "\e104";
@icon-loader: "\e105";
@icon-bag: "\e106";
@icon-ban: "\e107";
@icon-flag: "\e108";
@icon-trash: "\e109";
@icon-expand: "\e110";
@icon-contract: "\e111";
@icon-maximize: "\e112";
@icon-minimize: "\e113";
@icon-plus: "\e114";
@icon-minus: "\e115";
@icon-check: "\e116";
@icon-cross: "\e117";
@icon-move: "\e118";
@icon-delete: "\e119";
@icon-menu: "\e120";
@icon-archive: "\e121";
@icon-inbox: "\e122";
@icon-outbox: "\e123";
@icon-file: "\e124";
@icon-file-add: "\e125";
@icon-file-subtract: "\e126";
@icon-help: "\e127";
@icon-open: "\e128";
@icon-ellipsis: "\e129";
@frame-box-shadow: rgba(0,21,41,.08);
#app{
.app-frame {
min-height: 100vh;
}
.h-layout-sider{
z-index: 2;
box-shadow: 0 1px 4px @frame-box-shadow;
}
.h-layout-header{
overflow: hidden;
box-shadow: 0px 1px 4px 0 @frame-box-shadow;
}
.h-layout-sider-collapsed {
.app-logo{
padding-left: 5px;
}
.h-layout-header-fixed {
.sys-tabs-vue {
left: @layout-sider-collapse-width;
}
}
}
.h-layout-header-fixed {
.sys-tabs-vue {
position: fixed;
top: @layout-header-height;
right: 0;
z-index: 2;
left: @layout-sider-width;
}
.sys-tabs-vue + .h-layout-content {
margin-top: 45px;
}
}
.h-layout-sider-fixed .h-layout-header-fixed {
.h-layout-content {
overflow: auto;
height: calc(~"100vh - @{layout-header-height}");
}
.sys-tabs-vue + .h-layout-content {
height: calc(~"100vh - @{layout-header-height} - @{sys-tabs-height}");
}
}
.h-layout-sider-theme-dark .app-logo a{
color: #FFF;
}
}
@media (max-width: 900px) {
#app {
.app-header-info {
.h-autocomplete, .app-header-icon-item {
display: none;
}
}
.h-layout {
padding-left: 0;
.app-menu-mask {
position: fixed;
left: @layout-sider-width;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.2);
z-index: 1;
}
&.h-layout-sider-collapsed {
> .h-layout-sider {
transform: translateX(-@layout-sider-collapse-width);
overflow: hidden;
}
.app-menu-mask {
display: none;
}
}
}
.h-layout-content {
-webkit-overflow-scrolling: touch;
}
.h-layout-header-fixed .h-layout-header {
left: 0 !important;
}
.sys-tabs-vue {
left: 0 !important;
}
}
}
\ No newline at end of file
.markdown-info-show {
li {
list-style: disc;
}
h1,
h2,
h3,
h4 {
color: #111111;
font-weight: 400;
margin-top: 1em;
}
h1,
h2,
h3,
h4,
h5,
p,
dl {
margin-bottom: 16px;
padding: 0;
}
h1 {
font-size: 38px;
line-height: 54px;
}
h2 {
font-size: 30px;
line-height: 42px;
}
h1,
h2 {
border-bottom: 1px solid #EFEAEA;
padding-bottom: 10px;
}
h3 {
font-size: 24px;
line-height: 30px;
}
h4 {
font-size: 21px;
line-height: 26px;
}
h5 {
font-size: 18px;
list-style: 23px;
}
a {
color: #0099ff;
margin: 0;
padding: 0;
vertical-align: baseline;
}
a:hover {
text-decoration: none;
color: #ff6600;
}
a:visited {
/*color: purple;*/
}
ul,
ol {
padding: 0;
padding-left: 24px;
margin: 0;
}
li {
line-height: 24px;
}
p,
ul,
ol {
font-size: 16px;
line-height: 24px;
}
ol ol,
ul ol {
list-style-type: lower-roman;
}
code,
pre {
border-radius: 3px;
background-color: #f7f7f7;
color: inherit;
}
code {
font-family: Consolas, Monaco, Andale Mono, monospace;
margin: 0 2px;
}
pre {
line-height: 1.7em;
overflow: auto;
padding: 6px 10px;
border-left: 5px solid @primary-color;
}
pre>code {
border: 0;
display: inline;
max-width: initial;
padding: 0;
margin: 0;
overflow: initial;
line-height: inherit;
font-size: .85em;
white-space: pre;
background: 0 0;
}
code {
color: #666555;
}
aside {
display: block;
float: right;
width: 390px;
}
blockquote {
border-left: .5em solid #eee;
padding: 0 0 0 2em;
margin-left: 0;
}
blockquote cite {
font-size: 14px;
line-height: 20px;
color: #bfbfbf;
}
blockquote cite:before {
content: '\2014 \00A0';
}
blockquote p {
color: #666;
}
hr {
text-align: left;
color: #999;
height: 2px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
}
dl {
padding: 0;
}
dl dt {
padding: 10px 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: bold;
}
dl dd {
padding: 0 16px;
margin-bottom: 16px;
}
dd {
margin-left: 0;
}
}
\ No newline at end of file
.h-panel {
border: none;
&-title {
color: @dark-color;
}
&-bar {
padding: 15px 25px;
}
&-tabs-bar {
.h-tabs-default > .h-tabs-item {
padding: 16px 15px;
font-size: 18px;
}
}
&-bar-s {
padding-top: 8px;
padding-bottom: 8px;
.h-panel-title {
font-size: 15px;
}
}
&-body {
padding: 25px;
}
}
.h-menu-white .h-menu-li .h-menu-li-selected {
background-color: #f0f6ff;
}
.h-table {
td, th {
padding: 10px 0 10px 16px;
height: 48px;
}
}
\ No newline at end of file
@import (css) "~wangeditor/release/wangEditor.min.css";
.w-e-text-container {
border-radius: 0 0 3px 3px;
border-color: #e4e4e4 !important;
.w-e-panel-container .w-e-panel-tab-content input[type=text] {
height: 30px;
border-radius: 0px;
&:focus {
box-shadow: none;
}
}
}
.w-e-toolbar {
border-radius: 3px 3px 0 0;
border-color: #e4e4e4 !important;
}
\ No newline at end of file
const vars = require('heyui/themes/var.js');
Object.assign(vars, {
'primary-color': '#3788ee',
'link-color': '#3788ee',
'blue-color': '#2d7bf4',
'green-color': '#0acf97',
'yellow-color': '#f9bc0b',
'red-color': '#f1556c',
'hover-background-color': '#f8f8f8',
'input-height': '32px',
'layout-header-height': '60px',
'layout-sider-width': '240px',
'layout-sider-collapse-width': '70px',
'menu-dark-color': '#001529',
'menu-white-background-color': '#ecf8f2',
'sys-tabs-height': '45px'
});
module.exports = vars;
@import (less) "~heyui/themes/var.less";
@primary-color: #3788ee;
@red-color: #f1556c;
@green-color: #0acf97;
@yellow-color: #f9bc0b;
@blue-color: #2d7bf4;
@input-height: 32px;
@layout-sider-width: 240px;
@layout-header-height: 60px;
@menu-dark-color: #001529;
@sys-tabs-height: 45px;
\ No newline at end of file
/* eslint-disable */
import { saveAs } from 'file-saver'
import XLSX from 'xlsx'
......
/* eslint-disable */
import { saveAs } from 'file-saver'
import JSZip from 'jszip'
......
......@@ -210,7 +210,7 @@ export default {
},
};
</script>
<style lang="less" scoped>
<style lang="scss" scoped>
.app-container {
& > div.page-wrapper {
margin: 10px 0px;
......
<template>
<div class="app-container">
<el-form :inline="true" :model="form" size="mini">
<el-form-item><el-button type="warning" @click="onAdd">绑定设备</el-button></el-form-item>
</el-form>
<el-table v-loading="isLoading" element-loading-text="Loading" :data="list" size="mini" border stripe fit highlight-current-row>
<el-table-column prop="name" label="设备名称" align="center" min-width="100"></el-table-column>
<el-table-column prop="imei" label="IMEI" align="center" width="150"></el-table-column>
<el-table-column prop="create_at" label="创建时间" width="150"></el-table-column>
<el-table-column prop="create_by.username" label="创建者" width="150"></el-table-column>
<el-table-column prop="update_at" label="更新时间" width="150" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="update_by.username" label="更新者" width="150"></el-table-column>
<el-table-column label="操作" align="center" width="180" fixed="right">
<template slot-scope="scope">
<el-button size="mini" type="success" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="page-wrapper">
<el-pagination @current-change="handleCurrentChange" :current-page.sync="form.pagenum" background small :page-size="form.pagesize" :pager-count="5" layout="pager, prev, next, total" :total="total"></el-pagination>
</div>
<el-dialog
:title="dialogTitle"
:visible.sync="dialogVisible"
width="45%"
>
<el-form :model="post" status-icon :rules="rules" ref="post" size="mini" label-width="100px">
<el-form-item label="设备名称" prop="name">
<el-input type="text" v-model="post.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="IMEI" prop="imei">
<el-input type="text" v-model="post.imei" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="设备描述" prop="desc">
<el-input type="text" v-model="post.desc" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" plain @click="submitForm('post')">提交</el-button>
<el-button type="success" size="mini" plain @click="onReset('post')">重置</el-button>
<el-button size="mini" @click="dialogVisible = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getDeviceList, deleteDevice, addDevice, updateDevice } from '@/api/app-store'
import { mapTrim, compareObjectDiff } from '@/utils/index'
export default {
name: "Device",
data() {
return {
total: 0,
list: [],
isLoading: false,
roles: [],
depots: [],
form: {
uuid: null,
name: null,
pagesize: 15,
pagenum: 1
},
dialogTitle: "",
dialogVisible: false,
post: {
imei: null,
name: null,
type: "watch",
desc: null
},
rules: {
imei: [{ type: 'string', required: true, message: 'IMEI不能为空', trigger: 'blur' }],
name: [
{ type: 'string', required: true, message: '用户名不能为空', trigger: 'blur' },
{ min: 1, max: 20, message: '字符串长度在 1 到 20 之间', trigger: 'blur' }
]
}
}
},
methods: {
fetchData(params) {
this.isLoading = true
getDeviceList(Object.assign({
pagenum: this.form.pagenum,
pagesize: this.form.pagesize,
}, params)).then(res => {
if (res.code == 200) {
this.total = res.count
this.list = res.data
}
}).catch(err => {
// this.$message.error(err.message)
console.log(err.message)
}).finally(() => {
this.isLoading = false
})
},
fetchSelectData() {
getDeviceList({ "scope_type": "list" }).then(res => {
this.roles = res.data
}).catch(err => {
// this.$message.error(err.message)
console.log(err.message)
})
},
handleSizeChange(e) {
this.form.pagesize = e
this.fetchData(mapTrim(this.form))
},
handleCurrentChange(e) {
this.form.pagenum = e
this.fetchData(mapTrim(this.form))
},
handleEdit(index, row) {
this.post.name = row.name
this.post.imei = row.imei
this.post.desc = row.desc
this.dialogTitle = "编辑"
this.dialogVisible = true
},
handleDelete(index, row) {
this.$alert('您确定要删除么?删除操作将不可恢复。如需取消操作,请点击右上角关闭按钮。', '删除提醒', {
confirmButtonText: '确定',
callback: action => {
if (action == 'confirm') deleteDevice(row.id).then(res => {
console.log(res)
this.total -= 1
this.$delete(this.list, index)
this.$message({ type: 'success', message: `成功删除第${ index }行` })
this.fetchData(mapTrim(this.form))
}).catch(err => {
this.$message.error(err.message)
})
}
})
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
let result = true
if (valid) {
if (this.dialogTitle === '添加') addDevice(mapTrim(this.post)).then(res => {
console.log(res)
this.$message({ type: 'success', message: res.message })
this.fetchData(mapTrim(this.form))
}).catch(err => {
this.$message.error(err.message)
})
else if (this.dialogTitle === '编辑') updateDevice(this.currentValue.id, compareObjectDiff(this.post, this.currentValue)).then(res => {
console.log(res)
// this.$set(this.list, this.currentIndex, Object.assign(this.currentValue, tmp))
this.$message({ type: 'success', message: '更新成功' })
this.fetchData(mapTrim(this.form))
}).catch(err => {
this.$message.error(err.message)
})
} else {
result = false
}
this.dialogVisible = false
return result
})
},
onAdd() {
this.dialogTitle = "添加"
this.dialogVisible = true
},
onSubmit() {
this.form.pagenum = 1
this.form.pagesize = 15
this.fetchData(mapTrim(this.form))
},
onReset(formName) {
this.form.name = null
this.form.pagesize = 15
this.form.pagenum = 1
this.$refs[formName].resetFields()
this.fetchData()
}
},
mounted() {
},
created() {
this.fetchData()
this.fetchSelectData()
}
}
</script>
<style lang="scss" scoped>
.app-container {
& > div.page-wrapper {
margin: 10px 0px;
}
}
</style>
<template>
<div class="container">
<iframe src="https://www.yuque.com/dragondjf/ihusbn" height="100%" width="100%" name="demo" scrolling="auto" frameborder="0"></iframe>
</div>
</template>
<script>
export default {
name: "Document",
components: {},
data() {
return {};
},
computed: {},
methods: {},
beforeMount() {},
};
</script>
<style lang="scss" scoped>
.container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
& > img {
display: block;
}
}
</style>
\ No newline at end of file
......@@ -100,7 +100,7 @@ export default {
}
}
</script>
<style lang="less" scoped>
<style lang="scss" scoped>
.app-container {
& > div.page-wrapper {
margin: 10px 0px;
......
......@@ -226,7 +226,7 @@ export default {
}
}
</script>
<style lang="less" scoped>
<style lang="scss" scoped>
.app-container {
& > div.page-wrapper {
margin: 10px 0px;
......
......@@ -321,7 +321,6 @@ export default {
});
})
.catch((err) => {
// this.$message.error(err.message)
console.log(err.message);
})
.finally(() => {
......@@ -488,7 +487,7 @@ export default {
},
};
</script>
<style lang="less" scoped>
<style lang="scss" scoped>
.app-container {
& > div.page-wrapper {
margin: 10px 0px;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -301,7 +301,7 @@ export default {
}
}
</script>
<style lang="less" scoped>
<style lang="scss" scoped>
.app-container {
& > div.page-wrapper {
margin: 10px 0px;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<template>
<div class="m-index">
<div
class="banner"
style="
background: url(http://gtms01.alicdn.com/tps/i1/TB1rGYSGFXXXXawXXXXDcMi7VXX-1440-336.png)
no-repeat center 0 #657284;
"
>
<a class="btn" href="#newapp/upload"></a>
</div>
<div class="con">
<p class="nav2 clearfix">
<a class="one one1" href="#certify/certify"> 开发者实名认证 </a>
<a class="one one2" href="#newapp/upload"> 上传新应用 </a>
<a class="one one3" href="#claim/sift"> 认领新应用 </a>
<a class="one one4" href="#myapp/spu_list"> 我的应用 </a>
<a class="one one5" href="#generalize"> 申请推广 </a>
</p>
</div>
</div>
</template>
\ 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.
......@@ -355,7 +355,7 @@ export default {
};
</script>
<style lang="less" scoped>
<style lang="scss" scoped>
.app-container {
& > div.page-wrapper {
margin: 10px 0px;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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