Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
E
evm-store
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanli
evm-store
Commits
c0dd2d99
Commit
c0dd2d99
authored
Apr 20, 2021
by
wanli
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
更新后端
parent
57c0f668
Changes
28
Show whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
336 additions
and
515 deletions
+336
-515
backend/app/setting.py
backend/app/setting.py
+6
-5
backend/app/signal_manager.py
backend/app/signal_manager.py
+0
-10
backend/backupData.json
backend/backupData.json
+1
-0
backend/config.ini
backend/config.ini
+3
-2
backend/controller/__init__.py
backend/controller/__init__.py
+0
-1
backend/controller/app_logs_manager.py
backend/controller/app_logs_manager.py
+1
-1
backend/controller/apps_manager.py
backend/controller/apps_manager.py
+27
-45
backend/controller/build_logs_manager.py
backend/controller/build_logs_manager.py
+4
-4
backend/controller/device_manager.py
backend/controller/device_manager.py
+1
-2
backend/controller/upload_manager.py
backend/controller/upload_manager.py
+0
-40
backend/deploy.py
backend/deploy.py
+72
-252
backend/deploy.sh
backend/deploy.sh
+21
-0
backend/model/user.py
backend/model/user.py
+1
-1
backend/restart.json
backend/restart.json
+0
-3
backend/run.sh
backend/run.sh
+4
-0
backend/schema/apps.py
backend/schema/apps.py
+4
-8
backend/utils/epk.py
backend/utils/epk.py
+3
-30
backend/view/annex.py
backend/view/annex.py
+1
-1
backend/view/api.py
backend/view/api.py
+44
-7
backend/view/app_logs.py
backend/view/app_logs.py
+1
-1
backend/view/apps.py
backend/view/apps.py
+46
-6
backend/view/device.py
backend/view/device.py
+1
-1
backend/view/download.py
backend/view/download.py
+1
-1
backend/view/files.py
backend/view/files.py
+3
-9
backend/view/login.py
backend/view/login.py
+1
-1
backend/view/netdisc.py
backend/view/netdisc.py
+1
-1
backend/view/user.py
backend/view/user.py
+1
-1
frontend/src/views/system/apps.vue
frontend/src/views/system/apps.vue
+88
-82
No files found.
backend/app/setting.py
View file @
c0dd2d99
...
...
@@ -12,10 +12,9 @@ config = dict(
DEBUG
=
True
,
HOST
=
"0.0.0.0"
,
PORT
=
5000
,
SECRET_KEY
=
'secret_key_EhuqUkwV'
,
LOGIN_DISABLED
=
False
,
BACKUP_DIR
=
conf
.
get
(
'application'
,
'backup_dir'
)
,
NETDISC
=
conf
.
get
(
'uploads'
,
'netdisc'
)
,
MD5_SALT
=
"EhuqUkwV"
,
SECRET_KEY
=
'secret_key_EhuqUkwV'
,
DATABASE
=
conf
.
get
(
'database'
,
'filename'
),
DATABASE_FILE
=
conf
.
get
(
'scheduler'
,
'db'
),
PONY
=
{
...
...
@@ -24,9 +23,11 @@ config = dict(
'create_db'
:
True
,
},
TABLE_PREFIX
=
'evm_store_'
,
MD5_SALT
=
"EhuqUkwV"
,
BACKUP_DIR
=
conf
.
get
(
'application'
,
'backup_dir'
)
,
UPLOAD_SERVER
=
"{}://{}:{}/"
.
format
(
conf
.
get
(
'uploads'
,
'protocol'
),
conf
.
get
(
'uploads'
,
'host'
),
conf
.
get
(
'uploads'
,
'port'
)),
UPLOAD_PATH
=
os
.
getcwd
(),
EPK_DIR
=
conf
.
get
(
'uploads'
,
'epk_dir'
),
TEMP_DIR
=
conf
.
get
(
'uploads'
,
'temp_dir'
),
UPLOAD_PATH
=
os
.
path
.
abspath
(
conf
.
get
(
'uploads'
,
'upload_path'
)),
UPLOAD_DIR
=
conf
.
get
(
'uploads'
,
'upload_dir'
),
TEMPLATE_PATH
=
os
.
path
.
join
(
os
.
getcwd
(),
"static"
),
STATIC_PATH
=
os
.
path
.
join
(
os
.
getcwd
(),
"static"
),
...
...
backend/app/signal_manager.py
View file @
c0dd2d99
...
...
@@ -8,11 +8,8 @@ class SignalManager(object):
actionUpdatePassword
=
PySignal
()
# 上传文件
actionUploadFile
=
PySignal
()
actionBackupDatabase
=
PySignal
()
actionApplicationBuild
=
PySignal
()
# 导入excel
# 导出excel
# 登录模块
actionLogin
=
PySignal
()
...
...
@@ -33,13 +30,6 @@ class SignalManager(object):
actionUpdateBuildLog
=
PySignal
()
actionDeleteBuildLog
=
PySignal
()
# 网盘管理
actionAddNetDisc
=
PySignal
()
actionGetNetDisc
=
PySignal
()
actionGetNetDiscList
=
PySignal
()
actionUpdateNetDisc
=
PySignal
()
actionDeleteNetDisc
=
PySignal
()
# 用户模块
actionAddUser
=
PySignal
()
actionDeleteUser
=
PySignal
()
...
...
backend/backupData.json
0 → 100644
View file @
c0dd2d99
{
"lastModifyDateTime"
:
1618915131
}
\ No newline at end of file
backend/config.ini
View file @
c0dd2d99
...
...
@@ -2,10 +2,11 @@
port
=
80
host
=
store.evmiot.com
protocol
=
http
upload_path
=
.
/
upload_path
=
.
./../evm_app_store_files
temp_dir
=
tmp
epk_dir
=
epks
db_dir
=
epkdb
upload_dir
=
uploads
netdisc
=
netdisc
[database]
provider
=
sqlite
...
...
backend/controller/__init__.py
View file @
c0dd2d99
...
...
@@ -21,7 +21,6 @@ logger = logging.getLogger("controller")
def
initConnect
():
# 系统模块
signalManager
.
actionUploadFile
.
connect
(
uploadManager
.
upload
)
signalManager
.
actionUpdatePassword
.
connect
(
apiManager
.
update_user_password
)
signalManager
.
actionApplicationBuild
.
connect
(
appsManager
.
build
)
...
...
backend/controller/app_logs_manager.py
View file @
c0dd2d99
...
...
@@ -73,7 +73,7 @@ class AppLogsManager(object):
if
not
editor
:
return
False
,
"current user is not exists"
if
editor
.
role
==
"USER
"
:
if
editor
.
role
!=
"administrator
"
:
temp
.
update
({
'create_by'
:
editor
})
if
"scope_type"
in
data
and
data
.
get
(
"scope_type"
)
==
"list"
:
...
...
backend/controller/apps_manager.py
View file @
c0dd2d99
...
...
@@ -13,6 +13,7 @@ import traceback
from
urllib
import
parse
from
datetime
import
datetime
from
pony.orm
import
*
from
app
import
signalManager
,
config
from
model
import
fullStackDB
from
model.annex
import
Annex
...
...
@@ -44,6 +45,7 @@ class AppsManager(object):
# return False, "app_name has been exists."
data
.
update
({
'app_icon'
:
data
[
"app_icon"
]
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
),
'create_by'
:
editor
,
'create_at'
:
datetime
.
now
(),
'update_by'
:
editor
,
...
...
@@ -51,52 +53,33 @@ class AppsManager(object):
})
app_files
=
[]
if
data
.
get
(
"app_files"
):
app_files
=
data
.
get
(
"app_files"
)
data
.
pop
(
"app_files"
)
data
.
update
({
"app_icon"
:
data
.
get
(
"app_icon"
)
.
get
(
"filepath"
)
})
epk_path
=
""
if
data
.
get
(
"fileList"
):
app_files
=
data
.
get
(
"fileList"
)
data
.
pop
(
"fileList"
)
epk_path
=
data
.
get
(
"epk_path"
)
data
.
pop
(
"epk_path"
)
app
=
Apps
(
**
data
)
commit
()
target_path
=
os
.
sep
.
join
([
config
.
get
(
"UPLOAD_PATH"
),
config
.
get
(
"UPLOAD_DIR"
),
"evueapps"
,
editor
.
account
])
epk_dirname
=
"{}-{}-{}"
.
format
(
app
.
app_name
,
app
.
app_version
,
datetime
.
now
()
.
strftime
(
"
%
Y
%
m
%
d
%
H
%
M
%
S"
))
# EPK资源文件临时目录
target_dir
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
target_path
,
epk_dirname
]))
target_path
=
os
.
sep
.
join
([
target_dir
,
"src"
])
if
not
os
.
path
.
exists
(
target_path
):
os
.
makedirs
(
target_path
)
target_files
=
[]
for
f
in
app_files
:
filename
=
os
.
path
.
basename
(
f
.
get
(
"filepath"
))
target_f
=
copy
.
deepcopy
(
f
)
name
,
suffix
=
os
.
path
.
splitext
(
filename
)
name
=
re
.
sub
(
r"_\d{14}$"
,
""
,
name
)
# 在EPK目录下生成JSON文件
with
open
(
os
.
sep
.
join
([
os
.
path
.
dirname
(
epk_path
),
"epk.json"
]),
"w"
)
as
f
:
json
.
dump
(
app
.
to_dict
(
exclude
=
[
"uuid"
,
"create_at"
,
"update_at"
,
"delete_at"
]),
f
)
target_filepath
=
os
.
sep
.
join
([
target_path
,
name
+
suffix
])
target_f
[
'filepath'
]
=
target_filepath
target_files
.
append
(
target_f
)
shutil
.
copy
(
f
.
get
(
"filepath"
),
target_f
[
'filepath'
])
os
.
remove
(
f
.
get
(
"filepath"
))
for
a
in
target_files
:
Annex
(
app
=
app
,
title
=
a
.
get
(
"filename"
),
path
=
a
.
get
(
"filepath"
),
size
=
a
.
get
(
"filesize"
),
create_by
=
editor
,
create_at
=
datetime
.
now
(),
update_by
=
editor
,
update_at
=
datetime
.
now
())
for
a
in
app_files
:
Annex
(
app
=
app
,
title
=
os
.
path
.
basename
(
a
),
path
=
a
,
size
=
os
.
path
.
getsize
(
a
),
create_by
=
editor
,
create_at
=
datetime
.
now
(),
update_by
=
editor
,
update_at
=
datetime
.
now
())
flush
()
commit
()
# 打包成EPK文件
app_info
=
{}
params
=
{
'appName'
:
app
.
app_name
,
'appDir'
:
target_path
,
'appVersion'
:
app
.
app_version
,
'output'
:
target_dir
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
)
}
if
editor
.
role
==
"
ADMIN
"
:
params
=
{
'appName'
:
app
.
app_name
,
'appDir'
:
epk_path
,
'appVersion'
:
app
.
app_version
,
'output'
:
os
.
path
.
dirname
(
epk_path
)
}
if
editor
.
role
==
"
administrator"
or
editor
.
role
==
"enterprise
"
:
params
[
'algorithm'
]
=
"h"
epk
=
EpkApp
(
**
params
)
app_info
=
epk
.
pack
()
epk_filename
=
os
.
sep
.
join
([
target_dir
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
),
"{}.epk"
.
format
(
app
.
app_name
)])
.
replace
(
'
\\
'
,
'/'
)
epk_filename
=
os
.
sep
.
join
([
os
.
path
.
dirname
(
epk_path
)
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
),
"{}.epk"
.
format
(
app
.
app_name
)])
.
replace
(
'
\\
'
,
'/'
)
app_info
[
'md5'
]
=
str
(
app_info
[
'md5'
])
result
=
BuildLogs
(
app
=
app
,
app_path
=
epk_filename
,
app_info
=
app_info
,
create_by
=
editor
,
create_at
=
datetime
.
now
(),
update_by
=
editor
,
update_at
=
datetime
.
now
())
...
...
@@ -104,7 +87,7 @@ class AppsManager(object):
AppLogs
(
app_name
=
app
.
app_name
,
app_path
=
epk_filename
,
app_version
=
data
.
get
(
"app_version"
),
app_info
=
app_info
,
create_by
=
editor
,
create_at
=
datetime
.
now
())
commit
()
return
result
,
"add app {}
.
"
.
format
(
"success"
if
result
else
"fail"
)
return
result
,
"add app {}"
.
format
(
"success"
if
result
else
"fail"
)
def
delete
(
self
,
user
,
uuid
):
with
db_session
:
...
...
@@ -119,7 +102,6 @@ class AppsManager(object):
return
result
,
"delete app {}."
.
format
(
"success"
if
result
else
"fail"
)
def
get
(
self
,
user
,
data
):
# 重新打包
if
not
data
.
get
(
"uuid"
):
return
False
,
"app uuid can not be null"
...
...
@@ -141,9 +123,10 @@ class AppsManager(object):
if
not
source_files
:
return
None
,
"apps file not found"
dir_format
=
"{}-{}-{}"
.
format
(
app
.
app_name
,
app
.
app_version
,
datetime
.
now
()
.
strftime
(
"
%
Y
%
m
%
d
%
H
%
M
%
S"
))
upload_dir
=
os
.
sep
.
join
([
config
.
get
(
"UPLOAD_PATH"
),
config
.
get
(
"UPLOAD_DIR"
),
"evueapps"
])
target_dir
=
os
.
sep
.
join
([
upload_dir
,
editor
.
account
,
dir_format
])
dtNowString
=
datetime
.
now
()
.
strftime
(
"
%
Y
%
m
%
d
%
H
%
M
%
S"
)
dirname
=
"{}-{}-{}-{}"
.
format
(
app
.
app_name
,
app
.
app_version
,
app
.
category
,
dtNowString
)
upload_dir
=
os
.
sep
.
join
([
config
.
get
(
"UPLOAD_PATH"
),
config
.
get
(
"EPK_DIR"
)])
target_dir
=
os
.
sep
.
join
([
upload_dir
,
dirname
])
dest_dir
=
os
.
sep
.
join
([
target_dir
,
"src"
])
if
not
os
.
path
.
exists
(
dest_dir
):
os
.
makedirs
(
dest_dir
)
...
...
@@ -161,13 +144,13 @@ class AppsManager(object):
shutil
.
copy
(
os
.
path
.
normpath
(
target_file
),
dst_file
)
app_files
.
append
([
sf
.
id
,
dst_file
])
# 这里面存在一个逻辑问题,就是将文件拷贝过去之后,需要在Annex表重新生成有感这个EPK文件所有资源文件的记录
# 否则会在下次重新打包时候,找不到相关资源文件报错
with
open
(
os
.
sep
.
join
([
target_dir
,
"epk.json"
]),
"w"
)
as
f
:
json
.
dump
(
app
.
to_dict
(
exclude
=
[
"uuid"
,
"create_at"
,
"update_at"
,
"delete_at"
]),
f
)
# 打包成EPK文件
app_info
=
{}
params
=
{
'appName'
:
app
.
app_name
,
'appDir'
:
dest_dir
,
'appVersion'
:
app
.
app_version
,
'output'
:
target_dir
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
)
}
if
editor
.
role
==
"
ADMIN
"
:
params
=
{
'appName'
:
app
.
app_name
,
'appDir'
:
dest_dir
,
'appVersion'
:
app
.
app_version
,
'output'
:
target_dir
}
if
editor
.
role
==
"
administrator"
or
editor
.
role
==
"enterprise
"
:
params
[
'algorithm'
]
=
"h"
epk
=
EpkApp
(
**
params
)
app_info
=
epk
.
pack
()
...
...
@@ -175,7 +158,6 @@ class AppsManager(object):
# 更新数据库对应文件路径
# 将文件拷贝过去后,需要重新更新数据库文件记录
epk_path
=
os
.
sep
.
join
([
target_dir
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
),
"{}.epk"
.
format
(
app
.
app_name
)])
.
replace
(
'
\\
'
,
'/'
)
build
=
BuildLogs
.
get
(
app
=
app
)
...
...
@@ -206,7 +188,7 @@ class AppsManager(object):
if
not
editor
:
return
False
,
"current user is not exists"
if
editor
.
role
==
"
ADMIN
"
:
if
editor
.
role
==
"
administrator
"
:
temp
.
update
({
"is_delete"
:
False
})
else
:
temp
.
update
({
"create_by"
:
editor
,
"is_delete"
:
False
})
...
...
@@ -319,7 +301,7 @@ class AppsManager(object):
# 打包成EPK文件
app_info
=
{}
params
=
{
'appName'
:
app
.
app_name
,
'appDir'
:
dest_dir
,
'appVersion'
:
app
.
app_version
,
'output'
:
target_dir
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
)
}
if
user
.
role
==
"
ADMIN
"
:
if
user
.
role
==
"
administrator"
or
user
.
role
==
"enterprise
"
:
params
[
'algorithm'
]
=
"h"
epk
=
EpkApp
(
**
params
)
app_info
=
epk
.
pack
()
...
...
backend/controller/build_logs_manager.py
View file @
c0dd2d99
...
...
@@ -68,7 +68,7 @@ class BuildLogsManager(object):
# 打包成EPK文件
app_info
=
{}
params
=
{
'appName'
:
app
.
app_name
,
'appDir'
:
dest_dir
,
'appVersion'
:
app
.
app_version
,
'output'
:
target_dir
.
replace
(
config
.
get
(
"UPLOAD_PATH"
),
""
)
}
if
editor
.
role
==
"
ADMIN
"
:
if
editor
.
role
==
"
administrator"
or
editor
.
role
==
"enterprise
"
:
params
[
'algorithm'
]
=
"h"
epk
=
EpkApp
(
**
params
)
app_info
=
epk
.
pack
()
...
...
@@ -137,10 +137,10 @@ class BuildLogsManager(object):
if
not
editor
:
return
False
,
"current user is not exists"
if
editor
.
role
==
"USER"
:
temp
.
update
({
"create_by"
:
editor
,
"is_delete"
:
False
})
else
:
if
editor
.
role
==
"administrator"
:
temp
.
update
({
"is_delete"
:
False
})
else
:
temp
.
update
({
"create_by"
:
editor
,
"is_delete"
:
False
})
if
"scope_type"
in
data
and
data
.
get
(
"scope_type"
)
==
"list"
:
result
=
BuildLogs
.
select
()
.
where
(
**
temp
)
.
order_by
(
desc
(
BuildLogs
.
create_at
))
...
...
backend/controller/device_manager.py
View file @
c0dd2d99
...
...
@@ -73,12 +73,11 @@ class DeviceManager(object):
if
not
editor
:
return
False
,
"current user is not exists"
if
editor
.
role
==
"
ADMIN
"
:
if
editor
.
role
==
"
administrator
"
:
temp
.
update
({
"is_delete"
:
False
})
else
:
temp
.
update
({
"create_by"
:
editor
,
"is_delete"
:
False
})
if
"scope_type"
in
data
and
data
.
get
(
"scope_type"
)
==
"list"
:
result
=
Device
.
select
()
.
where
(
**
temp
)
.
order_by
(
desc
(
Device
.
create_at
))
temp
=
[]
...
...
backend/controller/upload_manager.py
View file @
c0dd2d99
...
...
@@ -19,7 +19,6 @@ from urllib import parse
from
datetime
import
datetime
from
threading
import
Thread
from
werkzeug.security
import
check_password_hash
from
flask
import
request
from
app.setting
import
config
from
utils
import
md5_salt
,
random_string
...
...
@@ -114,45 +113,6 @@ class UploadManager(object):
"message"
:
"upload file [
%
s] failed!
\n
%
s"
%
(
obj
[
'path'
],
repr
(
e
))
}
def
upload
(
self
):
try
:
binfile
=
request
.
files
.
get
(
"binfile"
)
if
not
binfile
:
return
None
,
"file can not be null"
obj
=
dict
()
obj
[
'filename'
]
=
binfile
.
filename
obj
[
'content'
]
=
binfile
.
stream
.
read
()
# 目录结构:模块类型/年/月/项目名/文件名_时间日期.文件后缀
# 模块类型:项目管理模块、资质管理模块
filename
=
os
.
path
.
splitext
(
obj
[
'filename'
])[
0
]
+
"_{}"
.
format
(
datetime
.
now
()
.
strftime
(
"
%
Y
%
m
%
d
%
H
%
M
%
S"
))
+
os
.
path
.
splitext
(
obj
[
'filename'
])[
-
1
]
# 获取相对路径
relative_path
=
config
.
get
(
"UPLOAD_DIR"
)
# 获取最终存储的绝对路径
savePath
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
config
.
get
(
"UPLOAD_PATH"
),
relative_path
]))
# 获取最终存储的文件路径
saveFile
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
savePath
,
filename
]))
if
not
os
.
path
.
exists
(
savePath
):
os
.
makedirs
(
savePath
)
with
open
(
saveFile
,
'wb'
)
as
f
:
# 保存文件
f
.
write
(
obj
[
'content'
])
return
{
"uuid"
:
str
(
uuid
.
uuid4
()),
# 附件唯一编号
"filename"
:
obj
[
'filename'
],
# 附件名称
"filesize"
:
os
.
path
.
getsize
(
saveFile
),
# 附件大小
"filepath"
:
os
.
sep
.
join
([
relative_path
,
filename
])
.
replace
(
"
\\
"
,
"/"
),
# 附件存储路径
},
"upload file [
%
s] successfully!"
%
obj
[
'filename'
]
except
Exception
as
e
:
# repr(e)
traceback
.
print_exc
()
logger
.
error
(
str
(
e
))
return
None
,
repr
(
e
)
def
delete
(
self
,
data
):
try
:
isAccessed
,
path
=
checkPath
(
data
[
"path"
])
...
...
backend/deploy.py
View file @
c0dd2d99
import
os
import
sys
import
json
import
getopt
import
shutil
import
configparser
import
PySimpleGUI
as
sg
iniFilePath
=
os
.
path
.
join
(
os
.
getcwd
(),
"config.ini"
)
conf
=
configparser
.
ConfigParser
()
conf
.
read
(
iniFilePath
)
current_dir
=
os
.
getcwd
()
project_dir
=
os
.
path
.
dirname
(
current_dir
)
def
init_dirs
():
new_dirs
=
[
os
.
path
.
join
(
project_dir
,
"wwwroot"
),
os
.
path
.
join
(
project_dir
,
"wwwroot"
,
"kxpms"
),
os
.
path
.
join
(
project_dir
,
"wwwroot"
,
"kxpms"
,
conf
.
get
(
'uploads'
,
'upload_dir'
)),
os
.
path
.
join
(
project_dir
,
"wwwroot"
,
"kxpms"
,
conf
.
get
(
'uploads'
,
'netdisc'
))
]
for
d
in
new_dirs
:
if
not
os
.
path
.
exists
(
d
):
os
.
mkdir
(
d
)
def
update_app_config
():
upload_path
=
os
.
path
.
join
(
project_dir
,
"wwwroot"
,
"kxpms"
)
temp
=
os
.
path
.
join
(
os
.
getcwd
(),
"config1.ini"
)
# fd = open(temp, mode="w", encoding="utf-8")
# fd.close()
shutil
.
copy
(
iniFilePath
,
temp
)
cp2
=
configparser
.
ConfigParser
()
cp2
.
read
(
temp
)
sections
=
conf
.
sections
()
for
section
in
sections
:
for
item
in
conf
.
items
(
section
):
cp2
.
set
(
section
,
item
[
0
],
item
[
1
])
cp2
.
set
(
"uploads"
,
"upload_path"
,
upload_path
)
with
open
(
temp
,
"w+"
)
as
f
:
cp2
.
write
(
f
)
shutil
.
move
(
temp
,
iniFilePath
)
# os.remove(temp)
conf
.
read
(
iniFilePath
)
def
update_nginx_conf
():
source_file
=
os
.
path
.
join
(
current_dir
,
"nginx.conf.template"
)
target_file
=
os
.
path
.
join
(
project_dir
,
"nginx-1.18.0"
,
"conf"
,
"nginx.conf"
)
if
os
.
path
.
exists
(
target_file
):
os
.
remove
(
target_file
)
with
open
(
source_file
,
'r'
,
encoding
=
"utf8"
)
as
src
,
open
(
target_file
,
'w'
,
encoding
=
"utf8"
)
as
dst
:
lines
=
src
.
readlines
()
for
content
in
lines
:
if
content
.
find
(
" listen 80;"
)
!=
-
1
:
dst
.
write
(
" listen {};
\n
"
.
format
(
conf
.
get
(
'uploads'
,
'port'
)
or
80
))
elif
content
.
find
(
" server_name localhost;"
)
!=
-
1
:
dst
.
write
(
" server_name {};
\n
"
.
format
(
conf
.
get
(
'uploads'
,
'host'
)
or
"localhost"
))
elif
content
.
find
(
" root html;"
)
!=
-
1
:
dst
.
write
(
" root {};
\n
"
.
format
(
os
.
getcwd
()))
else
:
dst
.
write
(
content
)
print
(
target_file
,
source_file
)
# shutil.move(source_file, target_file)
def
install_nssm
(
app_name
,
app_path
):
return
os
.
system
(
"nssm.exe install {} {}"
.
format
(
app_name
,
app_path
))
# http://nssm.cc/usage
def
manage_nssm_service
(
app_name
,
cmd
):
'''
nssm start <servicename> 启动服务
nssm stop <servicename> 停止服务
nssm restart <servicename> 重启服务
nssm remove <servicename> 删除服务,需要确认
nssm remove <servicename> confirm 删除服务,无需确认
nssm status <servicename>
nssm statuscode <servicename>
nssm rotate <servicename> 服务日志文件滚动
nssm processes <servicename>
'''
services
=
[
'start'
,
'stop'
,
'restart'
,
'remove'
,
'status'
,
'processes'
]
if
cmd
not
in
services
:
return
False
return
os
.
system
(
"nssm.exe {} {}"
.
format
(
cmd
,
app_name
))
def
exec_nssm_env_cmd
(
app_name
,
param_dict
=
{}):
'''
nssm set <servicename> AppParameters -jar slave.jar -secret redacted 服务启动时携带的参数
nssm set <servicename> AppDirectory C:
\\
Jenkins 服务启动的文件路径
nssm set <servicename> AppStdout C:
\\
Jenkins
\\
jenkins.log 服务标准日志输出
nssm set <servicename> AppStderr C:
\\
Jenkins
\\
jenkins.log 服务错误日志输出
nssm set <servicename> AppStopMethodSkip 0 在崩溃后或服务正常停止时清理应用程序时使用的各种停止方法和超时
nssm set <servicename> AppStopMethodConsole 1000
nssm set <servicename> AppThrottle 5000 如果app运行时间少于5秒,延迟启动
'''
for
key
,
value
in
param_dict
.
items
():
res
=
os
.
system
(
"nssm.exe set {} {} {}"
.
format
(
app_name
,
key
,
value
))
print
(
res
)
def
start_nginx_service
():
'''
./nginx 启动
./nginx -s stop 停止
./nginx -s quit 退出
./nginx -s reload 重载
'''
nginx_dir
=
os
.
path
.
join
(
project_dir
,
"nginx-1.18.0"
,
"nginx.exe"
)
res
=
install_nssm
(
conf
.
get
(
'application'
,
'nginx'
),
nginx_dir
)
print
(
res
)
# exec_nssm_env_cmd(conf.get('application', 'nginx'), {
# 'AppParameters': '-s start'
# })
res
=
manage_nssm_service
(
conf
.
get
(
'application'
,
'nginx'
),
"start"
)
print
(
res
)
def
start_app_service
():
app_dir
=
os
.
path
.
join
(
current_dir
,
"start.exe"
)
res
=
install_nssm
(
conf
.
get
(
'application'
,
'name'
),
app_dir
)
print
(
res
)
exec_nssm_env_cmd
(
conf
.
get
(
'application'
,
'name'
),
{
'AppThrottle'
:
'5000'
})
res
=
manage_nssm_service
(
conf
.
get
(
'application'
,
'name'
),
"start"
)
print
(
res
)
def
start_service
():
start_nginx_service
()
start_app_service
()
def
stop_app_service
():
app_dir
=
os
.
path
.
join
(
current_dir
,
"start.exe"
)
res
=
install_nssm
(
conf
.
get
(
'application'
,
'name'
),
app_dir
)
print
(
res
)
exec_nssm_env_cmd
(
conf
.
get
(
'application'
,
'name'
),
{
'AppThrottle'
:
'5000'
})
res
=
manage_nssm_service
(
conf
.
get
(
'application'
,
'name'
),
"stop"
)
print
(
res
)
def
stop_nginx_service
():
nginx_dir
=
os
.
path
.
join
(
project_dir
,
"nginx-1.18.0"
,
"nginx.exe"
)
res
=
install_nssm
(
conf
.
get
(
'application'
,
'nginx'
),
nginx_dir
)
print
(
res
)
res
=
manage_nssm_service
(
conf
.
get
(
'application'
,
'nginx'
),
"start"
)
print
(
res
)
def
stop_service
():
stop_app_service
()
stop_nginx_service
()
def
set_nssm_env
():
if
sys
.
platform
==
'win32'
:
os
.
chdir
(
current_dir
)
start_service
()
else
:
# res = os.system("ls -a")
# print(res)
print
(
"暂不支持在非windows平台部署"
)
def
user_command
(
argv
):
flag
=
False
value
=
None
opts
,
args
=
getopt
.
getopt
(
argv
[
1
:],
"a:c:h"
,
[
"app="
,
"cmd="
,
"help"
])
for
opt_name
,
opt_value
in
opts
:
if
opt_name
in
(
'-h'
,
'--help'
):
print
(
'''
usage:
nssm start <servicename> 启动服务
nssm stop <servicename> 停止服务
nssm restart <servicename> 重启服务
nssm remove <servicename> 删除服务,需要确认
nssm remove <servicename> confirm 删除服务,无需确认
nssm status <servicename>
nssm statuscode <servicename>
nssm rotate <servicename> 服务日志文件滚动
nssm processes <servicename>
'''
)
sys
.
exit
()
if
opt_name
in
(
'-a'
,
'--app'
):
if
flag
==
False
:
flag
=
True
value
=
opt_value
else
:
res
=
manage_nssm_service
(
opt_value
,
value
)
if
res
:
print
(
res
)
else
:
print
(
"[*] unsupport command"
)
if
opt_name
in
(
'-c'
,
'--cmd'
):
if
flag
==
False
:
flag
=
True
value
=
opt_value
else
:
res
=
manage_nssm_service
(
value
,
opt_value
)
if
res
:
print
(
res
)
else
:
print
(
"[*] unsupport command"
)
print
(
argv
)
# =======================GUI==========================
start_text
=
"启动应用"
stop_text
=
"关闭应用"
restart_text
=
"重启应用"
start_btn
=
sg
.
Button
(
start_text
,
button_color
=
(
'white'
,
'springgreen4'
))
stop_btn
=
sg
.
Button
(
stop_text
,
button_color
=
(
'white'
,
'firebrick3'
))
restart_btn
=
sg
.
Button
(
restart_text
)
layout
=
[
[
start_btn
,
stop_btn
,
restart_btn
]
]
# Create the Window
window
=
sg
.
Window
(
'KXPMS项目管理系统'
,
layout
,
auto_size_buttons
=
False
,
default_button_element_size
=
(
15
,
3
))
def
start_project
():
update_app_config
()
init_dirs
()
update_nginx_conf
()
set_nssm_env
()
def
stop_project
():
stop_service
()
def
run
():
# Create the event loop
while
True
:
event
,
values
=
window
.
read
()
if
event
in
(
None
,
start_text
):
# User closed the Window or hit the Cancel button
start_project
()
elif
event
in
(
None
,
stop_text
):
stop_project
()
elif
event
in
(
None
,
restart_text
):
stop_project
()
start_project
()
else
:
continue
if
event
==
sg
.
WIN_CLOSED
:
break
print
(
f
'Event: {event}'
)
window
.
close
()
def
main
(
argv
):
if
len
(
argv
)
>
1
:
user_command
(
argv
)
from
datetime
import
datetime
from
operator
import
itemgetter
# 应用和数据分离
# 数据库文件备份在evm_app_store_files/epkdb
# 探测文件变化,定时备份到 epkdb
config
=
configparser
.
ConfigParser
()
config
.
read
(
os
.
path
.
join
(
os
.
getcwd
(),
"config.ini"
))
# 根据文件最后修改时间排序文件
def
getSortDir
(
path
):
lists
=
os
.
listdir
(
path
)
print
(
lists
)
lists
.
sort
(
key
=
lambda
fn
:
os
.
path
.
getmtime
(
path
+
'
\\
'
+
fn
))
filepath
=
os
.
path
.
join
(
path
,
lists
[
-
1
])
print
(
filepath
)
return
filepath
def
isFileChange
(
dt
):
f
=
os
.
sep
.
join
([
os
.
getcwd
(),
config
.
get
(
"database"
,
"filename"
)])
if
dt
:
return
dt
!=
int
(
os
.
path
.
getmtime
(
f
))
else
:
update_app_config
()
init_dirs
()
update_nginx_conf
()
set_nssm_env
()
return
int
(
os
.
path
.
getctime
(
f
))
!=
int
(
os
.
path
.
getmtime
(
f
))
def
backupDatabase
():
src
=
config
.
get
(
"database"
,
"filename"
)
dst
=
os
.
path
.
abspath
(
config
.
get
(
"uploads"
,
"upload_path"
))
dst
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
dst
,
config
.
get
(
"uploads"
,
"db_dir"
)]))
if
not
os
.
path
.
exists
(
dst
):
os
.
makedirs
(
dst
)
# 判断文件创建时间和修改时间是否一致,不一致则备份
shutil
.
copy
(
src
,
dst
)
src
=
os
.
sep
.
join
([
dst
,
src
])
dst
=
os
.
sep
.
join
([
dst
,
f
"{datetime.now().strftime('
%
Y
%
m
%
d
%
H
%
M
%
S')}-{config.get('database', 'filename')}"
])
os
.
rename
(
src
,
dst
)
def
removeExpiredFiles
():
path
=
os
.
path
.
abspath
(
config
.
get
(
"uploads"
,
"upload_path"
))
path
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
path
,
config
.
get
(
"uploads"
,
"db_dir"
)]))
if
not
os
.
path
.
exists
(
path
):
os
.
makedirs
(
path
)
file_count
=
len
(
os
.
listdir
(
path
))
if
file_count
>
10
:
file_list
=
getSortDir
(
path
)[:
-
10
]
for
f
in
file_list
:
shutil
.
remove
(
f
)
def
getModifyTime
():
result
=
{}
with
open
(
"./backupData.json"
,
"r+"
)
as
f
:
result
=
json
.
loads
(
f
.
read
())
return
result
def
saveMofidyTime
(
result
):
db
=
config
.
get
(
"database"
,
"filename"
)
result
[
"lastModifyDateTime"
]
=
int
(
os
.
path
.
getmtime
(
db
))
with
open
(
"./backupData.json"
,
"w+"
)
as
f
:
f
.
write
(
json
.
dumps
(
result
))
return
result
def
main
():
removeExpiredFiles
()
result
=
getModifyTime
()
if
isFileChange
(
result
[
"lastModifyDateTime"
]):
saveMofidyTime
(
result
)
backupDatabase
()
if
__name__
==
"__main__"
:
# main(sys.argv)
run
()
\ No newline at end of file
main
()
\ No newline at end of file
backend/deploy.sh
0 → 100644
View file @
c0dd2d99
#!/usr/bin/env bash
# 获取当前路径
Cur_Dir
=
$(
pwd
)
# 关闭evm_store
supervisorctl stop evm_store
# 切换到release分支
git checkout release
# 拉取最新代码
git pull
# 启动evm_store
supervisorctl start evm_store
# 启动一个定时任务
# cd $Cur_Dir
# source venv/bin/activate
# 0 */1 * * * "${Cur_Dir}/venv/bin/python deploy.py"
backend/model/user.py
View file @
c0dd2d99
...
...
@@ -13,7 +13,7 @@ class User(db.Entity):
_table_
=
"{}"
.
format
(
config
[
'TABLE_PREFIX'
])
+
"user"
id
=
PrimaryKey
(
int
,
auto
=
True
)
uuid
=
Required
(
uuid
.
UUID
,
unique
=
True
,
default
=
uuid
.
uuid1
,
index
=
True
)
role
=
Required
(
str
,
default
=
"
USER"
)
# 角色
role
=
Required
(
str
,
default
=
"
community"
)
# 角色,管理员[administrator]、企业用户[enterprise]、社区用户[community]
account
=
Required
(
str
,
unique
=
True
)
# 账号
username
=
Required
(
str
,
max_len
=
100
)
# 用户名
password
=
Required
(
str
,
max_len
=
64
)
# 密码
...
...
backend/restart.json
deleted
100644 → 0
View file @
57c0f668
{
"count"
:
84
}
\ No newline at end of file
backend/run.sh
0 → 100644
View file @
c0dd2d99
#!/usr/bin/env bash
source
venv/bin/activate
python start.py
\ No newline at end of file
backend/schema/apps.py
View file @
c0dd2d99
...
...
@@ -5,11 +5,10 @@ from marshmallow import fields, validate, RAISE, INCLUDE, EXCLUDE
class
AddSchema
(
BaseSchema
):
app_name
=
fields
.
String
(
required
=
True
)
app_version
=
fields
.
String
(
required
=
False
)
app_icon
=
fields
.
Dict
(
required
=
True
)
app_url
=
fields
.
String
(
required
=
False
)
category
=
fields
.
String
(
required
=
False
)
app_desc
=
fields
.
String
(
required
=
False
)
app_files
=
fields
.
List
(
fields
.
Dict
,
required
=
False
)
category
=
fields
.
String
(
required
=
False
)
logo
=
fields
.
Raw
(
required
=
False
)
fileList
=
fields
.
List
(
fields
.
Raw
,
required
=
False
)
sort
=
fields
.
Int
(
required
=
False
,
default
=
0
)
class
Meta
:
...
...
@@ -18,11 +17,8 @@ class AddSchema(BaseSchema):
class
UpdateSchema
(
BaseSchema
):
app_name
=
fields
.
String
(
required
=
False
)
app_version
=
fields
.
String
(
required
=
False
)
app_icon
=
fields
.
Dict
(
required
=
True
)
app_url
=
fields
.
String
(
required
=
False
)
category
=
fields
.
String
(
required
=
False
)
app_desc
=
fields
.
String
(
required
=
False
)
app_files
=
fields
.
List
(
fields
.
Dict
,
required
=
False
)
category
=
fields
.
String
(
required
=
False
)
sort
=
fields
.
Int
(
required
=
False
)
class
Meta
:
...
...
backend/utils/epk.py
View file @
c0dd2d99
...
...
@@ -61,15 +61,11 @@ class EpkApp(object):
self
.
_appName
=
appName
self
.
_appDir
=
os
.
path
.
abspath
(
appDir
)
self
.
algorithm
=
algorithm
print
(
sys
.
argv
)
print
(
appName
)
print
(
appDir
)
print
(
self
.
_appDir
)
self
.
_appVersion
=
appVersion
self
.
_appCRCCode
=
None
self
.
_files
=
[]
self
.
_infoPath
=
os
.
sep
.
join
([
self
.
_appDir
,
"
%
s.json"
%
self
.
_appName
])
self
.
_epksDir
=
o
s
.
sep
.
join
([
os
.
getcwd
(),
output
])
self
.
_epksDir
=
o
utput
if
not
os
.
path
.
exists
(
self
.
_epksDir
):
fs
.
open_fs
(
os
.
getcwd
())
.
makedirs
(
output
)
self
.
_epkName
=
os
.
sep
.
join
([
self
.
_epksDir
,
"
%
s.epk"
%
self
.
_appName
])
...
...
@@ -100,10 +96,9 @@ class EpkApp(object):
fpath
=
"C:/
%
s"
%
jspath
.
info
.
name
fname
=
jspath
.
info
.
name
fsize
=
jspath
.
info
.
size
fbasename
=
jspath
.
info
.
name
.
split
(
"."
)[
0
]
fext
=
jspath
.
info
.
name
.
split
(
"."
)[
1
]
fbasename
,
fext
=
os
.
path
.
splitext
(
jspath
.
info
.
name
)
if
fext
in
[
"exe"
,
"dll"
,
"nv"
,
"conf"
]:
if
fext
in
[
"
"
,
"
exe"
,
"dll"
,
"nv"
,
"conf"
]:
continue
finfo
=
{
...
...
@@ -115,7 +110,6 @@ class EpkApp(object):
}
if
self
.
_infoPath
==
os
.
sep
.
join
([
path
,
fname
]):
print
(
finfo
)
files
.
insert
(
0
,
finfo
)
else
:
files
.
append
(
finfo
)
...
...
@@ -126,12 +120,9 @@ class EpkApp(object):
return
files
def
header
(
self
,
epk_start
=
0xAAAA
,
md5_offset
=
0
,
file_count
=
0
):
bytes_header
=
struct
.
pack
(
"<HLH"
,
epk_start
,
md5_offset
,
file_count
)
return
bytes_header
def
fileMD5
(
self
,
info
):
md5path
=
os
.
sep
.
join
([
self
.
_appDir
,
"
%
s.md5"
%
info
[
"basename"
]])
fpath
=
os
.
sep
.
join
([
self
.
_appDir
,
info
[
"name"
]])
...
...
@@ -158,7 +149,6 @@ class EpkApp(object):
md5
=
hashlib
.
md5
()
#获取一个md5加密算法对象
md5
.
update
(
content
)
#指定需要加密的字符串
newmd5
=
md5
.
hexdigest
()
#获取加密后的16进制字符串
print
(
"md5 == "
,
newmd5
)
content
=
self
.
sign
(
newmd5
)
ret
=
b
""
...
...
@@ -172,7 +162,6 @@ class EpkApp(object):
fpath
=
os
.
sep
.
join
([
self
.
_appDir
,
fname
])
fext
=
info
[
"ext"
]
fileBytes
=
b
""
if
fext
==
"md5"
:
fileBytes
+=
struct
.
pack
(
"<B"
,
1
)
...
...
@@ -185,8 +174,6 @@ class EpkApp(object):
fileBytes
+=
struct
.
pack
(
"<
%
ds"
%
len
(
_name
),
fname
.
encode
(
"utf-8"
))
with
open
(
fpath
,
"rb"
)
as
fc
:
fileContentBytes
=
fc
.
read
()
print
(
info
[
"name"
])
print
(
len
(
fileContentBytes
))
fileBytes
+=
struct
.
pack
(
"<L"
,
len
(
fileContentBytes
))
if
fext
==
"md5"
:
...
...
@@ -194,14 +181,8 @@ class EpkApp(object):
else
:
fileCompressBytes
=
self
.
compress
()(
fileContentBytes
,
level
)
print
(
"==="
,
fileCompressBytes
[
0
])
print
(
fileCompressBytes
)
fileBytes
+=
struct
.
pack
(
"<L"
,
len
(
fileCompressBytes
))
print
(
fileBytes
)
fileBytes
+=
fileCompressBytes
return
fileBytes
def
pack
(
self
,
level
=
9
):
...
...
@@ -217,23 +198,15 @@ class EpkApp(object):
for
info
in
infos
[
"files"
]:
epkFileContentBytes
+=
self
.
packFile
(
info
)
epkFileContentLength
=
len
(
epkFileContentBytes
)
epkFileBytes
+=
self
.
header
(
md5_offset
=
8
+
epkFileContentLength
,
file_count
=
file_count
)
epkFileBytes
+=
epkFileContentBytes
epkmd5Bytes
=
self
.
md5
(
epkFileBytes
)
epkFileBytes
+=
struct
.
pack
(
"<H"
,
len
(
epkmd5Bytes
))
epkFileBytes
+=
epkmd5Bytes
crcBytes
=
zlib
.
crc32
(
epkFileBytes
)
epkFileBytes
+=
struct
.
pack
(
"<L"
,
crcBytes
)
f
.
write
(
epkFileBytes
)
ret
=
{
...
...
backend/view/annex.py
View file @
c0dd2d99
...
...
@@ -12,7 +12,7 @@ from fullstack.validation import validate_schema
from
fullstack.response
import
ResponseCode
,
response_result
from
schema.annex
import
AddSchema
,
DeleteSchema
,
QuerySchema
,
UpdateSchema
,
ResponseSchema
logger
=
logging
.
getLogger
(
"annexApi"
)
logger
=
logging
.
getLogger
(
__name__
)
annex_api
=
Blueprint
(
"annex_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/annex"
%
config
[
'NAME'
])
...
...
backend/view/api.py
View file @
c0dd2d99
...
...
@@ -2,13 +2,14 @@
# -*- coding: utf_8 -*-
import
os
import
json
import
datetime
import
logging
import
traceback
import
uuid
from
datetime
import
datetime
from
flask
import
Blueprint
,
request
,
redirect
,
url_for
,
json
,
Response
,
send_file
,
make_response
,
send_from_directory
from
werkzeug.utils
import
secure_filename
from
app
import
config
,
signalManager
from
app.setting
import
conf
from
fullstack.login
import
Auth
...
...
@@ -16,10 +17,13 @@ from fullstack.response import ResponseCode, response_result
from
fullstack.validation
import
validate_schema
from
schema.api
import
UpdatePasswordSchema
,
ApplicationBuildSchema
logger
=
logging
.
getLogger
(
"api"
)
logger
=
logging
.
getLogger
(
__name__
)
api
=
Blueprint
(
"api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s"
%
config
[
'NAME'
])
logger
.
info
(
config
.
get
(
"UPLOAD_PATH"
))
logger
.
info
(
os
.
path
.
abspath
(
config
.
get
(
"UPLOAD_PATH"
)))
def
stopApp
():
fpath
=
os
.
sep
.
join
([
os
.
getcwd
(),
"restart.json"
])
with
open
(
fpath
,
"w+"
)
as
f
:
...
...
@@ -47,11 +51,45 @@ def update_password():
@
api
.
route
(
"/upload"
,
methods
=
[
'POST'
])
# 上传文件
def
upload_file
():
try
:
result
,
message
=
signalManager
.
actionUploadFile
.
emit
()
if
result
:
return
response_result
(
ResponseCode
.
OK
,
data
=
result
,
msg
=
message
)
else
:
result
=
None
message
=
None
binfile
=
request
.
files
.
get
(
"binfile"
)
if
not
binfile
:
return
response_result
(
ResponseCode
.
REQUEST_ERROR
,
msg
=
message
)
obj
=
dict
()
obj
[
'filename'
]
=
binfile
.
filename
obj
[
'content'
]
=
binfile
.
stream
.
read
()
dtNowString
=
datetime
.
now
()
.
strftime
(
"
%
Y
%
m
%
d
%
H
%
M
%
S
%
f"
)
# 文件名构成:文件名_时间日期.文件后缀
filename
=
os
.
path
.
splitext
(
obj
[
'filename'
])[
0
]
+
"_{}"
.
format
(
dtNowString
)
+
os
.
path
.
splitext
(
obj
[
'filename'
])[
-
1
]
# 获取相对路径
relative_path
=
os
.
sep
.
join
([
config
.
get
(
"TEMP_DIR"
),
dtNowString
])
# 获取最终存储的绝对路径
savePath
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
config
.
get
(
"UPLOAD_PATH"
),
relative_path
]))
# 获取最终存储的文件路径
saveFile
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
savePath
,
filename
]))
if
not
os
.
path
.
exists
(
savePath
):
os
.
makedirs
(
savePath
)
with
open
(
saveFile
,
'wb'
)
as
f
:
# 保存文件
f
.
write
(
obj
[
'content'
])
result
=
{
"uuid"
:
str
(
uuid
.
uuid4
()),
# 附件唯一编号
"filename"
:
obj
[
'filename'
],
# 附件名称
"filesize"
:
os
.
path
.
getsize
(
saveFile
),
# 附件大小
"filepath"
:
os
.
sep
.
join
([
config
.
get
(
"UPLOAD_DIR"
),
relative_path
,
filename
])
.
replace
(
"
\\
"
,
"/"
),
# 附件存储路径
},
"upload file [
%
s] successfully!"
%
obj
[
'filename'
]
return
response_result
(
ResponseCode
.
OK
,
data
=
result
)
except
Exception
as
e
:
traceback
.
print_exc
()
logger
.
error
(
str
(
e
))
...
...
@@ -79,7 +117,6 @@ def application_build():
os
.
makedirs
(
upload_path
)
for
f
in
request
.
files
.
getlist
(
'binfiles'
):
filename
=
secure_filename
(
f
.
filename
)
print
(
filename
)
file_path
=
os
.
sep
.
join
([
upload_path
,
filename
])
f
.
save
(
file_path
)
files
.
append
(
file_path
)
...
...
backend/view/app_logs.py
View file @
c0dd2d99
...
...
@@ -12,7 +12,7 @@ from fullstack.validation import validate_schema
from
fullstack.response
import
ResponseCode
,
response_result
from
schema.app_logs
import
AddSchema
,
DeleteSchema
,
QuerySchema
,
UpdateSchema
,
ResponseSchema
logger
=
logging
.
getLogger
(
"appLogsApi"
)
logger
=
logging
.
getLogger
(
__name__
)
appLogs_api
=
Blueprint
(
"appLogs_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/appLogs"
%
config
[
'NAME'
])
...
...
backend/view/apps.py
View file @
c0dd2d99
...
...
@@ -2,10 +2,13 @@
# -*- coding: utf_8 -*-
import
os
import
json
import
datetime
import
logging
import
traceback
from
datetime
import
datetime
from
flask
import
Blueprint
,
request
from
werkzeug.utils
import
secure_filename
from
app
import
config
,
signalManager
from
fullstack.login
import
Auth
from
fullstack.validation
import
validate_schema
...
...
@@ -13,7 +16,7 @@ from fullstack.response import ResponseCode, response_result
from
schema.apps
import
AddSchema
,
DeleteSchema
,
QuerySchema
,
UpdateSchema
from
schema.build_logs
import
AddSchema
as
LogAddScheme
,
QuerySchema
as
LogQuerySchema
logger
=
logging
.
getLogger
(
"appsApi"
)
logger
=
logging
.
getLogger
(
__name__
)
apps_api
=
Blueprint
(
"apps_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/apps"
%
config
[
'NAME'
])
...
...
@@ -22,8 +25,48 @@ apps_api = Blueprint("apps_api", __name__, url_prefix="/api/v1/%s/apps" % config
@
Auth
.
auth_required
def
add
():
try
:
params
=
request
.
schema_data
dtNowString
=
datetime
.
now
()
.
strftime
(
"
%
Y
%
m
%
d
%
H
%
M
%
S"
)
# 获取相对路径
dirname
=
"{}-{}-{}-{}"
.
format
(
params
[
"app_name"
],
params
[
"app_version"
],
params
[
"category"
],
dtNowString
)
relative_path
=
os
.
sep
.
join
([
config
.
get
(
"EPK_DIR"
),
dirname
])
# 获取最终存储的绝对路径
upload_path
=
os
.
path
.
normpath
(
os
.
sep
.
join
([
config
.
get
(
"UPLOAD_PATH"
),
relative_path
]))
if
not
os
.
path
.
exists
(
upload_path
):
os
.
makedirs
(
upload_path
)
files
=
[]
logo
=
request
.
files
.
get
(
"logo"
)
if
logo
:
filename
=
secure_filename
(
logo
.
filename
)
file_path
=
os
.
sep
.
join
([
upload_path
,
filename
])
file_path
=
os
.
path
.
normpath
(
file_path
)
logo
.
save
(
file_path
)
params
.
update
({
"app_icon"
:
file_path
})
fileList
=
request
.
files
.
getlist
(
'fileList'
)
if
fileList
:
upload_path
=
os
.
sep
.
join
([
upload_path
,
"src"
])
if
not
os
.
path
.
exists
(
upload_path
):
os
.
mkdir
(
upload_path
)
for
f
in
fileList
:
filename
=
secure_filename
(
f
.
filename
)
file_path
=
os
.
sep
.
join
([
upload_path
,
filename
])
file_path
=
os
.
path
.
normpath
(
file_path
)
f
.
save
(
file_path
)
files
.
append
(
file_path
)
# obj = dict()
# obj['filename'] = binfile.filename
# obj['content'] = binfile.stream.read()
params
.
update
({
"fileList"
:
files
,
"epk_path"
:
upload_path
})
user
=
request
.
current_user
.
get
(
"id"
)
isSuccess
,
message
=
signalManager
.
actionAddApp
.
emit
(
user
,
request
.
schema_data
)
isSuccess
,
message
=
signalManager
.
actionAddApp
.
emit
(
user
,
params
)
if
isSuccess
:
return
response_result
(
ResponseCode
.
OK
,
msg
=
message
)
else
:
...
...
@@ -33,7 +76,6 @@ def add():
logger
.
error
(
str
(
e
))
return
response_result
(
ResponseCode
.
SERVER_ERROR
,
msg
=
str
(
e
))
@
apps_api
.
route
(
"/delete/<uuid:id>"
,
methods
=
[
'POST'
])
@
Auth
.
auth_required
def
delete
(
id
):
...
...
@@ -49,7 +91,6 @@ def delete(id):
logger
.
error
(
str
(
e
))
return
response_result
(
ResponseCode
.
SERVER_ERROR
)
@
apps_api
.
route
(
"/get"
,
methods
=
[
"POST"
])
@
validate_schema
(
QuerySchema
)
@
Auth
.
auth_required
...
...
@@ -82,7 +123,6 @@ def get_list():
logger
.
error
(
str
(
e
))
return
response_result
(
ResponseCode
.
SERVER_ERROR
)
@
apps_api
.
route
(
"/update/<uuid:id>"
,
methods
=
[
'POST'
])
@
validate_schema
(
UpdateSchema
)
@
Auth
.
auth_required
...
...
backend/view/device.py
View file @
c0dd2d99
...
...
@@ -12,7 +12,7 @@ from fullstack.validation import validate_schema
from
fullstack.response
import
ResponseCode
,
response_result
from
schema.device
import
AddSchema
,
DeleteSchema
,
QuerySchema
,
UpdateSchema
logger
=
logging
.
getLogger
(
"deviceApi"
)
logger
=
logging
.
getLogger
(
__name__
)
device_api
=
Blueprint
(
"device_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/device"
%
config
[
'NAME'
])
...
...
backend/view/download.py
View file @
c0dd2d99
...
...
@@ -12,7 +12,7 @@ from fullstack.validation import validate_schema
from
fullstack.response
import
ResponseCode
,
response_result
from
schema.download
import
AddSchema
,
DeleteSchema
,
QuerySchema
,
UpdateSchema
,
DownloadSchema
logger
=
logging
.
getLogger
(
"DownloadApi"
)
logger
=
logging
.
getLogger
(
__name__
)
download_api
=
Blueprint
(
"download_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/download"
%
config
[
'NAME'
])
...
...
backend/view/files.py
View file @
c0dd2d99
...
...
@@ -9,21 +9,15 @@ import tempfile
import
shutil
import
base64
import
logging
from
hashlib
import
md5
as
fmd5
from
flask
import
Blueprint
,
request
,
redirect
,
url_for
,
json
from
app.setting
import
config
if
((
3
,
0
)
<=
sys
.
version_info
<=
(
3
,
10
)):
from
hashlib
import
md5
as
fmd5
elif
((
2
,
0
)
<=
sys
.
version_info
<=
(
2
,
10
)):
import
md5
fmd5
=
md5
.
new
logger
=
logging
.
getLogger
(
"filesApi"
)
logger
=
logging
.
getLogger
(
__name__
)
file_api
=
Blueprint
(
"file_api"
,
__name__
,
url_prefix
=
"/api/v1/file"
)
FileStoragePath
=
os
.
path
.
join
(
config
.
get
(
"UPLOAD_PATH"
)
,
config
.
get
(
"NETDISC"
)
)
FileStoragePath
=
os
.
path
.
join
(
config
.
get
(
"UPLOAD_PATH"
))
def
ajaxCheckAcess
(
path
):
realpath
=
os
.
path
.
realpath
(
path
)
...
...
backend/view/login.py
View file @
c0dd2d99
...
...
@@ -9,7 +9,7 @@ from fullstack.validation import validate_schema
from
fullstack.response
import
ResponseCode
,
response_result
from
schema.login
import
LoginSchema
,
RegisterSchema
logger
=
logging
.
getLogger
(
"loginApi"
)
logger
=
logging
.
getLogger
(
__name__
)
login_api
=
Blueprint
(
"login_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/login"
%
config
[
'NAME'
])
...
...
backend/view/netdisc.py
View file @
c0dd2d99
...
...
@@ -13,7 +13,7 @@ from fullstack.response import ResponseCode, response_result
from
schema.netdisc
import
AddSchema
,
DeleteSchema
,
QuerySchema
,
UpdateSchema
from
utils
import
random_string
logger
=
logging
.
getLogger
(
"netdiscApi"
)
logger
=
logging
.
getLogger
(
__name__
)
netdisc_api
=
Blueprint
(
"netdisc_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/netdisc"
%
config
[
'NAME'
])
...
...
backend/view/user.py
View file @
c0dd2d99
...
...
@@ -10,7 +10,7 @@ from fullstack.validation import validate_schema
from
fullstack.response
import
ResponseCode
,
response_result
from
schema.user
import
AddSchema
,
DeleteSchema
,
UpdateSchema
,
QuerySchema
,
ResponseSchema
logger
=
logging
.
getLogger
(
"userApi"
)
logger
=
logging
.
getLogger
(
__name__
)
user_api
=
Blueprint
(
"user_api"
,
__name__
,
url_prefix
=
"/api/v1/
%
s/user"
%
config
[
'NAME'
])
...
...
frontend/src/views/system/apps.vue
View file @
c0dd2d99
...
...
@@ -8,9 +8,9 @@
>
</el-form>
<el-table
:data=
"list"
v-loading=
"isLoading"
element-loading-text=
"Loading"
:data=
"list"
size=
"mini"
border
stripe
...
...
@@ -32,11 +32,6 @@
label=
"应用类别"
width=
"120"
></el-table-column>
<el-table-column
prop=
"app_url"
label=
"应用路径"
width=
"120"
></el-table-column>
<el-table-column
prop=
"epk_size"
label=
"应用大小"
...
...
@@ -137,13 +132,6 @@
autocomplete=
"off"
></el-input>
</el-form-item>
<el-form-item
label=
"应用路径"
prop=
"app_url"
>
<el-input
type=
"text"
v-model=
"post.app_url"
autocomplete=
"off"
></el-input>
</el-form-item>
<el-form-item
label=
"应用类别"
prop=
"category"
>
<el-input
type=
"text"
...
...
@@ -161,12 +149,15 @@
<el-form-item
label=
"应用Logo"
prop=
"app_icon"
>
<el-upload
class=
"avatar-uploader"
ref=
"icon"
:action=
"`${window.location.protocol}//${window.location.host}/api/v1/evm_store/upload`"
name=
"binfile"
:on-remove=
"handleAvatarRemove"
:on-success=
"handleAvatarSuccess"
:before-upload=
"beforeAvatarUpload"
ref=
"logo"
name=
"logo"
accept=
"image/*"
action=
"null"
:auto-upload=
"false"
:http-request=
"handleUploadLogo"
:on-remove=
"handleLogoRemove"
:on-change=
"handleLogoChange"
:before-upload=
"beforeLogoUpload"
>
<img
v-if=
"imageUrl"
:src=
"imageUrl"
class=
"avatar"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
...
...
@@ -175,12 +166,13 @@
<el-form-item
label=
"应用文件"
prop=
"app_files"
>
<el-upload
drag
ref=
"upload"
:action=
"`${window.location.protocol}//${window.location.host}/api/v1/evm_store/upload`"
:on-remove=
"handleRemove"
:on-success=
"handleUploadSuccess"
multiple
name=
"binfile"
ref=
"upload"
name=
"binfiles"
action=
"null"
:auto-upload=
"false"
:http-request=
"handleUploadFile"
:on-remove=
"handleUploadRemove"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
...
...
@@ -228,7 +220,6 @@ export default {
imageUrl
:
""
,
total
:
0
,
list
:
[],
fileList
:
[],
isLoading
:
false
,
form
:
{
uuid
:
null
,
...
...
@@ -245,10 +236,11 @@ export default {
app_name
:
"
evue_launcher
"
,
app_version
:
"
1.0
"
,
app_icon
:
null
,
app_url
:
"
evue_launcher
"
,
category
:
"
tools
"
,
app_desc
:
"
启动器
"
,
app_files
:
[],
logo
:
null
,
fileList
:
[],
},
};
},
...
...
@@ -261,7 +253,7 @@ export default {
this
.
post
.
app_icon
=
null
;
this
.
post
.
app_files
=
[];
this
.
$refs
.
upload
.
clearFiles
();
this
.
$refs
.
icon
.
clearFiles
();
this
.
$refs
.
logo
.
clearFiles
();
},
fetchData
(
params
)
{
this
.
isLoading
=
true
;
...
...
@@ -271,7 +263,8 @@ export default {
this
.
list
=
res
.
data
.
map
((
item
)
=>
{
if
(
item
.
app_build_log
&&
item
.
app_build_log
.
app_info
)
item
.
epk_size
=
(
item
.
app_build_log
.
app_info
.
buff_length
/
1024
).
toFixed
(
2
)
+
"
KB
"
;
(
item
.
app_build_log
.
app_info
.
buff_length
/
1024
).
toFixed
(
2
)
+
"
KB
"
;
else
item
.
epk_size
=
""
;
return
item
;
});
...
...
@@ -292,21 +285,22 @@ export default {
this
.
fetchData
(
mapTrim
(
this
.
form
));
},
handleRebuild
(
index
,
row
)
{
console
.
log
(
index
)
rebuildApp
({
uuid
:
row
.
uuid
}).
then
(
res
=>
{
// download(`${res.data.app_name}.epk`, res.data.app_path)
this
.
$message
.
success
(
res
.
message
)
}).
catch
(
err
=>
{
this
.
$message
.
error
(
err
.
message
)
rebuildApp
({
uuid
:
row
.
uuid
})
.
then
((
res
)
=>
{
this
.
$message
.
success
(
res
.
message
);
})
.
catch
((
err
)
=>
{
this
.
$message
.
error
(
err
.
message
);
});
},
handleBuild
(
index
,
row
)
{
console
.
log
(
index
)
getBuildApp
(
row
.
uuid
).
then
((
res
)
=>
{
download
(
`
${
res
.
data
.
app_name
}
.epk`
,
res
.
data
.
app_path
)
this
.
$message
.
success
(
res
.
message
)
}).
catch
((
err
)
=>
{
this
.
$message
.
error
(
err
.
message
)
getBuildApp
(
row
.
uuid
)
.
then
((
res
)
=>
{
download
(
`
${
res
.
data
.
app_name
}
.epk`
,
res
.
data
.
app_path
);
this
.
$message
.
success
(
res
.
message
);
})
.
catch
((
err
)
=>
{
this
.
$message
.
error
(
err
.
message
);
});
},
handleEdit
(
index
,
row
)
{
...
...
@@ -342,68 +336,82 @@ export default {
}
);
},
handleUploadSuccess
(
res
)
{
if
(
res
.
code
==
200
)
this
.
post
.
app_files
.
push
(
res
.
data
);
},
handleAvatarSuccess
(
res
,
file
)
{
if
(
res
.
code
==
200
)
this
.
post
.
app_icon
=
res
.
data
;
this
.
imageUrl
=
URL
.
createObjectURL
(
file
.
raw
);
handleUploadLogo
(
file
)
{
this
.
post
.
logo
=
file
;
},
beforeAvatarUpload
()
{
// const isJPG = file.type === "image/jpeg";
// const isLt2M = file.size / 1024 / 1024
<
2
;
// if (!isJPG) {
// this.$message.error("上传头像图片只能是 JPG 格式!");
// }
// if (!isLt2M) {
// this.$message.error("上传头像图片大小不能超过 2MB!");
// }
// return isJPG && isLt2M;
return
true
;
handleUploadFile
(
file
)
{
this
.
post
.
fileList
.
push
(
file
);
},
handleAvatarRemove
(
file
)
{
console
.
log
(
file
);
this
.
imageUrl
=
null
;
},
handleRemove
(
file
)
{
handleUploadRemove
(
file
,
fileList
)
{
console
.
log
(
file
,
fileList
);
for
(
let
i
=
0
;
i
<
this
.
post
.
app_files
.
length
;
i
++
)
{
if
(
this
.
post
.
app_files
[
i
].
uuid
==
file
.
response
.
data
.
uuid
)
{
this
.
post
.
app_files
.
splice
(
i
,
1
);
break
;
}
}
console
.
log
(
file
)
;
// this.post.app_files = fileList
;
},
handleFrameworkRemove
()
{},
handleFrameworkSuccess
(
res
)
{
this
.
framework
.
assets
.
files
.
push
(
res
.
data
);
handleLogoChange
(
file
)
{
this
.
imageUrl
=
URL
.
createObjectURL
(
file
.
raw
);
},
beforeLogoUpload
(
file
)
{
const
isLt2M
=
file
.
size
/
1024
/
1024
<
2
;
if
(
!
isLt2M
)
{
this
.
$message
.
error
(
"
上传头像图片大小不能超过 2MB!
"
);
}
return
isLt2M
;
},
handleLogoRemove
(
file
)
{
console
.
log
(
file
);
this
.
imageUrl
=
null
;
this
.
post
.
logo
=
file
.
file
;
},
submitForm
(
formName
)
{
this
.
$refs
[
formName
].
validate
((
valid
)
=>
{
let
result
=
true
;
if
(
valid
)
{
if
(
this
.
dialogTitle
===
"
添加
"
)
addApp
(
mapTrim
(
this
.
post
))
.
then
((
res
)
=>
{
console
.
log
(
res
);
this
.
$message
({
type
:
"
success
"
,
message
:
"
添加成功
"
});
if
(
this
.
dialogTitle
===
"
添加
"
)
{
this
.
$refs
.
upload
.
submit
();
// 调用这个upload组件该方法才会执行http-request回调
this
.
$refs
.
logo
.
submit
();
let
formData
=
new
FormData
();
this
.
post
.
fileList
.
forEach
(
item
=>
{
formData
.
append
(
"
fileList
"
,
item
.
file
)
});
formData
.
append
(
"
logo
"
,
this
.
post
.
logo
.
file
)
Object
.
keys
(
this
.
post
).
forEach
(
k
=>
{
if
(
this
.
post
[
k
]
&&
typeof
this
.
post
[
k
]
!==
"
object
"
)
{
formData
.
append
(
k
,
this
.
post
[
k
])
}
});
addApp
(
formData
).
then
((
res
)
=>
{
this
.
$message
({
type
:
"
success
"
,
message
:
`添加成功:
${
res
.
message
}
`
,
});
this
.
fetchData
(
mapTrim
(
this
.
form
));
})
.
catch
((
err
)
=>
{
this
.
$message
.
error
(
err
.
message
);
});
else
if
(
this
.
dialogTitle
===
"
编辑
"
)
}
else
if
(
this
.
dialogTitle
===
"
编辑
"
)
{
updateApp
(
this
.
currentValue
.
uuid
,
this
.
post
)
.
then
((
res
)
=>
{
console
.
log
(
res
);
// this.$set(this.list, this.currentIndex, Object.assign(this.currentValue, tmp))
this
.
$message
({
type
:
"
success
"
,
message
:
"
更新成功
"
});
this
.
$message
({
type
:
"
success
"
,
message
:
`更新成功:
${
res
.
message
}
`
,
});
this
.
fetchData
(
mapTrim
(
this
.
form
));
})
.
catch
((
err
)
=>
{
this
.
$message
.
error
(
err
.
message
);
});
}
}
else
{
result
=
false
;
}
...
...
@@ -412,12 +420,10 @@ export default {
});
},
onAdd
()
{
setTimeout
(()
=>
{
this
.
clear
();
},
100
)
this
.
post
.
sort
=
this
.
form
.
pagesize
*
(
this
.
form
.
pagenum
-
1
)
+
this
.
list
.
length
+
1
this
.
dialogTitle
=
"
添加
"
this
.
dialogVisible
=
true
setTimeout
(()
=>
{
this
.
clear
();
},
100
);
this
.
post
.
sort
=
this
.
form
.
pagesize
*
(
this
.
form
.
pagenum
-
1
)
+
this
.
list
.
length
+
1
;
this
.
dialogTitle
=
"
添加
"
;
this
.
dialogVisible
=
true
;
},
onSubmit
()
{
this
.
form
.
pagenum
=
1
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment