Commit 0b4cfe28 authored by wanliofficial's avatar wanliofficial

update

parents 05abb229 735d39eb
......@@ -27,6 +27,9 @@ deploy/
build/
venv/
node_modules
frontend_backup
logs/*.log
logs/*.log.*
*.db
......@@ -49,6 +52,9 @@ backend/backupData.json
config.ini
*.epk
tools/build_out/logs
tools/build_out/logs/*
release/
release.*
......
......@@ -24,4 +24,4 @@ pip3 install -r requirements.txt
如果有新安装的包,需要更新requirements.txt文件
```
pip freeze > requirements.txt
```
\ No newline at end of file
```
......@@ -21,4 +21,4 @@ backup_dir = backup
evueapps_dir = evueapps
launcher_dir = launcher
host = 127.0.0.1
port = 5000
\ No newline at end of file
port = 5001
\ No newline at end of file
#!/usr/bin/env bash
<<<<<<< HEAD
Cur_Dir=$(pwd)
source venv/bin/activate
nohup ${Cur_Dir}/venv/bin/python3 ${Cur_Dir}/start.py > runoob.log 2>&1 &
=======
Cur_Dir=$(pwd)
source venv/bin/activate
nohup ${Cur_Dir}/venv/bin/python3 ${Cur_Dir}/start.py > runoob.log 2>&1 &
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
......@@ -131,6 +131,7 @@ def filter_dict(source: dict, rules_list: list):
return result
def sql_filter(sql):
return re.sub(r"[\"\\/*\'=\-#;<>+%$()!@]", "", sql)
......
......@@ -122,7 +122,11 @@ class EpkApp(object):
files.insert(0, finfo)
else:
files.append(finfo)
<<<<<<< HEAD
=======
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
if fext == ".evue":
self.fileMD5(finfo)
......@@ -144,9 +148,9 @@ class EpkApp(object):
filecontent = f.read()
newmd5 = self.md5(filecontent)
with open(md5path, "wb") as f:
f.write(newmd5)
return newmd5
def sign(self, content):
......
......@@ -98,7 +98,7 @@ class EpkApp(object):
fsize = jspath.info.size
fbasename, fext = os.path.splitext(jspath.info.name)
if fext in ["", "exe", "dll", "nv", "conf"]:
if fext in ["", ".exe", ".dll", ".nv", ".conf"]:
continue
finfo = {
......@@ -114,7 +114,7 @@ class EpkApp(object):
else:
files.append(finfo)
if fext == "evue":
if fext == ".evue":
self.fileMD5(finfo)
return files
......
......@@ -31,7 +31,7 @@ module.exports = {
// change xxx-api/login => mock/login
// detail: https://cli.vuejs.org/config/#devserver-proxy
"/api/v1": {
target: "http://127.0.0.1:5000/",
target: "http://127.0.0.1:5001/",
changeOrigin: true,
pathRewrite: {},
},
......
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from controllers import initConnect
initConnect()
\ No newline at end of file
......@@ -98,7 +98,14 @@ def create_app(config):
# 自定义abort 400 响应数据格式
flask_restful.abort = _custom_abort
# 数据库初始化
<<<<<<< HEAD
db.init_app(app)
=======
# db.app = app
db.init_app(app)
# 创建表
db.create_all()
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
# 注册蓝图
from views import api_v1
app.register_blueprint(api_v1, url_prefix='/api/v1')
......
......@@ -32,13 +32,24 @@ class ProductionConfig(object):
MYSQL_PORT = 3306
MYSQL_USER = 'debian-sys-maint'
MYSQL_PWD = 'XMigC2B2uugnv18y'
<<<<<<< HEAD
SQLALCHEMY_BINDS = "sqlite:////test.db"
SQLALCHEMY_DATABASE_URI = "sqlite:////test.db"
=======
SQLALCHEMY_BINDS = {
'app-store': 'sqlite:///../test.db'
}
SQLALCHEMY_DATABASE_URI = 'sqlite:///../test.db'
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def __init__(self):
super().__init__()
<<<<<<< HEAD
self.SQLALCHEMY_DATABASE_URI = "sqlite:////test.db"
=======
self.SQLALCHEMY_DATABASE_URI = 'sqlite:///../test.db'
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class DevelopConfig(object):
......@@ -66,15 +77,26 @@ class DevelopConfig(object):
MYSQL_PORT = 3306
MYSQL_USER = 'debian-sys-maint'
MYSQL_PWD = 'XMigC2B2uugnv18y'
<<<<<<< HEAD
SQLALCHEMY_BINDS = "sqlite:////test.db"
SQLALCHEMY_DATABASE_URI = "sqlite:////test.db"
=======
SQLALCHEMY_BINDS = {
'app-store': 'sqlite:///../test.db'
}
SQLALCHEMY_DATABASE_URI = 'sqlite:///../test.db'
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
SQLALCHEMY_TRACK_MODIFICATIONS = True
SQLALCHEMY_ECHO = False
def __init__(self):
super().__init__()
<<<<<<< HEAD
self.SQLALCHEMY_DATABASE_URI = "sqlite:////test.db"
=======
self.SQLALCHEMY_DATABASE_URI = 'sqlite:///../test.db'
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
if MODE == 'production':
config = ProductionConfig()
......
......@@ -21,6 +21,10 @@ class SignalManager(object):
actionGetListUser = PySignal()
actionGetUser = PySignal()
actionPutUser = PySignal()
<<<<<<< HEAD
=======
actionPostLogin = PySignal()
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
actionGetListLogin = PySignal()
actionGetLogin = PySignal()
......
#!/usr/bin/env python
# -*- coding: utf_8 -*-
<<<<<<< HEAD
from application.app import signalManager
=======
from application.signal_manager import signalManager
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from .area import areaManager
from .app import appManager
from .package import packageManager
......@@ -26,7 +30,13 @@ def initConnect():
signalManager.actionGetListUser.connect(userManager.getList)
signalManager.actionGetUser.connect(userManager.get)
signalManager.actionPutUser.connect(userManager.put)
<<<<<<< HEAD
signalManager.actionGetListLogin.connect(loginManager.getList)
signalManager.actionGetLogin.connect(loginManager.get)
initConnect()
\ No newline at end of file
initConnect()
=======
signalManager.actionPostLogin.connect(loginManager.post)
signalManager.actionGetListLogin.connect(loginManager.getList)
signalManager.actionGetLogin.connect(loginManager.get)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from datetime import datetime
from application.app import db
from models.app import AppModel
<<<<<<< HEAD
from webcreator.utils import ResponseCode, response_result
=======
from webcreator.log import logger
from webcreator.response import ResponseCode, response_result
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class AppResource(object):
def __init__(self):
super().__init__()
<<<<<<< HEAD
def get(self, params):
# handle business
filters = []
......@@ -25,10 +31,40 @@ class AppResource(object):
return response_result(ResponseCode.OK)
elif result and result.is_delete == False:
return response_result(ResponseCode.EXISTS_ERROR)
=======
def get(self, uuid, params):
# handle business
filters = [AppModel.is_delete==False, AppModel.uuid==uuid]
result = AppModel.query.filter(*filters).first()
if result:
return (True, result)
return (False, result)
def getList(self, params):
# handle business
logger.warn(params)
filters = [AppModel.is_delete==False]
result = AppModel.query.filter(*filters).order_by(AppModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
return (True, result.items, result.total)
def post(self, params, jwt={}):
# handle business
result = AppModel.query.filter(AppModel.app_name == params.get('app_name')).first()
if result and result.is_delete:
result.is_delete = False
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
elif result and result.is_delete == False:
return (False, "record code exists")
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
result = AppModel(**params)
db.session.add(result)
db.session.commit()
<<<<<<< HEAD
return response_result(ResponseCode.OK)
def put(self, id, params, jwt=None):
......@@ -54,5 +90,37 @@ class AppResource(object):
result.is_delete = True
db.session.delete(result)
db.session.commit()
=======
return (True, None)
def put(self, uuid, params, jwt={}):
# handle business
result = AppModel.query.filter(AppModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
if params:
for key, value in params.items():
if value != None: setattr(result, key, value)
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
else:
return (False, "params is null")
def delete(self, uuid, jwt={}):
# handle business
result = AppModel.query.filter(AppModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
result.is_delete = True
db.session.delete(result)
db.session.commit()
return (True, None)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
appManager = AppResource()
\ No newline at end of file
from datetime import datetime
from application.app import db
from models.area import AreaModel
<<<<<<< HEAD
from webcreator.utils import ResponseCode, response_result
=======
from webcreator.log import logger
from webcreator.response import ResponseCode, response_result
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class AreaResource(object):
def __init__(self):
super().__init__()
<<<<<<< HEAD
def get(self, params):
# handle business
filters = []
......@@ -25,10 +31,40 @@ class AreaResource(object):
return response_result(ResponseCode.OK)
elif result and result.is_delete == False:
return response_result(ResponseCode.EXISTS_ERROR)
=======
def get(self, uuid, params):
# handle business
filters = [AreaModel.is_delete==False, AreaModel.uuid==uuid]
result = AreaModel.query.filter(*filters).first()
if result:
return (True, result)
return (False, result)
def getList(self, params):
# handle business
logger.warn(params)
filters = [AreaModel.is_delete==False]
result = AreaModel.query.filter(*filters).order_by(AreaModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
return (True, result.items, result.total)
def post(self, params, jwt={}):
# handle business
result = AreaModel.query.filter(AreaModel.areaCode == params.get('areaCode')).first()
if result and result.is_delete:
result.is_delete = False
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
elif result and result.is_delete == False:
return (False, "record code exists")
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
result = AreaModel(**params)
db.session.add(result)
db.session.commit()
<<<<<<< HEAD
return response_result(ResponseCode.OK)
def put(self, id, params, jwt=None):
......@@ -54,5 +90,37 @@ class AreaResource(object):
result.is_delete = True
db.session.delete(result)
db.session.commit()
=======
return (True, None)
def put(self, uuid, params, jwt={}):
# handle business
result = AreaModel.query.filter(AreaModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
if params:
for key, value in params.items():
if value != None: setattr(result, key, value)
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
else:
return (False, "params is null")
def delete(self, uuid, jwt={}):
# handle business
result = AreaModel.query.filter(AreaModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
result.is_delete = True
db.session.delete(result)
db.session.commit()
return (True, None)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
areaManager = AreaResource()
\ No newline at end of file
from datetime import datetime
from application.app import db
from models.login import LoginModel
<<<<<<< HEAD
from webcreator.utils import ResponseCode, response_result
=======
from webcreator.log import logger
from webcreator.response import ResponseCode, response_result
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class LoginResource(object):
def __init__(self):
super().__init__()
<<<<<<< HEAD
def get(self, params):
# handle business
filters = []
......@@ -25,10 +31,40 @@ class LoginResource(object):
return response_result(ResponseCode.OK)
elif result and result.is_delete == False:
return response_result(ResponseCode.EXISTS_ERROR)
=======
def get(self, uuid, params):
# handle business
filters = [LoginModel.is_delete==False, LoginModel.uuid==uuid]
result = LoginModel.query.filter(*filters).first()
if result:
return (True, result)
return (False, result)
def getList(self, params):
# handle business
logger.warn(params)
filters = [LoginModel.is_delete==False]
result = LoginModel.query.filter(*filters).order_by(LoginModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
return (True, result.items, result.total)
def post(self, params, jwt={}):
# handle business
result = LoginModel.query.filter(LoginModel.user == params.get('user')).first()
if result and result.is_delete:
result.is_delete = False
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
elif result and result.is_delete == False:
return (False, "record code exists")
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
result = LoginModel(**params)
db.session.add(result)
db.session.commit()
<<<<<<< HEAD
return response_result(ResponseCode.OK)
def put(self, id, params, jwt=None):
......@@ -54,5 +90,37 @@ class LoginResource(object):
result.is_delete = True
db.session.delete(result)
db.session.commit()
=======
return (True, None)
def put(self, uuid, params, jwt={}):
# handle business
result = LoginModel.query.filter(LoginModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
if params:
for key, value in params.items():
if value != None: setattr(result, key, value)
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
else:
return (False, "params is null")
def delete(self, uuid, jwt={}):
# handle business
result = LoginModel.query.filter(LoginModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
result.is_delete = True
db.session.delete(result)
db.session.commit()
return (True, None)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
loginManager = LoginResource()
\ No newline at end of file
from datetime import datetime
from application.app import db
from models.package import PackageModel
<<<<<<< HEAD
from webcreator.utils import ResponseCode, response_result
=======
from webcreator.log import logger
from webcreator.response import ResponseCode, response_result
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class PackageResource(object):
def __init__(self):
super().__init__()
<<<<<<< HEAD
def get(self, params):
# handle business
filters = []
......@@ -25,10 +31,40 @@ class PackageResource(object):
return response_result(ResponseCode.OK)
elif result and result.is_delete == False:
return response_result(ResponseCode.EXISTS_ERROR)
=======
def get(self, uuid, params):
# handle business
filters = [PackageModel.is_delete==False, PackageModel.uuid==uuid]
result = PackageModel.query.filter(*filters).first()
if result:
return (True, result)
return (False, result)
def getList(self, params):
# handle business
logger.warn(params)
filters = [PackageModel.is_delete==False]
result = PackageModel.query.filter(*filters).order_by(PackageModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
return (True, result.items, result.total)
def post(self, params, jwt={}):
# handle business
result = PackageModel.query.filter(PackageModel.app == params.get('app')).first()
if result and result.is_delete:
result.is_delete = False
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
elif result and result.is_delete == False:
return (False, "record code exists")
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
result = PackageModel(**params)
db.session.add(result)
db.session.commit()
<<<<<<< HEAD
return response_result(ResponseCode.OK)
def put(self, id, params, jwt=None):
......@@ -54,5 +90,37 @@ class PackageResource(object):
result.is_delete = True
db.session.delete(result)
db.session.commit()
=======
return (True, None)
def put(self, uuid, params, jwt={}):
# handle business
result = PackageModel.query.filter(PackageModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
if params:
for key, value in params.items():
if value != None: setattr(result, key, value)
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
else:
return (False, "params is null")
def delete(self, uuid, jwt={}):
# handle business
result = PackageModel.query.filter(PackageModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
result.is_delete = True
db.session.delete(result)
db.session.commit()
return (True, None)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
packageManager = PackageResource()
\ No newline at end of file
from datetime import datetime
from application.app import db
from models.user import UserModel
<<<<<<< HEAD
from webcreator.utils import ResponseCode, response_result
=======
from webcreator.log import logger
from webcreator.response import ResponseCode, response_result
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class UserResource(object):
def __init__(self):
super().__init__()
<<<<<<< HEAD
def get(self, params):
# handle business
filters = []
......@@ -25,10 +31,40 @@ class UserResource(object):
return response_result(ResponseCode.OK)
elif result and result.is_delete == False:
return response_result(ResponseCode.EXISTS_ERROR)
=======
def get(self, uuid, params):
# handle business
filters = [UserModel.is_delete==False, UserModel.uuid==uuid]
result = UserModel.query.filter(*filters).first()
if result:
return (True, result)
return (False, result)
def getList(self, params):
# handle business
logger.warn(params)
filters = [UserModel.is_delete==False]
result = UserModel.query.filter(*filters).order_by(UserModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
return (True, result.items, result.total)
def post(self, params, jwt={}):
# handle business
result = UserModel.query.filter(UserModel.app_name == params.get('app_name')).first()
if result and result.is_delete:
result.is_delete = False
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
elif result and result.is_delete == False:
return (False, "record code exists")
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
result = UserModel(**params)
db.session.add(result)
db.session.commit()
<<<<<<< HEAD
return response_result(ResponseCode.OK)
def put(self, id, params, jwt=None):
......@@ -54,5 +90,37 @@ class UserResource(object):
result.is_delete = True
db.session.delete(result)
db.session.commit()
=======
return (True, None)
def put(self, uuid, params, jwt={}):
# handle business
result = UserModel.query.filter(UserModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
if params:
for key, value in params.items():
if value != None: setattr(result, key, value)
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
db.session.commit()
return (True, None)
else:
return (False, "params is null")
def delete(self, uuid, jwt={}):
# handle business
result = UserModel.query.filter(UserModel.uuid==uuid).first()
if not result:
return (False, "record not exists")
result.update_by = jwt.get("id", "")
result.update_date = datetime.now()
result.is_delete = True
db.session.delete(result)
db.session.commit()
return (True, None)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
userManager = UserResource()
\ No newline at end of file
......@@ -37,12 +37,15 @@ def run():
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(3000, address='127.0.0.1')
<<<<<<< HEAD
# wsgi_app = WSGIContainer(app)
# application = Application([
# (r'.*', FallbackHandler, dict(fallback=wsgi_app))
# ], **service_config)
# application.listen(3000)
=======
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
IOLoop.instance().start()
......@@ -53,7 +56,10 @@ def debug():
To use: python3 manager.py debug
"""
# app.logger.setLevel(logging.DEBUG)
<<<<<<< HEAD
print("start from here......")
=======
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
app.run(debug=True, port=3000, host='127.0.0.1')
if __name__ == '__main__':
......
# -*- coding: utf-8 -*-
<<<<<<< HEAD
from sqlalchemy import Column, Integer, String
=======
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from sqlalchemy.ext.declarative import declared_attr, declarative_base
class BaseModelMixin(object):
......@@ -26,4 +32,36 @@ class MyMixin(object):
# example:
class MyModel(MyMixin, BaseModel):
<<<<<<< HEAD
name = Column(String(1000))
=======
__tablename__ = 'mymodel'
name = Column(String(20))
fullname = Column(String(32))
password = Column(String(32))
# if __name__ == "__main__":
engine = create_engine('sqlite:///test.db')
BaseModel.metadata.create_all(engine, checkfirst=True)
Session = sessionmaker(bind=engine)
session = Session()
ed_user = MyModel(name='ed', fullname='Ed Jones', password='edspassword')
session.add(ed_user)
session.add_all(
[
MyModel(name='wendy', fullname='Wendy Williams', password='foobar'),
MyModel(name='mary', fullname='Mary Contrary', password='xxg527'),
MyModel(name='fred', fullname='Fred Flinstone', password='blah')
]
)
session.commit()
# our_user = session.query(MyModel).filter_by(name='ed').first()
# print(our_user)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
......@@ -7,6 +7,7 @@ from marshmallow import Schema, fields, INCLUDE, EXCLUDE
class AppModel(PrimaryModel):
__tablename__ = 'evm_app'
<<<<<<< HEAD
app_name = db.Column(db.String(70), index = True)
app_icon = db.Column(db.String(200))
app_version = db.Column(db.String(20))
......@@ -18,6 +19,19 @@ class AppModel(PrimaryModel):
app_screen_size = db.Column(db.Integer)
app_arch = db.Column(db.String(20))
app_review = db.Column(db.String(100))
=======
app_name = db.Column(db.String(70), index = True, nullable = False)
app_icon = db.Column(db.String(200), nullable = False)
app_version = db.Column(db.String(20), nullable = False)
category = db.Column(db.Integer, nullable = False)
category_2th = db.Column(db.Integer, nullable = False)
developer = db.Column(db.Integer, nullable = False)
download_url = db.Column(db.String(20), nullable = False)
app_file_size = db.Column(db.Integer, nullable = False)
app_screen_size = db.Column(db.Integer, nullable = False)
app_arch = db.Column(db.String(20), nullable = False)
app_review = db.Column(db.String(100), nullable = False)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
# __table_args__ = (
# db.Index('idx_xxx', 'xxx', mysql_using='btree'),
......@@ -58,7 +72,11 @@ class AppModel(PrimaryModel):
class PostAppSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AppModel
app_name = ma.auto_field()
......@@ -72,12 +90,19 @@ class PostAppSchema(ma.SQLAlchemySchema):
app_review = ma.auto_field()
postAppSchema = PostAppSchema()
<<<<<<< HEAD
postAppsSchema = PostAppSchema(many=True)
=======
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class DeleteAppSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AppModel
......@@ -86,7 +111,11 @@ deleteAppSchema = DeleteAppSchema()
class GetListAppSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AppModel
page = fields.Integer(required=False)
......@@ -98,11 +127,19 @@ class GetListAppSchema(ma.SQLAlchemySchema):
app_arch = ma.auto_field()
getListAppSchema = GetListAppSchema()
<<<<<<< HEAD
=======
getListAppsSchema = GetListAppSchema(many=True)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class GetAppSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AppModel
app_name = ma.auto_field()
......@@ -116,7 +153,11 @@ getAppSchema = GetAppSchema()
class PutAppSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AppModel
app_name = ma.auto_field()
......
......@@ -7,6 +7,7 @@ from marshmallow import Schema, fields, INCLUDE, EXCLUDE
class AreaModel(PrimaryModel):
__tablename__ = 'evm_area'
<<<<<<< HEAD
areaCode = db.Column(db.String(20), index = True)
areaName = db.Column(db.String(20), index = True)
level = db.Column(db.Integer, default = 1)
......@@ -14,6 +15,15 @@ class AreaModel(PrimaryModel):
center = db.Column(db.String(20), index = True)
parentId = db.Column(db.String(20))
hasChildren = db.Column(db.Boolean)
=======
areaCode = db.Column(db.String(20), index = True, nullable = False)
areaName = db.Column(db.String(20), index = True, nullable = False)
level = db.Column(db.Integer, nullable = False, default = 1)
cityCode = db.Column(db.Integer, nullable = True)
center = db.Column(db.String(20), index = True, nullable = False)
parentId = db.Column(db.String(20), nullable = True)
hasChildren = db.Column(db.Boolean, nullable = True)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
# __table_args__ = (
# db.Index('idx_xxx', 'xxx', mysql_using='btree'),
......@@ -46,22 +56,38 @@ class AreaModel(PrimaryModel):
class PostAreaSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AreaModel
areaCode = ma.auto_field()
areaName = ma.auto_field()
level = ma.auto_field()
<<<<<<< HEAD
=======
parentId = ma.auto_field()
hasChildren = ma.auto_field()
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
cityCode = ma.auto_field()
center = ma.auto_field()
postAreaSchema = PostAreaSchema()
<<<<<<< HEAD
postAreasSchema = PostAreaSchema(many=True)
=======
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class DeleteAreaSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AreaModel
......@@ -70,7 +96,11 @@ deleteAreaSchema = DeleteAreaSchema()
class GetListAreaSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AreaModel
page = fields.Integer(required=False)
......@@ -82,11 +112,19 @@ class GetListAreaSchema(ma.SQLAlchemySchema):
field = fields.String(required=False, length=None)
getListAreaSchema = GetListAreaSchema()
<<<<<<< HEAD
=======
getListAreasSchema = GetListAreaSchema(many=True)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class GetAreaSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = AreaModel
areaName = ma.auto_field()
......@@ -100,6 +138,7 @@ getAreaSchema = GetAreaSchema()
class PutAreaSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
model = AreaModel
......@@ -107,6 +146,15 @@ class PutAreaSchema(ma.SQLAlchemySchema):
level = ma.auto_field()
parentId = ma.auto_field()
hasChildren = ma.auto_field()
=======
unknown = EXCLUDE # 未知字段默认排除
model = AreaModel
areaName = fields.String(required=False, length=None)
level = fields.Integer(required=False)
parentId = fields.String(required=False, length=None)
hasChildren = fields.Boolean(required=False)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
field = fields.String(required=False, length=None)
putAreaSchema = PutAreaSchema()
......@@ -4,6 +4,12 @@ import uuid
from datetime import datetime
from application.app import db
<<<<<<< HEAD
=======
def generate_uuid():
return uuid.uuid1().hex
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class BaseModel(db.Model):
# Flask-SQLAlchemy创建table时,如何声明基类(这个类不会创建表,可以被继承)
# 方法就是把__abstract__这个属性设置为True,这个类为基类,不会被创建为表!
......@@ -18,7 +24,11 @@ class BaseModel(db.Model):
class PrimaryModel(BaseModel):
__abstract__ = True
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
<<<<<<< HEAD
uuid = db.Column(db.String(64), primary_key=True, default=uuid.uuid1)
=======
uuid = db.Column(db.String(64), primary_key=False, default=generate_uuid)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class AutoBaseModel(BaseModel):
__abstract__ = True
......@@ -27,7 +37,11 @@ class AutoBaseModel(BaseModel):
class UuidBaseModel(BaseModel):
__abstract__ = True
<<<<<<< HEAD
id = db.Column(db.String(64), primary_key=True, default=uuid.uuid1)
=======
id = db.Column(db.String(64), primary_key=True, default=generate_uuid)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
sort = db.Column(db.Integer, default=0)
class SortBaseModel(BaseModel):
......
......@@ -7,12 +7,21 @@ from marshmallow import Schema, fields, INCLUDE, EXCLUDE
class LoginModel(PrimaryModel):
__tablename__ = 'evm_login'
<<<<<<< HEAD
user = db.Column(db.Integer)
login_at = db.Column(db.String(200))
user_agent = db.Column(db.String(200))
ip = db.Column(db.String(128))
geo_location = db.Column(db.String(200))
operator = db.Column(db.String(50))
=======
user = db.Column(db.Integer, nullable = False)
login_at = db.Column(db.String(200), nullable = False)
user_agent = db.Column(db.String(200), nullable = False)
ip = db.Column(db.String(128), nullable = False)
geo_location = db.Column(db.String(200), nullable = False)
operator = db.Column(db.String(50), nullable = False)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
# __table_args__ = (
# db.Index('idx_xxx', 'xxx', mysql_using='btree'),
......@@ -39,10 +48,28 @@ class LoginModel(PrimaryModel):
}
<<<<<<< HEAD
class GetListLoginSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
# unknown = EXCLUDE # 未知字段默认排除
=======
class PostLoginSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
unknown = EXCLUDE # 未知字段默认排除
model = LoginModel
account = fields.String(required=True, length=64)
password = fields.String(required=True, length=64)
postLoginSchema = PostLoginSchema()
class GetListLoginSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = LoginModel
page = fields.Integer(required=False)
......@@ -55,11 +82,19 @@ class GetListLoginSchema(ma.SQLAlchemySchema):
operator = ma.auto_field()
getListLoginSchema = GetListLoginSchema()
<<<<<<< HEAD
=======
getListLoginsSchema = GetListLoginSchema(many=True)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class GetLoginSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = LoginModel
user = ma.auto_field()
......
......@@ -7,6 +7,7 @@ from marshmallow import Schema, fields, INCLUDE, EXCLUDE
class PackageModel(PrimaryModel):
__tablename__ = 'evm_package'
<<<<<<< HEAD
app = db.Column(db.Integer)
app_version = db.Column(db.String(200))
package_info = db.Column(db.String(20))
......@@ -17,6 +18,18 @@ class PackageModel(PrimaryModel):
ip = db.Column(db.String(128))
geo_location = db.Column(db.String(200))
operator = db.Column(db.String(50))
=======
app = db.Column(db.Integer, nullable = False)
app_version = db.Column(db.String(200), nullable = False)
package_info = db.Column(db.String(20), nullable = False)
file_path = db.Column(db.String(200), nullable = False)
source = db.Column(db.Integer, nullable = False)
user_agent = db.Column(db.String(200), nullable = False)
download_url = db.Column(db.String(200), nullable = False)
ip = db.Column(db.String(128), nullable = False)
geo_location = db.Column(db.String(200), nullable = False)
operator = db.Column(db.String(50), nullable = False)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
# __table_args__ = (
# db.Index('idx_xxx', 'xxx', mysql_using='btree'),
......@@ -54,7 +67,11 @@ class PackageModel(PrimaryModel):
class GetListPackageSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = PackageModel
page = fields.Integer(required=False)
......@@ -71,11 +88,19 @@ class GetListPackageSchema(ma.SQLAlchemySchema):
operator = ma.auto_field()
getListPackageSchema = GetListPackageSchema()
<<<<<<< HEAD
=======
getListPackagesSchema = GetListPackageSchema(many=True)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class GetPackageSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = PackageModel
app = ma.auto_field()
......
......@@ -7,6 +7,7 @@ from marshmallow import Schema, fields, INCLUDE, EXCLUDE
class UserModel(PrimaryModel):
__tablename__ = 'evm_user'
<<<<<<< HEAD
app_name = db.Column(db.String(70), index = True)
app_icon = db.Column(db.String(200))
app_version = db.Column(db.String(20))
......@@ -18,6 +19,19 @@ class UserModel(PrimaryModel):
app_screen_size = db.Column(db.Integer)
app_arch = db.Column(db.String(20))
app_review = db.Column(db.String(100))
=======
app_name = db.Column(db.String(70), index = True, nullable = False)
app_icon = db.Column(db.String(200), nullable = False)
app_version = db.Column(db.String(20), nullable = False)
category = db.Column(db.Integer, nullable = False)
category_2th = db.Column(db.Integer, nullable = False)
developer = db.Column(db.Integer, nullable = False)
download_url = db.Column(db.String(20), nullable = False)
app_file_size = db.Column(db.Integer, nullable = False)
app_screen_size = db.Column(db.Integer, nullable = False)
app_arch = db.Column(db.String(20), nullable = False)
app_review = db.Column(db.String(100), nullable = False)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
# __table_args__ = (
# db.Index('idx_xxx', 'xxx', mysql_using='btree'),
......@@ -58,7 +72,11 @@ class UserModel(PrimaryModel):
class PostUserSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = UserModel
app_name = ma.auto_field()
......@@ -72,12 +90,19 @@ class PostUserSchema(ma.SQLAlchemySchema):
app_review = ma.auto_field()
postUserSchema = PostUserSchema()
<<<<<<< HEAD
postUsersSchema = PostUserSchema(many=True)
=======
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class DeleteUserSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = UserModel
......@@ -86,7 +111,11 @@ deleteUserSchema = DeleteUserSchema()
class GetListUserSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = UserModel
page = fields.Integer(required=False)
......@@ -98,11 +127,19 @@ class GetListUserSchema(ma.SQLAlchemySchema):
app_arch = ma.auto_field()
getListUserSchema = GetListUserSchema()
<<<<<<< HEAD
=======
getListUsersSchema = GetListUserSchema(many=True)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class GetUserSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = UserModel
app_name = ma.auto_field()
......@@ -116,7 +153,11 @@ getUserSchema = GetUserSchema()
class PutUserSchema(ma.SQLAlchemySchema):
class Meta:
# unknown = INCLUDE # 未知字段默认包含
<<<<<<< HEAD
# unknown = EXCLUDE # 未知字段默认排除
=======
unknown = EXCLUDE # 未知字段默认排除
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
model = UserModel
app_name = ma.auto_field()
......
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
Base = declarative_base()
print(sqlalchemy.__version__)
# where <path> is relative:
engine = create_engine('sqlite:///test.db')
# Unix/Mac - 4 initial slashes in total
# engine = create_engine('sqlite:////absolute/path/to/foo.db')
# # Windows
# engine = create_engine('sqlite:///C:\\path\\to\\foo.db')
# # Windows alternative using raw string
# engine = create_engine(r'sqlite:///C:\path\to\foo.db')
# 定义映射类User,其继承上一步创建的Base
class User(Base):
# 指定本类映射到users表
__tablename__ = 'users'
# 如果有多个类指向同一张表,那么在后边的类需要把extend_existing设为True,表示在已有列基础上进行扩展
# 或者换句话说,sqlalchemy允许类是表的字集
# __table_args__ = {'extend_existing': True}
# 如果表在同一个数据库服务(datebase)的不同数据库中(schema),可使用schema参数进一步指定数据库
# __table_args__ = {'schema': 'test_database'}
# 各变量名一定要与表的各字段名一样,因为相同的名字是他们之间的唯一关联关系
# 从语法上说,各变量类型和表的类型可以不完全一致,如表字段是String(64),但我就定义成String(32)
# 但为了避免造成不必要的错误,变量的类型和其对应的表的字段的类型还是要相一致
# sqlalchemy强制要求必须要有主键字段不然会报错,如果要映射一张已存在且没有主键的表,那么可行的做法是将所有字段都设为primary_key=True
# 不要看随便将一个非主键字段设为primary_key,然后似乎就没报错就能使用了,sqlalchemy在接收到查询结果后还会自己根据主键进行一次去重
# 指定id映射到id字段; id字段为整型,为主键,自动增长(其实整型主键默认就自动增长)
id = Column(Integer, primary_key=True, autoincrement=True)
# 指定name映射到name字段; name字段为字符串类形,
name = Column(String(20))
fullname = Column(String(32))
password = Column(String(32))
# __repr__方法用于输出该类的对象被print()时输出的字符串,如果不想写可以不写
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
def get_dynamic_table_name_class(table_name):
# 定义一个内部类
class TestModel(Base):
# 给表名赋值
__tablename__ = table_name
__table_args__ = {'extend_existing': True}
username = Column(String(32), primary_key=True)
password = Column(String(32))
# 把动态设置表名的类返回去
return TestModel
# 查看映射对应的表
print(User.__table__)
# 创建数据表。一方面通过engine来连接数据库,另一方面根据哪些类继承了Base来决定创建哪些表
# checkfirst=True,表示创建表前先检查该表是否存在,如同名表已存在则不再创建。其实默认就是True
Base.metadata.create_all(engine, checkfirst=True)
# 上边的写法会在engine对应的数据库中创建所有继承Base的类对应的表,但很多时候很多只是用来则试的或是其他库的
# 此时可以通过tables参数指定方式,指示仅创建哪些表
# Base.metadata.create_all(engine,tables=[Base.metadata.tables['users']],checkfirst=True)
# 在项目中由于model经常在别的文件定义,没主动加载时上边的写法可能写导致报错,可使用下边这种更明确的写法
# User.__table__.create(engine, checkfirst=True)
# 另外我们说这一步的作用是创建表,当我们已经确定表已经在数据库中存在时,我完可以跳过这一步
# 针对已存放有关键数据的表,或大家共用的表,直接不写这创建代码更让人心里踏实
# engine是2.2中创建的连接
Session = sessionmaker(bind=engine)
# 创建Session类实例
session = Session()
if __name__ == "__main__":
# 创建User类实例
ed_user = User(name='ed', fullname='Ed Jones', password='edspassword')
# 将该实例插入到users表
session.add(ed_user)
# 一次插入多条记录形式
session.add_all(
[
User(name='wendy', fullname='Wendy Williams', password='foobar'),
User(name='mary', fullname='Mary Contrary', password='xxg527'),
User(name='fred', fullname='Fred Flinstone', password='blah')
]
)
# 当前更改只是在session中,需要使用commit确认更改才会写入数据库
session.commit()
our_user = session.query(User).filter_by(name='ed').first()
print(our_user)
\ No newline at end of file
......@@ -3,7 +3,12 @@ from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from flask_jwt_extended import ( jwt_required, get_jwt_identity )
from application.signal_manager import signalManager
<<<<<<< HEAD
from models.app import postAppSchema,deleteAppSchema,getListAppSchema,getAppSchema,putAppSchema
=======
from models.app import postAppSchema,deleteAppSchema,getListAppSchema,getListAppsSchema,getAppSchema,putAppSchema
from webcreator.log import logger
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from webcreator.response import ResponseCode, response_result
class AppResourceList(Resource):
......@@ -20,23 +25,48 @@ class AppResourceList(Resource):
try:
json_payload = request.json
<<<<<<< HEAD
print("========>", json_payload)
data = getListAppSchema.load(json_payload)
result = signalManager.actionGetApp.emit(**data)
json_dumps = getListAppSchema.dump(result)
return jsonify(json_dumps), 200
=======
logger.warn(json_payload)
data = getListAppSchema.load(json_payload)
result = signalManager.actionGetListApp.emit(data)
json_dumps = getListAppSchema.dump(result)
if result[0]:
json_dumps = getListAppsSchema.dump(result[1])
logger.warn(json_dumps)
return response_result(ResponseCode.OK, data=json_dumps, count=result[2])
return response_result(ResponseCode.REQUEST_ERROR)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def post(self):
try:
json_payload = request.json
data = postAppSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionPostApp.emit(**data)
json_dumps = postAppSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionPostApp.emit(data)
if result[0] == False:
# json_dumps = postAppSchema.dump(result)
return response_result(ResponseCode.REQUEST_ERROR, msg=result[1])
logger.warn(result)
return response_result(ResponseCode.OK)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -48,7 +78,11 @@ class AppResource(Resource):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser = RequestParser()
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def get(self, uuid):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser.add_argument("page", type=int, location="args", default=1)
......@@ -59,37 +93,69 @@ class AppResource(Resource):
json_payload = request.json
print("========>", uuid, json_payload)
data = getAppSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionGetApp.emit(**data)
json_dumps = getAppSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionGetApp.emit(uuid, data)
if result[0]:
json_dumps = getAppSchema.dump(result[1])
return response_result(ResponseCode.OK, data=json_dumps)
return response_result(ResponseCode.NO_DATA)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def put(self, uuid):
try:
json_payload = request.json
print("========>", uuid, json_payload)
data = putAppSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionPutApp.emit(**data)
json_dumps = putAppSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionPutApp.emit(uuid, data)
if result[0] == True:
# json_dumps = putAppSchema.dump(result)
return response_result(ResponseCode.OK)
return response_result(ResponseCode.NOTHING_CHANGE, msg=result[1])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def delete(self, uuid):
try:
json_payload = request.json
print("========>", uuid, json_payload)
<<<<<<< HEAD
data = deleteAppSchema.load(json_payload)
result = signalManager.actionDeleteApp.emit(**data)
json_dumps = deleteAppSchema.dump(result)
return jsonify(json_dumps), 200
=======
# data = deleteAppSchema.load(json_payload)
result = signalManager.actionDeleteApp.emit(uuid)
if result[0] == True:
return response_result(ResponseCode.OK)
return response_result(ResponseCode.REQUEST_ERROR, msg=result[1])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -3,7 +3,12 @@ from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from flask_jwt_extended import ( jwt_required, get_jwt_identity )
from application.signal_manager import signalManager
<<<<<<< HEAD
from models.area import postAreaSchema,deleteAreaSchema,getListAreaSchema,getAreaSchema,putAreaSchema
=======
from models.area import postAreaSchema,deleteAreaSchema,getListAreaSchema,getListAreasSchema,getAreaSchema,putAreaSchema
from webcreator.log import logger
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from webcreator.response import ResponseCode, response_result
class AreaResourceList(Resource):
......@@ -20,23 +25,48 @@ class AreaResourceList(Resource):
try:
json_payload = request.json
<<<<<<< HEAD
print("========>", json_payload)
data = getListAreaSchema.load(json_payload)
result = signalManager.actionGetArea.emit(**data)
json_dumps = getListAreaSchema.dump(result)
return jsonify(json_dumps), 200
=======
logger.warn(json_payload)
data = getListAreaSchema.load(json_payload)
result = signalManager.actionGetListArea.emit(data)
json_dumps = getListAreaSchema.dump(result)
if result[0]:
json_dumps = getListAreasSchema.dump(result[1])
logger.warn(json_dumps)
return response_result(ResponseCode.OK, data=json_dumps, count=result[2])
return response_result(ResponseCode.REQUEST_ERROR)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def post(self):
try:
json_payload = request.json
data = postAreaSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionPostArea.emit(**data)
json_dumps = postAreaSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionPostArea.emit(data)
if result[0] == False:
# json_dumps = postAreaSchema.dump(result)
return response_result(ResponseCode.REQUEST_ERROR, msg=result[1])
logger.warn(result)
return response_result(ResponseCode.OK)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -48,7 +78,11 @@ class AreaResource(Resource):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser = RequestParser()
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def get(self, uuid):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser.add_argument("page", type=int, location="args", default=1)
......@@ -59,37 +93,69 @@ class AreaResource(Resource):
json_payload = request.json
print("========>", uuid, json_payload)
data = getAreaSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionGetArea.emit(**data)
json_dumps = getAreaSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionGetArea.emit(uuid, data)
if result[0]:
json_dumps = getAreaSchema.dump(result[1])
return response_result(ResponseCode.OK, data=json_dumps)
return response_result(ResponseCode.NO_DATA)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def put(self, uuid):
try:
json_payload = request.json
print("========>", uuid, json_payload)
data = putAreaSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionPutArea.emit(**data)
json_dumps = putAreaSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionPutArea.emit(uuid, data)
if result[0] == True:
# json_dumps = putAreaSchema.dump(result)
return response_result(ResponseCode.OK)
return response_result(ResponseCode.NOTHING_CHANGE, msg=result[1])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def delete(self, uuid):
try:
json_payload = request.json
print("========>", uuid, json_payload)
<<<<<<< HEAD
data = deleteAreaSchema.load(json_payload)
result = signalManager.actionDeleteArea.emit(**data)
json_dumps = deleteAreaSchema.dump(result)
return jsonify(json_dumps), 200
=======
# data = deleteAreaSchema.load(json_payload)
result = signalManager.actionDeleteArea.emit(uuid)
if result[0] == True:
return response_result(ResponseCode.OK)
return response_result(ResponseCode.REQUEST_ERROR, msg=result[1])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -3,7 +3,12 @@ from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from flask_jwt_extended import ( jwt_required, get_jwt_identity )
from application.signal_manager import signalManager
<<<<<<< HEAD
from models.login import getListLoginSchema,getLoginSchema
=======
from models.login import postLoginSchema,getListLoginSchema,getListLoginsSchema,getLoginSchema
from webcreator.log import logger
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from webcreator.response import ResponseCode, response_result
class LoginResourceList(Resource):
......@@ -20,22 +25,56 @@ class LoginResourceList(Resource):
try:
json_payload = request.json
<<<<<<< HEAD
print("========>", json_payload)
data = getListLoginSchema.load(json_payload)
result = signalManager.actionGetLogin.emit(**data)
json_dumps = getListLoginSchema.dump(result)
return jsonify(json_dumps), 200
=======
logger.warn(json_payload)
data = getListLoginSchema.load(json_payload)
result = signalManager.actionGetListLogin.emit(data)
json_dumps = getListLoginSchema.dump(result)
if result[0]:
json_dumps = getListLoginsSchema.dump(result[1])
logger.warn(json_dumps)
return response_result(ResponseCode.OK, data=json_dumps, count=result[2])
return response_result(ResponseCode.REQUEST_ERROR)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
=======
def post(self):
try:
json_payload = request.json
data = postLoginSchema.load(json_payload)
result = signalManager.actionPostLogin.emit(data)
if result[0] == False:
# json_dumps = postLoginSchema.dump(result)
return response_result(ResponseCode.REQUEST_ERROR, msg=result[1])
logger.warn(result)
return response_result(ResponseCode.OK)
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
class LoginResource(Resource):
def __init__(self):
pass
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser = RequestParser()
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def get(self, uuid):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser.add_argument("page", type=int, location="args", default=1)
......@@ -46,9 +85,17 @@ class LoginResource(Resource):
json_payload = request.json
print("========>", uuid, json_payload)
data = getLoginSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionGetLogin.emit(**data)
json_dumps = getLoginSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionGetLogin.emit(uuid, data)
if result[0]:
json_dumps = getLoginSchema.dump(result[1])
return response_result(ResponseCode.OK, data=json_dumps)
return response_result(ResponseCode.NO_DATA)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -3,7 +3,12 @@ from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from flask_jwt_extended import ( jwt_required, get_jwt_identity )
from application.signal_manager import signalManager
<<<<<<< HEAD
from models.package import getListPackageSchema,getPackageSchema
=======
from models.package import getListPackageSchema,getListPackagesSchema,getPackageSchema
from webcreator.log import logger
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from webcreator.response import ResponseCode, response_result
class PackageResourceList(Resource):
......@@ -20,11 +25,23 @@ class PackageResourceList(Resource):
try:
json_payload = request.json
<<<<<<< HEAD
print("========>", json_payload)
data = getListPackageSchema.load(json_payload)
result = signalManager.actionGetPackage.emit(**data)
json_dumps = getListPackageSchema.dump(result)
return jsonify(json_dumps), 200
=======
logger.warn(json_payload)
data = getListPackageSchema.load(json_payload)
result = signalManager.actionGetListPackage.emit(data)
json_dumps = getListPackageSchema.dump(result)
if result[0]:
json_dumps = getListPackagesSchema.dump(result[1])
logger.warn(json_dumps)
return response_result(ResponseCode.OK, data=json_dumps, count=result[2])
return response_result(ResponseCode.REQUEST_ERROR)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -35,7 +52,11 @@ class PackageResource(Resource):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser = RequestParser()
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def get(self, uuid):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser.add_argument("page", type=int, location="args", default=1)
......@@ -46,9 +67,17 @@ class PackageResource(Resource):
json_payload = request.json
print("========>", uuid, json_payload)
data = getPackageSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionGetPackage.emit(**data)
json_dumps = getPackageSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionGetPackage.emit(uuid, data)
if result[0]:
json_dumps = getPackageSchema.dump(result[1])
return response_result(ResponseCode.OK, data=json_dumps)
return response_result(ResponseCode.NO_DATA)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -3,7 +3,12 @@ from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from flask_jwt_extended import ( jwt_required, get_jwt_identity )
from application.signal_manager import signalManager
<<<<<<< HEAD
from models.user import postUserSchema,deleteUserSchema,getListUserSchema,getUserSchema,putUserSchema
=======
from models.user import postUserSchema,deleteUserSchema,getListUserSchema,getListUsersSchema,getUserSchema,putUserSchema
from webcreator.log import logger
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
from webcreator.response import ResponseCode, response_result
class UserResourceList(Resource):
......@@ -20,23 +25,48 @@ class UserResourceList(Resource):
try:
json_payload = request.json
<<<<<<< HEAD
print("========>", json_payload)
data = getListUserSchema.load(json_payload)
result = signalManager.actionGetUser.emit(**data)
json_dumps = getListUserSchema.dump(result)
return jsonify(json_dumps), 200
=======
logger.warn(json_payload)
data = getListUserSchema.load(json_payload)
result = signalManager.actionGetListUser.emit(data)
json_dumps = getListUserSchema.dump(result)
if result[0]:
json_dumps = getListUsersSchema.dump(result[1])
logger.warn(json_dumps)
return response_result(ResponseCode.OK, data=json_dumps, count=result[2])
return response_result(ResponseCode.REQUEST_ERROR)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def post(self):
try:
json_payload = request.json
data = postUserSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionPostUser.emit(**data)
json_dumps = postUserSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionPostUser.emit(data)
if result[0] == False:
# json_dumps = postUserSchema.dump(result)
return response_result(ResponseCode.REQUEST_ERROR, msg=result[1])
logger.warn(result)
return response_result(ResponseCode.OK)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
......@@ -48,7 +78,11 @@ class UserResource(Resource):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser = RequestParser()
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def get(self, uuid):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser.add_argument("page", type=int, location="args", default=1)
......@@ -59,37 +93,69 @@ class UserResource(Resource):
json_payload = request.json
print("========>", uuid, json_payload)
data = getUserSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionGetUser.emit(**data)
json_dumps = getUserSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionGetUser.emit(uuid, data)
if result[0]:
json_dumps = getUserSchema.dump(result[1])
return response_result(ResponseCode.OK, data=json_dumps)
return response_result(ResponseCode.NO_DATA)
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def put(self, uuid):
try:
json_payload = request.json
print("========>", uuid, json_payload)
data = putUserSchema.load(json_payload)
<<<<<<< HEAD
result = signalManager.actionPutUser.emit(**data)
json_dumps = putUserSchema.dump(result)
return jsonify(json_dumps), 200
=======
result = signalManager.actionPutUser.emit(uuid, data)
if result[0] == True:
# json_dumps = putUserSchema.dump(result)
return response_result(ResponseCode.OK)
return response_result(ResponseCode.NOTHING_CHANGE, msg=result[1])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
<<<<<<< HEAD
@jwt_required
=======
@jwt_required(locations=["headers"])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
def delete(self, uuid):
try:
json_payload = request.json
print("========>", uuid, json_payload)
<<<<<<< HEAD
data = deleteUserSchema.load(json_payload)
result = signalManager.actionDeleteUser.emit(**data)
json_dumps = deleteUserSchema.dump(result)
return jsonify(json_dumps), 200
=======
# data = deleteUserSchema.load(json_payload)
result = signalManager.actionDeleteUser.emit(uuid)
if result[0] == True:
return response_result(ResponseCode.OK)
return response_result(ResponseCode.REQUEST_ERROR, msg=result[1])
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
except Exception as e:
current_app.logger.error(e)
return response_result(ResponseCode.DB_ERROR)
# -*- coding: utf_8 -*-
############################
# Signals-Slots
# 信号槽
############################
......@@ -43,6 +42,7 @@ class PySignal(object):
def emit(self, *args, **kwargs):
rets = {}
for handler in self._handlers:
ret = handler(*args, **kwargs)
rets[handler.__name__] = ret
......
......@@ -16,12 +16,19 @@ if not os.path.exists(logPath):
fh = RotatingFileHandler("logs/running.log", maxBytes=10 * 1024 * 1024, backupCount=100)
fh.setLevel(logging.DEBUG)
<<<<<<< HEAD
# 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')
=======
ch = logging.StreamHandler()
ch.setLevel(logging.WARNING)
formatter = logging.Formatter('[%(asctime)s][%(levelname)7s][in %(pathname)s -> %(funcName)s line:%(lineno)s] %(message)s')
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
fh.setFormatter(formatter)
ch.setFormatter(formatter)
......
......@@ -3,9 +3,20 @@
"name": "evm-store",
"host": "127.0.0.1",
"port": 1000,
<<<<<<< HEAD
"jwtSecret": "",
"tablePrefix": "evm_",
"logLevel": "debug",
=======
"project": {
"inputDirectory": "",
"outputDirectory": ""
},
"jwtSecret": "6UdxRgs2hvWpTLmj027d5vt7dXXQX",
"tablePrefix": "evm_",
"logLevel": "DEBUG",
"database": "sqlite",
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"mysql": {
"host": "127.0.0.1",
"port": 3306,
......@@ -18,6 +29,7 @@
}
},
"modules": [
<<<<<<< HEAD
{
"file": "modules/user.json",
"enable": false
......@@ -27,6 +39,17 @@
"enable": false
},
{
=======
{
"file": "modules/user.json",
"enable": false
},
{
"file": "modules/permission.json",
"enable": false
},
{
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"file": "modules/menu.json",
"enable": false
}
......@@ -89,7 +112,11 @@
"default": "",
"length": 20,
"index": false,
<<<<<<< HEAD
"required": true,
=======
"required": false,
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"toJson": true
},
{
......@@ -128,6 +155,23 @@
"required": false
},
{
<<<<<<< HEAD
=======
"name": "parentId",
"dataType": "String",
"location": "args",
"default": "",
"required": false
},
{
"name": "hasChildren",
"dataType": "Boolean",
"location": "args",
"default": false,
"required": false
},
{
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"name": "cityCode",
"detaType": "String",
"location": "",
......@@ -142,6 +186,71 @@
"required": false
}
]
<<<<<<< HEAD
},
"delete": {
"auth": true,
"path": "/<string:uuid>",
"endpoint": "",
"params": []
},
"getList": {
"auth": false,
"path": "",
"endpoint": "",
"params": [
{
"name": "page",
"dataType": "Integer",
"location": "args",
"default": 1,
"required": false
},
{
"name": "pageSize",
"dataType": "Integer",
"location": "args",
"default": 10,
"required": false
},
{
"name": "areaName",
"dataType": "String",
"location": "args",
"default": null,
"required": false
},
{
"name": "level",
"dataType": "Integer",
"location": "args",
"default": 1,
"required": false
},
{
"name": "parentId",
"dataType": "String",
"location": "args",
"default": "",
"required": false
},
{
"name": "hasChildren",
"dataType": "Boolean",
"location": "args",
"default": false,
"required": false
},
{
"name": "field",
"dataType": "String",
"location": "args",
"default": "",
"required": false
}
]
},
=======
},
"delete": {
"auth": true,
......@@ -205,6 +314,7 @@
}
]
},
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"get": {
"auth": true,
"path": "/<string:uuid>",
......@@ -257,6 +367,10 @@
"dataType": "String",
"location": "args",
"default": "",
<<<<<<< HEAD
=======
"priority": true,
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"required": false
},
{
......@@ -264,6 +378,10 @@
"dataType": "Integer",
"location": "args",
"default": 0,
<<<<<<< HEAD
=======
"priority": true,
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"required": false
},
{
......@@ -271,6 +389,10 @@
"dataType": "String",
"location": "args",
"default": null,
<<<<<<< HEAD
=======
"priority": true,
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"required": false
},
{
......@@ -278,6 +400,10 @@
"dataType": "Boolean",
"location": "args",
"default": false,
<<<<<<< HEAD
=======
"priority": true,
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"required": false
},
{
......@@ -285,6 +411,10 @@
"dataType": "String",
"location": "args",
"default": null,
<<<<<<< HEAD
=======
"priority": true,
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
"required": false
}
]
......@@ -997,7 +1127,26 @@
"path": "",
"endpoint": "",
"params": [
<<<<<<< HEAD
=======
{
"name": "account",
"dataType": "String",
"location": "args",
"length": 64,
"default": null,
"required": true
},
{
"name": "password",
"dataType": "String",
"location": "args",
"length": 64,
"default": null,
"required": true
}
>>>>>>> 735d39eb4d0c3134b62bf4fe1b7a2ca0ea8da1ca
]
},
"getList": {
......
// set baseUrl
MIX_LFM_BASE_URL=http://my-url.loc/file-manager/
// if you don't want to use csrf-token - you can off it
MIX_LFM_CSRF_TOKEN=OFF
\ No newline at end of file
.DS_Store
node_modules
/dist
# 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*
MIT License
Copyright (c) 2019 ruyangit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# 工作中台基础UI
#### 项目介绍
[SeedWorkbenchUi](https://github.com/ruyangit/seed-workbench-ui) 简洁的中台UI,vuejs 开发,组件化,模块化 See: <a href="https://ruyangit.gitee.io/seed-workbench-ui">demo</a>
<p align="center">
<!-- <a><img src="https://img.shields.io/github/release/ruyangit/seed-workbench-ui.svg"/></a>
<a><img src="https://badge.fury.io/js/%40seed-workbench-ui%2Fice-scaffold.svg"/></a> -->
<a><img src="https://img.shields.io/github/last-commit/ruyangit/seed-workbench-ui.svg"/></a>
<a><img src="https://img.shields.io/badge/code_style-standard-brightgreen.svg"/></a>
<a><img src="https://img.shields.io/github/forks/ruyangit/seed-workbench-ui.svg"/></a>
<a><img src="https://img.shields.io/github/stars/ruyangit/seed-workbench-ui.svg"/></a>
</p>
#### 先来波图
![banner](https://ruyangit.gitee.io/bgcdn/analysis.jpg)
![banner](https://ruyangit.gitee.io/bgcdn/workplace.jpg)
![banner](https://ruyangit.gitee.io/bgcdn/list.jpg)
![banner](https://ruyangit.gitee.io/bgcdn/setting.jpg)
![banner](https://ruyangit.gitee.io/bgcdn/phone_login.jpg)
![banner](https://ruyangit.gitee.io/bgcdn/register.jpg)
#### 预览
[预览地址](https://ruyangit.gitee.io/seed-workbench-ui)
> 预览部署在 Github Page ,如果您访问时由于网络原因卡在载入界面或者白屏,请克隆或者下载本仓库在本地运行查看效果。
#### 软件架构
* [vue/cli3](https://cli.vuejs.org)
* vue 2.5.17
* vue-router 3.0.1
* vuex 3.0.1
* vuex-router-sync 5.0.5
* vue-i18n 8.1.0
* numeral 2.0.6
* axios 0.18.0
* [ant-design-vue 1.1.2 组件库](https://vuecomponent.github.io/ant-design-vue)
* [antv/g2 3.2.7 图表库](http://g2.alipay.com/)
#### 安装教程
```
npm install
```
### 运行包含热加载的开发环境
```
npm run serve
```
### 打包压缩后的生产文件
```
npm run build
```
### 本地如何运行打包后的生产文件
```
npm install serve -g 安装serve服务 -g 安装到全局
serve -s dist 运行打包后的生产文件 dist 打包后的文件夹
```
### Lints and fixes files
```
npm run lint
```
#### 使用说明
1. 运行文件配置 [vue.config.js](https://github.com/ruyangit/seed-workbench-ui/blob/dev/vue.config.js)
```
// 基础路径 注意发布之前要先修改这里
const baseUrl = '/'
if (process.env.NODE_ENV === 'production') {
baseUrl = '/frontend/'
}
// 主题样式全局修改替换
css: {
loaderOptions: {
less: {
modifyVars: {
'ai-prefix': 'ai',
'primary-color': '#42b983'
},
paths: [
resolve('node_modules'),
resolve('src')
],
javascriptEnabled: true
}
}
}
// 过滤掉moment其它国家,只保留中文和英文
configureWebpack: {
plugins: [
new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(zh-cn|en-us)$/),
]
}
// 配置本地svg优化方案 ,重新设置src别名@
chainWebpack: config => {
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.include
.add(resolve('src/assets/svg-icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'ai-[name]'
})
.end()
// image exclude
const imagesRule = config.module.rule('images')
imagesRule
.test(/\.(png|jpe?g|gif|webp|svg)(\?.*)?$/)
.exclude
.add(resolve('src/assets/svg-icons'))
.end()
// 重新设置 alias
config.resolve.alias.set('@', resolve('src'))
}
```
2. 编译文件配置 [babel.config.js](https://github.com/ruyangit/seed-workbench-ui/blob/dev/babel.config.js)
```
// 设置ant-design-vue 按需加载方案
"plugins": [
["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": true }]
]
```
3. 组件及页面API说明待后续时间充裕补充上来。
#### 计划
* 后续完善UI中所需的组件
* 对接完成自己开发的后台系统
[SpringbootSeed](https://gitee.com/ruyangit/springboot-seed)
* 关于阿里的g2 或者百度的 echarts 对于我来说感觉有点大,之后看看图表相关的简化一下
* 代码的规范及API文档的编写
* 代码的CI,CD测试
#### 参与贡献
1. Fork 本项目
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 人家都喝咖啡,我就喝瓶水就行,谢谢支持!
\ No newline at end of file
module.exports = {
"presets": [ [ "@vue/app", { useBuiltIns: "entry" } ] ],
"plugins": [
["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": true }]
]
}
This diff is collapsed.
{
"name": "evm-workbench-admin",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@antv/g2": "^3.2.7",
"ant-design-vue": "^1.7.5",
"axios": "^0.18.0",
"bootstrap": "4.6.0",
"codemirror": "^5.59.2",
"core-js": "^3.9.0",
"cropperjs": "^1.5.11",
"npm-check-updates": "^11.7.1",
"numeral": "^2.0.6",
"plyr": "^3.6.4",
"vue": "^2.5.17",
"vue-codemirror": "^4.0.6",
"vue-i18n": "^8.1.0",
"vue-router": "^3.0.1",
"vuex": "^3.0.1",
"vuex-router-sync": "^5.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.0.3",
"@vue/cli-plugin-eslint": "^3.0.3",
"@vue/cli-service": "^3.0.3",
"babel-plugin-import": "^1.9.1",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"node-sass": "^4.14.1",
"sass-loader": "^8.0.2",
"svg-sprite-loader": "^3.9.2",
"vue-template-compiler": "^2.6.12"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>EVM 应用商店</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.2/css/all.css">
<style>
html,
body {
background-color: transparent;
margin: 0;
height: 100%;
}
.box {
height: 80px;
width: 80px;
position: relative;
top: calc(50% - 80px);
left: calc(50% - 50px);
perspective: 1000px;
}
.thing {
height: 40px;
width: 40px;
background-color: #E87722;
position: absolute;
box-sizing: border-box;
top: 0;
left: 0;
}
.thing:nth-of-type(1) {
animation: bounce 0.5s ease-in-out infinite alternate, move 4s -1s infinite;
}
.thing:nth-of-type(2) {
animation: bounce 0.5s ease-in-out infinite alternate, move 4s -2s infinite;
}
.thing:nth-of-type(3) {
animation: bounce 0.5s ease-in-out infinite alternate, move 4s -3s infinite;
}
.thing:nth-of-type(4) {
animation: bounce 0.5s ease-in-out infinite alternate, move 4s -4s infinite;
}
@keyframes bounce {
from {
transform: scale(1);
}
to {
transform: scale(0.8);
}
}
@keyframes move {
0% {
top: 0;
left: 0;
background-color: #E87722;
}
25% {
top: 0;
left: 50%;
background-color: #42b983;
}
50% {
top: 50%;
left: 50%;
background-color: #69B3E7;
}
75% {
top: 50%;
left: 0;
background-color: #FFC845;
}
}
</style>
</head>
<body>
<noscript>
<strong>We're sorry but frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app" class="box">
<div class="thing"></div>
<div class="thing"></div>
<div class="thing"></div>
<div class="thing"></div>
</div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<ConfigProvider :locale="locale">
<div class="root"><router-view /></div>
</ConfigProvider>
</template>
<script>
import { LocaleProvider, ConfigProvider } from "ant-design-vue";
export default {
components: {
LocaleProvider,
ConfigProvider,
},
computed: {
locale() {
return this.$i18n.messages[this.$i18n.locale];
},
},
};
</script>
\ No newline at end of file
import request from '@/utils/request'
export function menuNav() {
return request({
url: 'https://randomuser.me/api',
method: 'get'
})
}
import request from '@/utils/request'
export function users(params) {
return request({
url: 'https://randomuser.me/api',
method: 'get',
params
})
}
<svg width="642" height="642" xmlns="http://www.w3.org/2000/svg" class="icon">
<defs>
<style type="text/css"/>
</defs>
<g>
<title>background</title>
<rect x="-1" y="-1" width="644" height="644" id="canvas_background" fill="none"/>
</g>
<g>
<title>Layer 1</title>
<path d="m546.6176,641.32967l-451.23517,0c-52.32527,0 -95.08571,-42.76044 -95.08571,-95.08571l0,-451.23517c0,-52.32527 42.76044,-95.08571 95.08571,-95.08571l451.23517,0c52.32527,0 95.08571,42.76044 95.08571,95.08571l0,451.23517c0,52.32527 -42.76044,95.08571 -95.08571,95.08571z" fill="#2ecccd" id="svg_1"/>
<path d="m321.46431,263.67473c-131.65714,0 -238.55824,-87.2088 -243.05934,-195.79781c0,-3.93846 -3.37582,-7.31428 -7.31429,-7.31428c-3.93846,0 -7.87692,3.37582 -7.31428,7.87692c5.06373,115.34066 118.71648,208.17582 258.25055,208.17583s253.18681,-92.27253 258.25055,-208.17583c0,-3.93846 -3.37583,-7.87692 -7.31429,-7.87692c-3.93846,0 -7.31428,3.37582 -7.31428,7.31428c-5.62638,108.58901 -112.52748,195.79781 -244.18462,195.79781z" fill="#FCFCFC" id="svg_2"/>
<path d="m322,324.43956m-14.06593,0a14.06593,14.06593 0 1 0 28.13186,0a14.06593,14.06593 0 1 0 -28.13186,0z" fill="#FCFCFC" id="svg_3"/>
<text fill="#ffffff" stroke-width="0" x="183.3125" y="488.8" id="svg_4" font-size="128" font-family="Helvetica, Arial, sans-serif" text-anchor="start" xml:space="preserve">EVM</text>
</g>
</svg>
\ No newline at end of file
<template>
<a-card :loading="loading" :bodyStyle="{padding: '20px 24px 8px 24px'}">
<div class="chartCard" >
<div :class="classNames('chartTop',{['chartTopMargin']:!$slots.default && !$slots.footer})">
<div class="avatar">{{avatar}}</div>
<div class="metaWrap">
<div class="meta">
<span class="title">{{title}}</span>
<span class="action">
<slot name="action"></slot>
</span>
</div>
<div class="total" v-if="total">{{total}}</div>
</div>
</div>
<div class="content" ref="cardRef" :style="{height: contentHeight || 'auto'}" v-if="$slots.default">
<div class="contentFixed">
<slot></slot>
</div>
</div>
<div v-if="$slots.footer" :class="classNames('footer',{['footerMargin']:!$slots.default})">
<slot name="footer"></slot>
</div>
</div>
</a-card>
</template>
<script>
import { Card } from "ant-design-vue";
import classNames from "classnames";
export default {
props: {
loading: { default: false, type: Boolean },
avatar: { type: String },
title: { type: String },
action: { type: String },
total: { type: String },
contentHeight: { type: String }
},
components: {
ACard: Card
},
methods: {
classNames
}
};
</script>
<style lang="less">
@import url("./index.less");
</style>
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.chartCard {
position: relative;
.chartTop {
position: relative;
overflow: hidden;
width: 100%;
}
.chartTopMargin {
margin-bottom: 12px;
}
.chartTopHasMargin {
margin-bottom: 20px;
}
.metaWrap {
float: left;
}
.avatar {
position: relative;
top: 4px;
float: left;
margin-right: 20px;
img {
border-radius: 100%;
}
}
.meta {
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
height: 22px;
}
.action {
cursor: pointer;
position: absolute;
top: 0;
right: 0;
}
.total {
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
color: @heading-color;
margin-top: 4px;
margin-bottom: 0;
font-size: 30px;
line-height: 38px;
height: 38px;
}
.content {
margin-bottom: 12px;
position: relative;
width: 100%;
}
.contentFixed {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
}
.footer {
border-top: 1px solid @border-color-split;
padding-top: 9px;
margin-top: 8px;
& > * {
position: relative;
}
}
.footerMargin {
margin-top: 20px;
}
}
<template>
<div class="field">
<span>{{label}}</span>
<span>{{value}}</span>
</div>
</template>
<script>
export default {
props: ["label", "value"]
};
</script>
<style lang="less">
@import url("./index.less");
</style>
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.field {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0;
span {
font-size: @font-size-base;
line-height: 22px;
}
span:last-child {
margin-left: 8px;
color: @heading-color;
}
}
<template>
<div class='miniChart'>
<div class='chartContent' >
<div :id="container" style="width:100%"></div>
</div>
</div>
</template>
<script>
import PropTypes from "ant-design-vue/es/_util/vue-types";
import moment from "moment";
import { initDefaultProps } from "ant-design-vue/es/_util/props-util";
const G2 = require("@antv/g2/lib/core");
require("@antv/g2/lib/geom/area");
const MniBarProps = {
container: PropTypes.string,
height: PropTypes.number,
forceFit: PropTypes.bool,
color: PropTypes.string,
data: PropTypes.array
};
const beginDay = new Date().getTime();
const visitData = [];
const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
for (let i = 0; i < fakeY.length; i += 1) {
visitData.push({
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format(
"YYYY-MM-DD"
),
y: fakeY[i]
});
}
export default {
data: () => ({
chart: Object
}),
props: initDefaultProps(MniBarProps, {
forceFit: true,
color: "#1890FF",
height: 46,
container: 'container_'+new Date().getTime(),
}),
methods: {
createChart() {
const scale = {
x: {
type: "cat"
},
y: {
min: 0
}
};
const padding = [36, 5, 30, 5];
const chartHeight = this.height + 54;
this.chart = new G2.Chart({
container: this.container,
forceFit: this.forceFit,
height: chartHeight,
padding: padding
});
this.chart.source(visitData);
this.chart.scale(scale);
this.chart.axis(false);
this.chart.tooltip(true, { showTitle: false, crosshairs: false });
this.chart
.area()
.position("x*y")
.color(this.color)
.tooltip("x*y", (x, y) => ({
name: x,
value: y
})).shape('smooth').style({fillOpacity: 1})
this.chart.render();
}
},
mounted() {
console.log(this);
this.createChart();
},
updated(){
if(!this.chart){
this.createChart();
}
}
};
</script>
\ No newline at end of file
<template>
<div class='miniChart' :style="{style: height+'px'}">
<div class='chartContent' >
<div style="width:100%" :id="container" ></div>
</div>
</div>
</template>
<script>
import PropTypes from "ant-design-vue/es/_util/vue-types";
import moment from "moment";
import { initDefaultProps } from "ant-design-vue/es/_util/props-util";
const G2 = require("@antv/g2/lib/core");
require("@antv/g2/lib/geom/interval");
const MniBarProps = {
container: PropTypes.string,
height: PropTypes.number,
forceFit: PropTypes.bool,
color: PropTypes.string,
data: PropTypes.array
};
const beginDay = new Date().getTime();
const visitData = [];
const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
for (let i = 0; i < fakeY.length; i += 1) {
visitData.push({
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format(
"YYYY-MM-DD"
),
y: fakeY[i]
});
}
export default {
data: () => ({
chart: Object
}),
props: initDefaultProps(MniBarProps, {
forceFit: true,
color: "#1890FF",
height: 46,
container: 'container_'+new Date().getTime(),
}),
methods: {
createChart() {
const scale = {
x: {
type: "cat"
},
y: {
min: 0
}
};
const padding = [36, 5, 30, 5];
const chartHeight = this.height + 54;
this.chart = new G2.Chart({
container: this.container,
forceFit: this.forceFit,
height: chartHeight,
padding: padding
});
this.chart.source(visitData);
this.chart.scale(scale);
this.chart.axis(false);
this.chart.tooltip(true, { showTitle: false, crosshairs: false });
this.chart
.interval()
.position("x*y")
.color(this.color)
.tooltip("x*y", (x, y) => ({
name: x,
value: y
}));
this.chart.render();
}
},
mounted() {
this.createChart();
// 注:window.onresize只能在项目内触发1次
},
computed:{
},
updated(){
console.log(1);
if(!this.chart){
this.createChart();
}
}
};
</script>
\ No newline at end of file
import './index.less'
import { Tooltip } from "ant-design-vue";
export default {
props: {
target: { type: Number },
color: {
default: 'rgb(19, 194, 194)'
},
strokeWidth: { type: Number },
percent: { type: Number },
},
components: {
ATooltip: Tooltip
},
render() {
const { target, color, percent, strokeWidth } = this
return (
<div class="miniProgress">
<a-tooltip title={`目标值 ${target}%`}>
<div class='target' style={{ left: target + 'px' ? `${target}%` : null }}>
<span style={{ backgroundColor: color || null }} />
<span style={{ backgroundColor: color || null }} />
</div>
</a-tooltip>
<div class='progressWrap'>
<div
class='progress'
style={{
backgroundColor: color || null,
width: percent ? `${percent}%` : null,
height: strokeWidth + 'px' || null,
}}
/>
</div>
</div>
)
}
}
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.miniProgress {
padding: 5px 0;
position: relative;
width: 100%;
.progressWrap {
background-color: @background-color-base;
position: relative;
}
.progress {
transition: all 0.4s cubic-bezier(0.08, 0.82, 0.17, 1) 0s;
border-radius: 1px 0 0 1px;
background-color: @primary-color;
width: 0;
height: 100%;
}
.target {
position: absolute;
top: 0;
bottom: 0;
span {
border-radius: 100px;
position: absolute;
top: 0;
left: 0;
height: 4px;
width: 2px;
}
span:last-child {
top: auto;
bottom: 0;
}
}
}
import './index.less'
import numeral from 'numeral';
import ChartCard from './ChartCard/ChartCard';
import Field from './Field/Field';
import MiniProgress from './MiniProgress';
// import MiniBar from './MiniBar/MiniBar';
// import MiniArea from './MiniArea/MiniArea';
const yuan = val => ${numeral(val).format('0,0')}`;
export {
yuan,
ChartCard,
Field,
MiniProgress,
// MiniBar,
// MiniArea
};
\ No newline at end of file
.miniChart {
position: relative;
width: 100%;
.chartContent {
position: absolute;
bottom: -30px;
width: 100%;
> div {
margin: 0 -5px;
overflow: hidden;
}
}
.chartLoading {
position: absolute;
top: 16px;
left: 50%;
margin-left: -7px;
}
}
\ No newline at end of file
<template>
<div class="descItem">
<p>
{{title}}
</p>
<template v-if="content">{{content}}</template>
<slot name="content" v-else></slot>
</div>
</template>
<script>
export default {
props: {
title: String,
content: String|Number|null
}
};
</script>
<style lang="less">
.descItem {
font-size: 14px;
line-height: 24px;
margin-bottom: 7px;
color: rgba(0, 0, 0, 0.65);
p {
margin-right: 8px;
display: inline-block;
color: rgba(0, 0, 0, 0.85);
}
}
</style>
\ No newline at end of file
import './index.less'
import classNames from 'classnames';
const GlobalFooter = {
props: ["className", "links", "copyright"],
render(){
const {className,links,copyright} = this;
const cls = classNames('globalFooter', className);
return (
<div class={cls}>
{links && (
<div class="links">
{links.map(link => (
<a
key={link.key}
title={link.key}
target={link.blankTarget ? '_blank' : '_self'}
href={link.href}
>
{link.title}
</a>
))}
</div>
)}
{copyright && <div class="copyright">{copyright}</div>}
</div>
)
}
}
export default GlobalFooter
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.globalFooter {
padding: 0 16px;
margin: 48px 0 24px 0;
text-align: center;
.links {
margin-bottom: 8px;
a {
color: @text-color-secondary;
transition: all 0.3s;
&:not(:last-child) {
margin-right: 40px;
}
&:hover {
color: @text-color;
}
}
}
.copyright {
color: @text-color-secondary;
font-size: @font-size-base;
}
}
<template>
<div :class="className">
<a-tooltip title="使用文档" placement="bottom">
<a target="_blank" href="javascript:;" class="action" @click="success">
<a-icon type="question-circle-o" />
</a>
</a-tooltip>
<a-dropdown placement="bottomRight">
<span class="action">
<a-icon type="codepen" theme="outlined" />
</span>
<a-menu slot="overlay" @click="handleMenuClick">
<a-menu-item key="gitee">
<a target="_blank" href="https://gitee.com/scriptiot/evm">
<a-icon type="slack-square" theme="outlined" />
Gitee
</a>
</a-menu-item>
<a-menu-item key="github">
<a target="_blank" href="https://github.com/scriptiot/evm">
<a-icon type="github" />
Github
</a>
</a-menu-item>
</a-menu>
</a-dropdown>
<a-notice-icon
class="ai-notice"
className="action"
:count="8"
:loading="false"
>
<a-notice-icon-tab
:list="[
{
id: '000000001',
avatar:
'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
title: '你收到了 14 份新周报',
datetime: '2017-08-09',
},
{
id: '000000002',
avatar:
'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png',
title: '你推荐的 曲妮妮 已通过第三轮面试',
datetime: '2017-08-08',
read: true,
},
]"
title="通知"
emptyText="你已查看所有通知"
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
/>
<a-notice-icon-tab
:list="[]"
title="消息"
emptyText="您已读完所有消息"
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
/>
<a-notice-icon-tab
:list="[
{
id: '000000009',
title: '任务名称',
description: '任务需要在 2017-01-12 20:00 前启动',
extra: '未开始',
status: 'todo',
},
{
id: '000000010',
title: '第三方紧急代码变更',
description:
'冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
extra: '马上到期',
read: true,
status: 'urgent',
},
{
id: '000000011',
title: '信息安全考试',
description: '指派竹尔于 2017-01-09 前完成更新并发布',
extra: '已耗时 8 天',
status: 'doing',
},
{
id: '000000012',
title: 'ABCD 版本发布',
description:
'冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
extra: '进行中',
status: 'processing',
},
]"
title="待办"
emptyText="你已完成所有待办"
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/HsIsxMZiWKrNUavQUXqx.svg"
/>
</a-notice-icon>
<a-tooltip :title="$t('navbar.lang')" placement="bottom">
<a href="javascript:;" class="action" @click="changeLang">
<a-icon type="api" />
</a>
</a-tooltip>
<a-dropdown>
<span class="action account">
<a-avatar
size="small"
class="avatar"
src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png"
alt="avatar"
/>
<span class="name">EVM</span>
</span>
<a-menu slot="overlay" class="menu">
<a-menu-item key="userCenter">
<a-icon type="user" />
{{ $t("menu.account.center") }}
</a-menu-item>
<a-menu-item key="userinfo">
<a-icon type="setting" />
{{ $t("menu.account.settings") }}
</a-menu-item>
<a-menu-item key="triggerError">
<a-icon type="close-circle-o" />
{{ $t("menu.account.trigger") }}
</a-menu-item>
<a-menu-divider />
<a-menu-item key="logout" @click="logout">
<a-icon type="logout" />
退出登录
</a-menu-item>
</a-menu>
</a-dropdown>
<a-tooltip title="预览设置" placement="bottom">
<a
@click="
() => {
this.collapse = !this.collapse;
}
"
href="javascript:;"
class="action"
:style="{ marginRight: '12px' }"
>
<a-icon type="ellipsis" />
</a>
</a-tooltip>
<a-setting-drawer :collapse="collapse" />
</div>
</template>
<script>
import {
Tooltip,
Icon,
Dropdown,
Menu,
Avatar,
Modal,
Divider,
} from "ant-design-vue";
import NoticeIcon from "@/components/NoticeIcon";
import SettingDrawer from "@/components/SettingDrawer";
export default {
data: () => ({
collapse: false,
}),
components: {
ATooltip: Tooltip,
AIcon: Icon,
ADropdown: Dropdown,
AMenu: Menu,
AMenuItem: Menu.Item,
AMenuDivider: Menu.Divider,
AAvatar: Avatar,
ANoticeIcon: NoticeIcon,
ANoticeIconTab: NoticeIcon.Tab,
ADivider: Divider,
ASettingDrawer: SettingDrawer,
},
props: ["theme", "layout"],
methods: {
changeLang() {
this.$i18n.locale = this.$i18n.locale === "en_US" ? "zh_CN" : "en_US";
},
handleMenuClick(e) {
if (e.key === "gitee") {
window.open(
"https://gitee.com/scriptiot/evm",
"_blank"
);
} else {
window.open(
"https://gitee.com/scriptiot/evm",
"_blank"
);
}
},
logout() {
this.$router.push({ path: "/user/login" });
},
success() {
Modal.success({
title: "友好的一个提示",
// JSX support
content: (
<div>
<p>使用文档,组件API,等说明。正在加班整理中...</p>
<p>您可以先 Star 一个,追踪后面的更新。</p>
<p>欢迎 Pr</p>
</div>
),
});
},
},
computed: {
className() {
let className = "ai-header-right";
if (this.theme === "dark" && this.layout === "topmenu") {
className = `ai-header-right dark`;
}
return className;
},
},
};
</script>
import './index.less'
import RightContent from './RightContent'
import { Icon, Spin } from "ant-design-vue";
import { mapGetters } from "vuex";
const GlobalHeader = {
props:['theme','layout'],
computed: {
...mapGetters({
spinning: "global/getBasicLayoutSpinning",
collapsed: "global/getChangeLayoutCollapsed"
}),
},
methods: {
onCollapsed() {
this.$store.commit('global/UpdateChangeLayoutCollapsed', !this.collapsed)
},
},
render() {
const { spinning, collapsed, onCollapsed, theme,layout } = this
return (
<div class="header-index">
<Icon
class="trigger"
type={collapsed ? 'menu-unfold' : 'menu-fold'}
onClick={onCollapsed}
/>
<Spin spinning={spinning}></Spin>
<RightContent theme={theme} layout={layout}/>
</div>
)
}
}
export default GlobalHeader
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.trigger{
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color .3s;
&:hover{
color: @primary-color;
}
}
.header-index{
height: 64px;
padding: 0 12px 0 0;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
position: relative;
}
@ai-header-prefix: ~"@{ai-prefix}-header";
.@{ai-header-prefix}-right {
float: right;
height: 100%;
.action {
cursor: pointer;
padding: 0 12px;
display: inline-block;
transition: all 0.3s;
height: 100%;
> i {
font-size: 18px;
vertical-align: middle;
color: @text-color;
}
&:hover {
background: @primary-1;
}
:global(&.ant-popover-open) {
background: @primary-1;
}
}
.search {
padding: 0 12px;
&:hover {
background: transparent;
}
}
.account {
.avatar {
margin: 20px 8px 20px 0;
color: @primary-color;
background: rgba(255, 255, 255, 0.85);
vertical-align: middle;
}
.name{
margin-top: 5px;
}
}
&.dark {
.action {
color: rgba(255, 255, 255, 0.85);
> i {
color: rgba(255, 255, 255, 0.85);
}
&:hover,
&:global(.ant-popover-open) {
background: transparent;
}
:global(.ant-badge) {
color: rgba(255, 255, 255, 0.85);
}
}
}
}
.menu {
:global(.anticon) {
margin-right: 8px;
}
:global(.ant-dropdown-menu-item) {
width: 160px;
}
}
import './NoticeList.less'
import { List, Avatar } from "ant-design-vue";
import classNames from 'classnames';
export default {
props: ['data', 'title', 'locale', 'emptyText', 'emptyImage', 'showClear'],
methods: {
onClear() {
this.$emit('clear');
},
onClick(e){
this.$emit('click',e);
}
},
render() {
const { data = [], title, locale, emptyText, emptyImage, showClear = true ,onClear} = this
if (data.length === 0) {
return (
<div class="ai-notice notFound">
{emptyImage ? <img src={emptyImage} alt="not found" /> : null}
<div>{emptyText || locale.emptyText}</div>
</div>
);
}
return (
<div class="ai-notice">
<List class="list">
{data.map((item, i) => {
const itemCls = classNames('item', {
['read']: item.read,
});
// eslint-disable-next-line no-nested-ternary
const leftIcon = item.avatar ? (
typeof item.avatar === 'string' ? (
<Avatar class="avatar" src={item.avatar} />
) : (
item.avatar
)
) : null;
return (
<List.Item class={itemCls} rowKey={item.key || i} onClick={() => this.onClick(item)}>
<List.Item.Meta
class="meta"
avatar={<span class="iconElement">{leftIcon}</span>}
title={
<div class="title">
{item.title}
<div class="extra">{item.extra}</div>
</div>
}
description={
<div>
<div class="description" title={item.description}>
{item.description}
</div>
<div class="datetime">{item.datetime}</div>
</div>
}
/>
</List.Item>
)
})}
</List>
{showClear ? (
<div class="clear" onClick={onClear}>
{locale.clear}
{title}
</div>
) : null}
</div>
)
}
}
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
@ai-notice-prefix: ~"@{ai-prefix}-notice";
.@{ai-notice-prefix}{
.list {
max-height: 400px;
overflow: auto;
.item {
transition: all 0.3s;
overflow: hidden;
cursor: pointer;
padding-left: 24px;
padding-right: 24px;
.meta {
width: 100%;
}
.avatar {
background: #fff;
margin-top: 4px;
}
.iconElement {
font-size: 32px;
}
&.read {
opacity: 0.4;
}
&:last-child {
border-bottom: 0;
}
&:hover {
background: @primary-1;
}
.title {
font-weight: normal;
margin-bottom: 8px;
}
.description {
font-size: 12px;
line-height: @line-height-base;
}
.datetime {
font-size: 12px;
margin-top: 4px;
line-height: @line-height-base;
}
.extra {
float: right;
color: @text-color-secondary;
font-weight: normal;
margin-right: 0;
margin-top: -1.5px;
}
}
}
&.notFound {
text-align: center;
padding: 73px 0 88px 0;
color: @text-color-secondary;
img {
display: inline-block;
margin-bottom: 16px;
height: 76px;
}
}
.clear {
height: 46px;
line-height: 46px;
text-align: center;
color: @text-color;
border-radius: 0 0 @border-radius-base @border-radius-base;
border-top: 1px solid @border-color-split;
transition: all 0.3s;
cursor: pointer;
&:hover {
color: @heading-color;
}
}
}
import './index.less'
import { Badge, Popover, Icon, Spin, Tabs } from "ant-design-vue";
import classNames from "classnames";
import List from './NoticeList';
const { TabPane } = Tabs
const NoticeIcon = {
props: ["className", "count", "bell", "locale", "loading"],
methods: {
classNames,
onClear(e) {
// console.log(e);
this.$emit('clear',e);
},
onTabChange(e) {
this.$emit('tabChange', e);
},
onPopupVisibleChange(e) {
this.$emit('popupVisibleChange', e);
},
onItemClick(item, tabProps) {
console.log(item);
this.$emit('itemClick', item, tabProps);
},
getNotificationBox() {
const { $slots, locale = {
emptyText: '暂无数据',
clear: '清空',
}, loading = false } = this;
const children = $slots.default;
if (!children) {
return null;
}
const panes = children.map(child => {
const { list, title, emptyText, emptyImage = 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg' } = child.data.attrs
const tab = list && list.length > 0 ? `${title} (${list.length})` : title
return (
<TabPane tab={tab} key={title}>
<List
data={list}
onClick={item => this.onItemClick(item, child.data.attrs)}
onClear={() => this.onClear(title)}
title={title}
locale={locale}
emptyText={emptyText}
emptyImage={emptyImage}
/>
</TabPane>
)
})
return (
<Spin spinning={loading} delay={0}>
<Tabs class="tabs" onChange={this.onTabChange}>
{panes}
</Tabs>
</Spin>
)
}
},
render() {
const { className, bell, count, onPopupVisibleChange } = this
const noticeButtonClass = classNames(className, 'noticeButton');
const NoticeBellIcon = bell || <Icon type="bell" class="icon" />;
const trigger = (
<span class={noticeButtonClass}>
<Badge count={count} style={{ boxShadow: 'none' }} class="badge">
{NoticeBellIcon}
</Badge>
</span>
);
const notificationBox = this.getNotificationBox();
if (!notificationBox) {
return trigger;
}
return (
<Popover
placement="bottomRight"
content={notificationBox}
overlayClassName="ai-notice-popover"
trigger="click"
arrowPointAtCenter={true}
// popupAlign={popupAlign}
onVisibleChange={onPopupVisibleChange}
>
{trigger}
</Popover>
)
}
}
NoticeIcon.Tab = TabPane
export default NoticeIcon
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
@ai-notice-prefix: ~"@{ai-prefix}-notice";
.@{ai-notice-prefix}{
&.noticeButton {
cursor: pointer;
display: inline-block;
transition: all 0.3s;
}
.icon {
font-size: 18px;
padding: 4px;
}
}
.@{ai-notice-prefix}-popover {
width: 336px;
:global(.ant-popover-inner-content) {
padding: 0;
}
.tabs {
:global {
.ant-tabs-nav-scroll {
text-align: center;
}
.ant-tabs-bar {
margin-bottom: 4px;
}
}
}
}
<template>
<div :class="cls">
<div v-if="title" class="numberInfoTitle">
{{ title }}
</div>
<div v-if="subTitle" class="numberInfoSubTitle">
{{ subTitle }}
</div>
<div class="numberInfoValue" :style="{ 'margin-top:gap': gap }">
<span>
{{ total }}
<em v-if="suffix" class="suffix">{{ suffix }}</em>
</span>
<span v-if="status || subTotal" class="subTotal">
{{ subTotal }}
<a-icon v-if="status" :type="`caret-${status}`" />}
</span>
</div>
</div>
</template>
<script>
import { Icon } from "ant-design-vue";
import classNames from "classnames";
export default {
props: [
"theme",
"title",
"subTitle",
"total",
"subTotal",
"status",
"suffix",
"gap",
],
components: {
AIcon: Icon,
},
computed: {
cls() {
const { theme } = this;
return classNames("numberInfo", {
["numberInfo" + theme]: theme,
});
},
},
};
</script>
\ No newline at end of file
import './index.less'
import NumberInfo from './NumberInfo'
export default NumberInfo
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.numberInfo {
.suffix {
color: @text-color;
font-size: 16px;
font-style: normal;
margin-left: 4px;
}
.numberInfoTitle {
color: @text-color;
font-size: @font-size-lg;
margin-bottom: 16px;
transition: all 0.3s;
}
.numberInfoSubTitle {
color: @text-color-secondary;
font-size: @font-size-base;
height: 22px;
line-height: 22px;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
}
.numberInfoValue {
margin-top: 4px;
font-size: 0;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
& > span {
color: @heading-color;
display: inline-block;
line-height: 32px;
height: 32px;
font-size: 24px;
margin-right: 32px;
}
.subTotal {
color: @text-color-secondary;
font-size: @font-size-lg;
vertical-align: top;
margin-right: 0;
i {
font-size: 12px;
transform: scale(0.82);
margin-left: 4px;
}
:global {
.anticon-caret-up {
color: @red-6;
}
.anticon-caret-down {
color: @green-6;
}
}
}
}
}
.numberInfolight {
.numberInfoValue {
& > span {
color: @text-color;
}
}
}
import './index.less'
import pathToRegexp from 'path-to-regexp';
import { Breadcrumb,Tabs } from "ant-design-vue";
import eventBus from '@/utils/eventBus.js'
const {TabPane} = Tabs
export function urlToList(url) {
const urllist = url.split('/').filter(i => i);
return urllist.map((urlItem, index) => `/${urllist.slice(0, index + 1).join('/')}`);
}
export const getBreadcrumb = (breadcrumbNameMap, url) => {
let breadcrumb = breadcrumbNameMap[url];
if (!breadcrumb) {
Object.keys(breadcrumbNameMap).forEach(item => {
if (pathToRegexp(item).test(url)) {
breadcrumb = breadcrumbNameMap[item];
}
});
}
return breadcrumb || {};
};
const PageHeader = {
props: ["wide", "home", "title", "action", "content", "extraContent", "breadcrumbList", "breadcrumbSeparator", "itemRender", "linkElement","tabList", "tabActiveKey", "tabBarExtraContent","tabChange"],
methods: {
conversionFromProps() {
const { breadcrumbList, breadcrumbSeparator, itemRender, linkElement = 'a' } = this;
return (
<Breadcrumb class="breadcrumb" separator={breadcrumbSeparator}>
{breadcrumbList.map(item => {
const title = itemRender ? itemRender(item) : item.title;
return (
<Breadcrumb.Item key={item.title}>
{item.href
? h(
linkElement,
{
attrs: {
[linkElement === 'a' ? 'href' : 'to']: item.href,
}
},
title
)
: title}
</Breadcrumb.Item>
);
})}
</Breadcrumb>
);
},
getBreadcrumbProps() {
const { params, $router, $route } = this;
const { breadcrumbNameMap } = eventBus;
return {
router: $router,
params,
route: $route,
breadcrumbNameMap
};
},
conversionBreadcrumbList() {
const { breadcrumbList, breadcrumbSeparator } = this;
const { router, params, route, breadcrumbNameMap } = this.getBreadcrumbProps();
if (breadcrumbList && breadcrumbList.length) {
return this.conversionFromProps();
}
// 如果传入 routes 和 params 属性
// If pass routes and params attributes
// if (router && params) {
// return (
// <Breadcrumb
// class="breadcrumb"
// routes={routes.filter(route => route.breadcrumbName)}
// params={params}
// // itemRender={this.itemRender}
// separator={breadcrumbSeparator}
// />
// );
// }
// 根据 location 生成 面包屑
// Generate breadcrumbs based on location
if (route && route.path) {
return this.conversionFromLocation(route, breadcrumbNameMap);
}
return null;
},
conversionFromLocation(route, breadcrumbNameMap) {
const { breadcrumbSeparator, home, itemRender, linkElement = 'a' } = this;
// Convert the url to an array
const pathSnippets = urlToList(route.path);
// Loop data mosaic routing
const extraBreadcrumbItems = pathSnippets.map((url, index) => {
const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url);
if (currentBreadcrumb.inherited) {
return null;
}
const isLinkable = index !== pathSnippets.length - 1 && !currentBreadcrumb.menus;
const name = itemRender ? itemRender(currentBreadcrumb) : currentBreadcrumb.name;
return currentBreadcrumb.name && !currentBreadcrumb.hideInBreadcrumb ? (
<Breadcrumb.Item key={url}>
{h(
isLinkable ? linkElement : 'span',
{ attrs: { [linkElement === 'a' ? 'href' : 'to']: url } },
name
)}
</Breadcrumb.Item>
) : null;
});
// Add home breadcrumbs to your head
extraBreadcrumbItems.unshift(
<Breadcrumb.Item key="home">
{h(
linkElement,
{
attrs:
{
[linkElement === 'a' ? 'href' : 'to']: '/'
}
},
home || 'Home'
)}
</Breadcrumb.Item>
);
return (
<Breadcrumb class="breadcrumb" separator={breadcrumbSeparator}>
{extraBreadcrumbItems}
</Breadcrumb>
);
},
// itemRender(route, params, routes, paths){
// const { linkElement = 'a' } = this;
// const last = routes.indexOf(route) === routes.length - 1;
// return last || !route.component ? (
// <span>{route.breadcrumbName}</span>
// ) : (
// // createElement(
// // linkElement,
// // {
// // href: paths.join('/') || '/',
// // to: paths.join('/') || '/',
// // },
// // route.breadcrumbName
// // )
// <a>atest</a>
// );
// }
},
render() {
const { wide = false, logo, title, action, content, extraContent, tabList, tabActiveKey, tabBarExtraContent, tabChange } = this
const breadcrumb = this.conversionBreadcrumbList();
return (
<div class="pageHeader">
<div class={wide ? 'wide' : ''}>
{breadcrumb}
<div class="detail">
{logo && <div class="logo">{logo}</div>}
<div class="main">
<div class="row">
{title && <h1 class="title">{title}</h1>}
{action && <div class="action">{action}</div>}
</div>
<div class="row">
{content && <div class="content">{content}</div>}
{extraContent && <div class="extraContent">{extraContent}</div>}
</div>
</div>
</div>
{tabList && tabList.length ? (
<Tabs
size="small"
class="tabs"
defaultActiveKey={tabActiveKey}
onChange={tabChange}
tabBarExtraContent={tabBarExtraContent}
>
{tabList.map(item => (
<TabPane tab={item.tab} key={item.key} />
))}
</Tabs>
) : null}
</div>
</div>
)
}
}
export default PageHeader
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.pageHeader {
background: @component-background;
padding: 16px 32px 0 32px;
border-bottom: @border-width-base @border-style-base @border-color-split;
.wide {
max-width: 1200px;
margin: auto;
}
.detail {
display: flex;
}
.row {
display: flex;
width: 100%;
}
.breadcrumb {
margin-bottom: 16px;
}
.tabs {
margin: 0 0 0 -8px;
:global {
.ant-tabs-bar {
border-bottom: 0px;
margin: 0px;
}
}
}
.logo {
flex: 0 1 auto;
margin-right: 16px;
padding-top: 1px;
> img {
width: 28px;
height: 28px;
border-radius: @border-radius-base;
display: block;
}
}
.title {
font-size: 20px;
font-weight: 500;
color: @heading-color;
}
.action {
margin-left: 56px;
min-width: 266px;
:global {
.ant-btn-group:not(:last-child),
.ant-btn:not(:last-child) {
margin-right: 8px;
}
.ant-btn-group > .ant-btn {
margin-right: 0;
}
}
}
.title,
.content {
flex: auto;
}
.action,
.extraContent,
.main {
flex: 0 1 auto;
}
.main {
width: 100%;
}
.title,
.action {
margin-bottom: 16px;
}
.logo,
.content,
.extraContent {
margin-bottom: 16px;
}
.action,
.extraContent {
text-align: right;
}
.extraContent {
margin-left: 88px;
min-width: 242px;
}
}
@media screen and (max-width: @screen-xl) {
.pageHeader {
.extraContent {
margin-left: 44px;
}
}
}
@media screen and (max-width: @screen-lg) {
.pageHeader {
.extraContent {
margin-left: 20px;
}
}
}
@media screen and (max-width: @screen-md) {
.pageHeader {
.row {
display: block;
}
.action,
.extraContent {
margin-left: 0;
text-align: left;
}
}
}
@media screen and (max-width: @screen-sm) {
.pageHeader {
.detail {
display: block;
}
}
}
@media screen and (max-width: @screen-xs) {
.pageHeader {
.action {
:global {
.ant-btn-group,
.ant-btn {
display: block;
margin-bottom: 8px;
}
.ant-btn-group > .ant-btn {
display: inline-block;
margin-bottom: 0;
}
}
}
}
}
import './GridContent.less'
import { mapGetters } from "vuex";
const GridContent = {
computed: {
...mapGetters({
settings: "global/settings"
})
},
render() {
const { $slots } = this;
const { contentWidth } = this.settings;
const children = $slots.default;
let className = `main`;
if (contentWidth === 'Fixed') {
className = `main wide`;
}
return <div class={className}>{children}</div>;
}
}
export default GridContent
\ No newline at end of file
.main {
width: 100%;
height: 100%;
min-height: 100%;
transition: 0.3s;
&.wide {
max-width: 1200px;
margin: 0 auto;
}
}
\ No newline at end of file
import './index.less'
import GridContent from './GridContent';
import PageHeader from '@/components/PageHeader';
import { mapGetters } from "vuex";
const PageHeaderWrapper = {
props: ["wrapperClassName","loading","content","extraContent","breadcrumbList","title","tabList", "tabActiveKey", "tabBarExtraContent","tabChange"],
computed: {
...mapGetters({
settings: "global/settings"
})
},
render(){
const {$slots,wrapperClassName,content,extraContent,breadcrumbList,title,tabList,tabActiveKey,tabBarExtraContent,tabChange} = this
const children = $slots.default;
const top = $slots.top;
return (
<div style={{ margin: '-24px -24px 0' }} class={wrapperClassName}>
{top}
<PageHeader
wide={this.settings.contentWidth === 'Fixed'}
home={this.$t('menu.home')}
content={content}
extraContent={extraContent}
breadcrumbList={breadcrumbList}
title={title}
linkElement={'router-link'}
tabList={tabList}
tabActiveKey={tabActiveKey}
tabBarExtraContent={tabBarExtraContent}
tabChange={tabChange}
itemRender={item => {
if (item.locale) {
return this.$t(item.locale);
}
return item.name;
}}
/>
{children?(
<div class="pageheaderwrapper-content">
<GridContent>{children}</GridContent>
</div>
):null}
</div>
)
}
}
export default PageHeaderWrapper
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.pageheaderwrapper-content {
margin: 24px 24px 0;
}
@media screen and (max-width: @screen-sm) {
.pageheaderwrapper-content {
margin: 24px 0 0;
}
}
<template>
<ai-send-captcha-button :size="size" :disabled="start" @click="handleClick" v-text="tmpStr" />
</template>
<script>
import { Button } from "ant-design-vue";
const SendCaptchaButton = {
extends: Button,
components: {
"ai-send-captcha-button": Button
},
data() {
return {
tmpStr: this.initStr,
runStr: "{%s}秒后重试",
resetStr: "重新获取",
timer: null,
start: false,
runSecond: this.second,
lastSecond: 0
};
},
props: {
initStr: {
type: String,
default: "获取验证码"
},
second: {
default: 60,
validator(val) {
return /^\d*$/.test(val);
}
},
value: {
default: false,
type: Boolean
},
storageKey: {
default: "SendCaptchaStorageKey",
type: String
}
},
methods: {
run() {
let lastSecond = this.lastSecond;
let second = lastSecond ? lastSecond : this.runSecond;
if (this.storageKey) {
const runSecond = new Date().getTime() + second * 1000;
window.sessionStorage.setItem(this.storageKey, runSecond);
}
if (!lastSecond) {
this.tmpStr = this.getStr(second);
}
this.timer = setInterval(() => {
second--;
this.tmpStr = this.getStr(second);
second <= 0 && this.timeout();
}, 1000);
},
timeout() {
this.tmpStr = this.resetStr;
this.start = false;
this.$emit("input", false);
clearInterval(this.timer);
},
getStr(second) {
return this.runStr.replace(/\{([^{]*?)%s(.*?)\}/g, second);
},
handleClick() {
// this.start = true;
this.$emit("click");
}
},
watch: {
value(val) {
this.start = val;
if (!val) {
clearInterval(this.timer);
if (this.storageKey) {
window.sessionStorage.removeItem(this.storageKey);
this.lastSecond = 0;
}
} else {
this.run();
}
}
},
created() {
const lastSecond = ~~(
(window.sessionStorage.getItem(this.storageKey) - new Date().getTime()) /
1000
);
if (lastSecond > 0 && this.storageKey) {
this.$emit("input", true);
this.tmpStr = this.getStr(lastSecond);
this.lastSecond = lastSecond;
}
},
beforeDestroy() {
!this.storageKey && this.timeout();
}
};
export default SendCaptchaButton;
</script>
\ No newline at end of file
import { Tooltip, Icon } from "ant-design-vue";
import './index.less';
const BlockChecbox = {
props: ["value", "list"],
methods:{
handleChange(key) {
this.$emit('change', key);
},
},
render(){
const {value,list} = this
return (
<div class="blockChecbox" key={value}>
{list.map(item => (
<Tooltip title={item.title} key={item.key}>
<div class="item" onClick={() => this.handleChange(item.key)}>
<img src={item.url} alt={item.key} />
<div
class="selectIcon"
style={{ display: value === item.key ? 'block' : 'none', ...item.style}}
>
<Icon type="check"/>
</div>
</div>
</Tooltip>
))}
</div>
)
}
}
export default BlockChecbox;
import { Tooltip, Icon } from "ant-design-vue";
import styles from './ThemeColor.less';
const Tag = {
props: ["color", "check"],
methods:{
handleChange(color) {
this.$emit('change', color);
},
},
render() {
const { color, check } = this
return (
<div
onClick={()=>this.handleChange(color)}
style={{
backgroundColor: color,
}}
>
{check ? <Icon type="check" /> : ''}
</div>
)
}
}
const ThemeColor = {
props: ["colors", "title", "value"],
methods:{
handleChange(color) {
this.$emit('change', color);
},
},
render() {
const { colors, title, value } = this
let colorList = colors;
if (!colors) {
colorList = [
{
key: 'dust',
color: '#F5222D',
},
{
key: 'volcano',
color: '#FA541C',
},
{
key: 'sunset',
color: '#FAAD14',
},
{
key: 'cyan',
color: '#13C2C2',
},
{
key: 'green',
color: '#42b983',
},
{
key: 'daybreak',
color: '#1890FF',
},
{
key: 'geekblue',
color: '#2F54EB',
},
{
key: 'purple',
color: '#722ED1',
},
];
}
return (
<div class="themeColor">
<h3 class="title">{title}</h3>
<div>
{colorList.map(({ key, color }) => (
<Tooltip key={color} title={this.$t(`app.setting.themecolor.${key}`)}>
<Tag
class="colorBlock"
color={color}
check={value === color}
onChange={color=>this.handleChange(color)}
/>
</Tooltip>
))}
</div>
</div>
)
}
};
export default ThemeColor;
.themeColor {
overflow: hidden;
margin-top: 24px;
.title {
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
line-height: 22px;
margin-bottom: 12px;
}
.colorBlock {
width: 20px;
height: 20px;
border-radius: 2px;
float: left;
cursor: pointer;
margin-right: 8px;
text-align: center;
color: #fff;
font-weight: bold;
}
}
\ No newline at end of file
import './index.less';
import ThemeColor from './ThemeColor';
import BlockChecbox from './BlockChecbox';
import { Drawer, Modal, Divider, message } from "ant-design-vue";
import { mapGetters } from "vuex";
const Body = {
props:['title'],
render: function render() {
var h = arguments[0];
const { $slots,title } = this
return h('div', { style: { marginBottom: 24 } }, [h('h3', { 'class': 'title' }, title), $slots['default']])
}
}
const SettingDrawer = {
// data: () => ({
// primaryColor: "#42b983",
// blockChecbox: "sidemenu"
// }),
props: ["collapse"],
computed: {
...mapGetters({
settings: "global/settings",
}),
},
methods: {
changeSetting(key,value) {
const nextState = this.settings;
nextState[key] = value;
if (key === 'layout') {
nextState.contentWidth = value === 'topmenu' ? 'Fixed' : 'Fluid';
}
// else if (key === 'fixedHeader' && !value) {
// nextState.autoHideHeader = false;
// }
// console.log(this.settings);
// console.log(nextState);
// this.$store.commit('global/UpdateDefaultSettings', this.s)
// this.$store.commit('global/UpdateDefaultSettings', nextState)
// console.log(key);
// console.log(value);
// message.loading("正在编译主题!", 3);
this.$store.dispatch('global/defaultSettings',true)
},
togglerContent() {
this.$parent.collapse = !this.collapse
}
},
render() {
const { collapse } = this
const { primaryColor, layout, navTheme } = this.settings
return (
<Drawer
title="我是一个抽屉"
placement="right"
closable={false}
onClose={this.togglerContent}
visible={collapse}
width={300}
>
<div class="setting-drawer content">
<Body title={this.$t('app.setting.pagestyle')}>
<BlockChecbox
list={[
{
key: 'dark',
url: 'https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg',
title: this.$t('app.setting.pagestyle.dark'),
},
{
key: 'light',
url: 'https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg',
title: this.$t('app.setting.pagestyle.light'),
},
]}
value={navTheme}
onChange={e=>{this.changeSetting('navTheme',e)}}
/>
</Body>
<Divider />
<ThemeColor
title={this.$t('app.setting.themecolor')}
value={primaryColor}
onChange={e=>{this.changeSetting('primaryColor',e)}}
/>
<Divider />
<Body title={this.$t('app.setting.navigationmode')}>
<BlockChecbox
list={[
{
key: 'sidemenu',
url: 'https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg',
title: this.$t('app.setting.sidemenu'),
},
{
key: 'topmenu',
url: 'https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg',
title: this.$t('app.setting.topmenu'),
style: {paddingLeft: '18px'}
},
]}
value={layout}
onChange={e=>{this.changeSetting('layout',e)}}
/>
</Body>
<Divider />
<p>其它设置</p>
</div>
</Drawer>
)
}
}
export default SettingDrawer
\ No newline at end of file
@import 'ant-design-vue/lib/style/themes/default.less';
.setting-drawer{
&.content {
min-height: 100%;
background: #fff;
position: relative;
}
.blockChecbox {
display: flex;
.item {
margin-right: 16px;
position: relative;
// box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
border-radius: @border-radius-base;
cursor: pointer;
img {
width: 48px;
}
}
.selectIcon {
position: absolute;
top: 0;
right: 0;
width: 100%;
padding-top: 15px;
padding-left: 24px;
height: 100%;
color: @primary-color;
font-size: 14px;
font-weight: bold;
}
}
.color_block {
width: 38px;
height: 22px;
margin: 4px;
border-radius: 4px;
cursor: pointer;
margin-right: 12px;
display: inline-block;
vertical-align: middle;
}
.title {
font-size: 14px;
color: @heading-color;
line-height: 22px;
margin-bottom: 12px;
}
.handle {
position: absolute;
top: 240px;
background: @primary-color;
width: 48px;
height: 48px;
right: 300px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
pointer-events: auto;
z-index: 0;
text-align: center;
font-size: 16px;
border-radius: 4px 0 0 4px;
}
.productionHint {
font-size: 12px;
margin-top: 16px;
}
}
<script>
import { Menu, Icon, Spin } from "ant-design-vue";
import { mapGetters } from "vuex";
// Conversion router to menu.
export default {
props: {
collapsed: { default: false, type: Boolean },
theme: { default: "dark", type: String },
layout: { type: String },
mode: { default: "inline", type: String },
menuData: { default: () => [], type: Array },
styles: { type: String },
},
computed: {
...mapGetters({
loading: "global/nav/loading",
}),
},
components: {
AMenu: Menu,
AMenuItem: Menu.Item,
ASubMenu: Menu.SubMenu,
AMenuDivider: Menu.Divider,
AMenuItemGroup: Menu.ItemGroup,
AIcon: Icon,
},
methods: {
getIcon(icon) {
if (typeof icon === "string" && icon.indexOf("http") === 0) {
return <img src={icon} alt="icon" class="icon" />;
}
if (typeof icon === "string") {
return <a-icon type={icon} />;
}
// if(!icon){
// return <a-icon type='profile' />;
// }
return icon;
},
getNavMenuItems(menusData, parent) {
// console.log(menusData)
if (!menusData) {
return [];
}
return menusData.map((item) => {
if (item.name) {
return this.getSubMenuOrItem(item, parent);
}
if (item.menus) {
return this.getNavMenuItems(item.menus, parent);
}
});
},
getSubMenuOrItem(item) {
// doc: add hideChildrenInMenu 隐藏菜单
if (item.menus && item.menus.some((menu) => menu.name)) {
const name = this.$t(item.locale);
return (
<a-sub-menu
title={
item.icon ? (
<span>
{this.getIcon(item.icon)}
<span>{name}</span>
</span>
) : (
name
)
}
key={item.path}
>
{this.getNavMenuItems(item.menus)}
</a-sub-menu>
);
}
return (
<a-menu-item key={item.path}>{this.getMenuItemPath(item)}</a-menu-item>
);
},
getMenuItemPath(item) {
const name = this.$t(item.locale);
const itemPath = this.conversionPath(item.path);
const icon = this.getIcon(item.icon);
// // Is it a http link
if (/^https?:\/\//.test(itemPath)) {
return (
<a href={itemPath}>
{icon}
<span>{name}</span>
</a>
);
}
return (
<router-link to={itemPath}>
{icon}
<span>{name}</span>
</router-link>
);
},
conversionPath(path) {
if (path && path.indexOf("http") === 0) {
return path;
}
return `/${path || ""}`.replace(/\/+/g, "/");
},
urlToList(url) {
const urllist = url.split("/").filter((i) => i);
return urllist.map(
(urlItem, index) => `/${urllist.slice(0, index + 1).join("/")}`
);
},
getOpenKeys(path) {
const openKeys = this.urlToList(path);
if (this.layout === "topmenu") {
return null;
}
return openKeys.filter((item) => item !== path);
},
},
render() {
const { path } = this.$route;
const openKeys = this.getOpenKeys(path);
return (
<Spin spinning={this.loading} class="baseMenuLoadding">
<a-menu
defaultOpenKeys={openKeys}
selectedKeys={[path]}
key="Menu"
mode={this.mode}
theme={this.theme}
collapsed={this.collapsed}
style={this.styles}
>
{this.getNavMenuItems(this.menuData)}
</a-menu>
</Spin>
);
},
};
</script>
\ No newline at end of file
<template>
<a-layout-sider v-model="collapsed" width="256" :class="`ai-sider-menu sider ${fixSiderbar?'fixSiderbar':'',settings.navTheme==='light'?'light':'dark'}`" :theme="settings.navTheme">
<div class="logo" key="logo" id="logo">
<router-link to="/">
<img :src="logo" alt="logo" />
<h1>{{ settings.leftMenuTitle }}</h1>
</router-link>
</div>
<a-base-menu :collapsed="collapsed" :menuData="menuData" :theme="settings.navTheme" :layout="settings.layout" styles="padding: '16px 0'; width: '100%'"/>
</a-layout-sider>
</template>
<script>
import { Layout } from "ant-design-vue";
import ABaseMenu from "@/components/SiderMenu/BaseMenu";
import { mapGetters } from "vuex";
export default {
props: {
collapsed: {
default: false,
type: Boolean
},
fixSiderbar: {
default: false,
type: Boolean
},
menuData: {
default: () => [],
type: Array
},
logo: { type: String }
},
computed: {
...mapGetters({
settings: "global/settings"
})
},
components: {
ALayoutSider: Layout.Sider,
ABaseMenu
},
};
</script>
import './index.less'
import SiderMenu from './SiderMenu.vue'
export default SiderMenu
\ 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.
export default {
navTheme: 'dark', // theme for nav menu
primaryColor: '#1890FF', // primary color of ant design
layout: 'sidemenu', // nav menu position: sidemenu or topmenu
contentWidth: 'Fluid', // layout of content: Fluid or Fixed, only works when layout is topmenu
fixedHeader: false, // sticky header
autoHideHeader: false, // auto hide header
fixSiderbar: false, // sticky siderbar
leftMenuTitle: "EVM 应用商店", // 左侧边栏顶部名称
leftMenuIcon: "", // 左侧边栏顶部Logo
appSlogan: "EVM,致力于为互联网行业提供物联网解决方案", // 应用宣传文案
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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