diff --git a/README.md b/README.md index f5367bf867938f078111223fbb0790f760175c8e..125257eb0c0a0f7f604055e6befd273ab3caa9bf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -centos安装命令:wget http://file.kwebapp.cn/sh/install/intapp/kcwebplus.sh && bash kcwebplus.sh -tar zcvf lkmall.chengliao.com.tar.gz lkmall.chengliao.com -scp -r /www/lkmall.chengliao.com.tar.gz 47.97.115.105:/www/ \ No newline at end of file +

linuxlinux集成运维应用

+ +kcweb作为web开发而设计的高性能框架,采用全新的架构思想,注重易用性。遵循MIT开源许可协议发布,意味着个人和企业可以免费使用kcweb,甚至允许把你基于kcweb开发的应用开源或商业产品发布或销售。 + +[完整文档](https://intapp.kwebapp.cn/intapp/doc/index/finddoc/5/27/1 "文档") \ No newline at end of file diff --git a/app/common/__init__.py b/app/common/__init__.py index 5609cbcea36920e562477f5cbb74b3b4cb2625e8..76817a776991075da2bc28ce2c2ade7dfc6f8a75 100644 --- a/app/common/__init__.py +++ b/app/common/__init__.py @@ -83,6 +83,7 @@ def serlogin(username,sign,timestamp,random,types="session"): else: account_token=md5(str(username)+str(inifo['password'])) set_cache(account_token,inifo,86400) + G.userinfo=inifo return True,0,"登录成功",account_token def check_role(): t=request.getroutecomponent() @@ -97,7 +98,7 @@ def check_role(): break if not status: if 'GET' == request.HEADER.Method(): - return response.tpl("/common/html/error.html",title="无权访问",content="抱歉...,您当前没有此页面访问权限,请联系管理员",imgsrc=config.domain['kcwebimg']+"/icon/suo.png",status="401") + return response.tpl("/common/html/error.html",title="无权访问",content="抱歉...,您当前没有此页面访问权限,请联系管理员",imgsrc=config.domain['kcwebimg']+"/icon/suo.png",status="401 error") else: return errorjson(msg="您没有以下接口访问权限,可联系管理员申请。\r\n"+ts,status="401") def check_login(): @@ -121,10 +122,41 @@ def before_request(): 进行登录验证,权限验证 """ if not config.app['cli']: + G.setadminlog="" return check_login() -def after_request(): +def after_request(body,status,resheader): "响应拦截" - pass + if status=='200 ok': + if G.userinfo: #记录操作日志 + method=request.HEADER.Method() + if method!="GET": + t=request.getroutecomponent() + modular=t[1] + plug=t[2] + controller=t[3] + function=t[4] + routeparam=json_encode(list(t[5])) + t1=request.HEADER.URL().split("?") + if len(t1)>1: + getparam="?"+t1[1:][0] + else: + getparam="" + dataparam=request.get_data() + sqlite("admin_log",model_app_path).insert({ + "user_id":G.userinfo['id'], + "title":G.setadminlog, + "method":method, + "modular":modular, + "plug":plug, + "controller":controller, + "function":function, + "routeparam":routeparam, + "getparam":getparam, + "dataparam":dataparam, + "addtime":times() + }) + G.setadminlog="" + G.userinfo=None def return_list(lists,count,pagenow,pagesize): """返回分页列表 diff --git a/app/common/html/login.html b/app/common/html/login.html index 9f7c7517503f41a20ab7b1259486091bff0b9364..6c061bc249bcbc3bce22b359f5feb9796ff28343 100644 --- a/app/common/html/login.html +++ b/app/common/html/login.html @@ -66,7 +66,7 @@ var vm = new Vue({ timestamp= Date.parse(new Date())/1000; random=md5('feafwefasas'+timestamp) sign=md5(self.username+md5('kcw'+self.password)+timestamp+random) - self.get("/index/index/index/login/"+self.username+"/"+sign+"/"+timestamp+"/"+random,{},'登录中...').then(function(res){ + self.post("/index/index/index/login/"+self.username+"/"+sign+"/"+timestamp+"/"+random,{},'登录中...').then(function(res){ if(res.code==0){ location.reload() } diff --git a/app/common/model.py b/app/common/model.py index 44947a409cec030dda9e8713d062dd8f43035ffb..a52aead3c1eaeb9b346403291310bc09424c6596 100644 --- a/app/common/model.py +++ b/app/common/model.py @@ -47,7 +47,28 @@ except: model_admins=model_app_admin() model_admins.create_table() sqlite("admin",model_app_path).insert({"username":"kcw","password":md5("kcw"+str(password)),"phone":"","nickname":"kcw-linux控制板","name":"","role":1,"logintime":times(),"addtime":times()}) - +class model_app_admin_log(modelsqliteintapp): + "管理员操作日志" + table="admin_log" + fields={ + "id":model.dbtype.int(LEN=11,PRI=True,A_L=True), #设置id为自增主键 + "user_id":model.dbtype.int(LEN=11,DEFAULT=0), #用户id(管理员id) + "title":model.dbtype.varchar(LEN=32,DEFAULT=''), #日志标题 + "method":model.dbtype.varchar(LEN=8,DEFAULT='GET'), #请求类型 + "modular":model.dbtype.varchar(LEN=32,DEFAULT=''), #请求模块 + "plug":model.dbtype.varchar(LEN=32,DEFAULT=''), #请求插件 + "controller":model.dbtype.varchar(LEN=32,DEFAULT=''), #请求控制器 + "function":model.dbtype.varchar(LEN=32,DEFAULT=''), #请求控制器方法 + "routeparam":model.dbtype.varchar(LEN=11,DEFAULT=''), #路由参数 + "getparam":model.dbtype.varchar(LEN=64,DEFAULT=''), #GET参数 + "dataparam":model.dbtype.text(), #body参数 + "addtime":model.dbtype.int(LEN=11,DEFAULT=0) #添加时间 + } +try: + sqlite('admin_log',model_app_path).find() +except: + model_app_admin_log=model_app_admin_log() + model_app_admin_log.create_table() class model_intapp_menu(modelsqliteintapp): "顶部和左边菜单 表" table="menu" diff --git a/app/config/app.py b/app/config/app.py index af79eb967ba660e852f8ebafa312808afadbda19..b962468415a19ddfd73e3879014738a2a9382364 100644 --- a/app/config/app.py +++ b/app/config/app.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- from .database import * -app['app_debug']=False #是否开启调试模式 +app['app_debug']=True #是否开启调试模式 app['tpl_folder']='./app' #设置模板文件目录名 注意:所有的配置目录都是以您的运行文件所在目录开始 app['before_request']='before_request' #设置请求前要执行的函数名 app['after_request']='after_request' #设置请求后要执行的函数名 @@ -41,7 +41,7 @@ route['defmodular']='intapp' #默认模块 当url不包括模块名时 route['defplug']='index' #默认插件 当url不包括插件名时 route['files']='index' #默认路由文件(控制器) 当url不包括控制器名时 route['funct']='index' #默认路由函数 (操作方法) 当url不包括操作方法名时 -route['methods']=['POST','GET'] #默认请求方式 +route['methods']=['POST','GET','DELETE','PUT'] #默认请求方式 diff --git a/app/index/controller/index/index.py b/app/index/controller/index/index.py index a4fb861361f1f817008ff12a681de238118b0743..9c4abe37d64c25c43c7703b54cada17231e3d430 100644 --- a/app/index/controller/index/index.py +++ b/app/index/controller/index/index.py @@ -19,6 +19,7 @@ def get_account_token(username,sign,timestamp,random,types="get_account_token"): return errorjson(code=code,msg=msg) def login(username,sign,timestamp,random,types="session"): "登录" + G.setadminlog=username+",登录系统" status,code,msg,account_token=serlogin(username,sign,timestamp,random,types) if status: return successjson(data=account_token,msg=msg) diff --git a/app/intapp/controller/index/admin.py b/app/intapp/controller/index/admin.py index d2b4fee2bb08ecc42bec31ea562bda93d51e8092..50615aa83c641b46df6c0494c813b6cabba6fb9e 100644 --- a/app/intapp/controller/index/admin.py +++ b/app/intapp/controller/index/admin.py @@ -4,11 +4,65 @@ def index(): return response.tpl("../tplm/admin/index") else: return response.tpl() +def admin(): + if sysisphone(): + return response.tpl("../tplm/admin/admin") + else: + return response.tpl() def role(): if sysisphone(): return response.tpl("../tplm/admin/role") else: return response.tpl() +def adminlog(): + if sysisphone(): + return response.tpl("../tplm/admin/adminlog") + else: + return response.tpl() +def logdeta(id): + "日志明细" + data=sqlite("admin_log t1",model_app_path).field("t1.*,t2.icon,t2.name,t2.phone").join("admin t2","t1.user_id=t2.id","LEFT").where("t1.id",id).find() + data['routeparamarr']=json_decode(data['routeparam']) + data['dataparamarr']=json_decode(data['dataparam']) + return successjson(data) +def loglist(): + "日志列表" + where="1=1" + kw=request.args.get('kw') + types=request.args.get('types') + method=request.args.get('method') + pagenow=request.args.get('pagenow') + pagesize=request.args.get('pagesize') + if kw: + where+=" and t2."+types+" like '%"+kw+"%'" + if method: + where+=" and method='"+method+"'" + if not pagenow: + pagenow=1 + else: + pagenow=int(pagenow) + if not pagesize: + pagesize=10 + else: + pagesize=int(pagesize) + lists=sqlite("admin_log t1",model_app_path).order("t1.id desc").field("t1.*,t2.icon,t2.name,t2.phone").join("admin t2","t1.user_id=t2.id","LEFT").where(where).page(pagenow,pagesize).select() + count=sqlite("admin_log t1",model_app_path).join("admin t2","t1.user_id=t2.id","LEFT").where(where).count() + data=return_list(lists,count,pagenow,pagesize) + return successjson(data) +def deletelog(id=0): + "删除日志" + G.setadminlog="删除日志" + if id: + sqlite("admin_log",model_app_path).where('id',id).delete() + return successjson() + else: + try: + id=request.get_json() + sqlite("admin_log",model_app_path).where('id','in',id).delete() + except: + return errorjson(msg="失败") + else: + return successjson() def getpluglist(modular="intapp"): "本地插件列表" path="app/"+modular+"/controller/" @@ -29,6 +83,7 @@ def getpluglist(modular="intapp"): i+=1 return successjson(data) def dellogin(): + G.setadminlog="退出所有会话" shutil.rmtree(config.session['path']) return successjson() def getlist(id=0): @@ -54,6 +109,7 @@ def getlist(id=0): data=return_list(lists,count,pagenow,pagesize) return successjson(data) def insert(): + G.setadminlog="添加管理员" try: data=request.get_json() if not data['username'] or not data['password']: @@ -66,6 +122,7 @@ def insert(): return successjson() def delete(id=0): "批量删除" + G.setadminlog="删除管理员" if id: sqlite("admin",model_app_path).where('id',id).delete() return successjson() @@ -81,6 +138,7 @@ def delete(id=0): return successjson() def update(id=0): "更新内容" + G.setadminlog="修改管理员" data=request.get_json() if not id: id=data['id'] @@ -96,6 +154,7 @@ def update(id=0): return successjson() def setpwd(): "设置管理员登录密码" + G.setadminlog="设置管理员登录密码" data=request.get_json() try: sqlite("admin",model_app_path).where("id",data['id']).update({'password':data['password']}) @@ -105,6 +164,7 @@ def setpwd(): return successjson() def setmypwd(): """设置自己的登录密码""" + G.setadminlog="设置自己的登录密码" data=request.get_json() try: sqlite("admin",model_app_path).where("id",G.userinfo['id']).update({'password':data['password']}) @@ -137,6 +197,7 @@ def getrolelist(id=0): data=return_list(lists,count,pagenow,pagesize) return successjson(data) def insertrole(): + G.setadminlog="添加角色" try: data=request.get_json() data.update(updtime=times(),addtime=times()) @@ -148,6 +209,7 @@ def insertrole(): return successjson() def updaterole(id=0): "更新内容" + G.setadminlog="修改角色权限" data=request.get_json() if not id: id=data['id'] @@ -164,6 +226,7 @@ def updaterole(id=0): return successjson() def deleterole(): "批量删除" + G.setadminlog="删除角色" try: id=request.get_json() try: diff --git a/app/intapp/controller/index/index.py b/app/intapp/controller/index/index.py index cd231a5b88cb9fcc811d1f7dadea8ac3357fc431..8adf3acfcfe1f0ab0cc8e88e32bdd084f4f7d4d3 100644 --- a/app/intapp/controller/index/index.py +++ b/app/intapp/controller/index/index.py @@ -122,15 +122,19 @@ def shell(): shellstr=request.args.get("shellstr") if shellstr: os.system(shellstr) + G.setadminlog="执行命令:"+shellstr else: data=request.get_json() os.system(data['shell']) + G.setadminlog="执行命令:"+data['shell'] return successjson() def reboot(types='app'): "重启" if types=='app': + G.setadminlog="重启应用" shellstr="bash server.sh" else: + G.setadminlog="重启服务器" shellstr="reboot" os.system(shellstr) return successjson() \ No newline at end of file diff --git a/app/intapp/controller/index/menu.py b/app/intapp/controller/index/menu.py index 652280694cbc9dbc60b4ea5964b89c165a71200f..23a34ebb22bce00bd79265d273b44c18d847c0d6 100644 --- a/app/intapp/controller/index/menu.py +++ b/app/intapp/controller/index/menu.py @@ -27,6 +27,7 @@ def menulist(pid=0): return successjson(data) def menuupdate(id=0): "更新内容" + G.setadminlog="修改菜单" data=request.get_json() if not id: id=data['id'] @@ -36,6 +37,7 @@ def menuupdate(id=0): return errorjson(msg="参数不全") def menudelete(): "批量删除" + G.setadminlog="删除菜单" id=request.get_json() idstr="0" for k in id: @@ -43,6 +45,7 @@ def menudelete(): sqlite("menu",model_app_path).where("id in ("+idstr+")").delete() return successjson() def menuinsert(): + G.setadminlog="添加菜单" data=request.get_json() if is_index(data,'id'): del data['id'] diff --git a/app/intapp/controller/index/modular.py b/app/intapp/controller/index/modular.py index c2b24990c8d89ffcaeaa710dd33483cf2ac6c929..5b9969749a810d288ed24923f1db22a42112c79f 100644 --- a/app/intapp/controller/index/modular.py +++ b/app/intapp/controller/index/modular.py @@ -61,6 +61,7 @@ def modular_list(kw='',pagenow=1): def uploadmodular(): "打包模块上传" + G.setadminlog="打包模块上传模块" kcwebuserinfo=file_get_content(kcwebuserinfopath+str(G.userinfo['id'])) if kcwebuserinfo: kcwebuserinfo=json_decode(kcwebuserinfo) @@ -78,6 +79,7 @@ def uploadmodular(): return errorjson("请先配置kcweb账号") def installmodular(): "安装模块" + G.setadminlog="安装模块" arr=request.get_json() server=create("app",arr['name']) data=server.installmodular(arr['token']) @@ -89,6 +91,7 @@ def installmodular(): return errorjson(msg=data[1]) def uninstallmodular(): "卸载模块" + G.setadminlog="卸载模块" arr=request.get_json() server=create("app",arr['name']) data=server.uninstallmodular() diff --git a/app/intapp/controller/index/plan.py b/app/intapp/controller/index/plan.py index 1dbad6d2aa856682393db2884b1907508d01b9a4..dce77e1c9c54992593d7c9548daaa8d3abab5558 100644 --- a/app/intapp/controller/index/plan.py +++ b/app/intapp/controller/index/plan.py @@ -28,6 +28,7 @@ def get(id=0): data['strconfig']=json_decode(file_get_content(indexconfigpath+"strconfig")) return successjson(data) def add(): + G.setadminlog="添加计划任务" "添加任务" if sqlite("interval").count() >=100: return errorjson(code=1,msg="您已超过系统预设最大限制") @@ -50,6 +51,7 @@ def add(): return successjson(msg="添加成功,重启后生效") def delpl(): "删除计划" + G.setadminlog="删除计划任务" id=request.get_json() sqlite("interval").where('id','in',id).delete() return successjson(msg="任务已删除,重启后生效") @@ -59,6 +61,7 @@ def log(iden): def setconfig(types='set',paths='strconfig'): if types=='set': + G.setadminlog="保存配置" data=request.get_json() file_set_content(indexconfigpath+paths,json_encode(data)) return successjson(data) diff --git a/app/intapp/controller/index/plug.py b/app/intapp/controller/index/plug.py index 4589076a4eec45c157a75e483ef7488a50d651c6..cb91d9fbb54c9aadd633ea28224a0d5b160b9338 100644 --- a/app/intapp/controller/index/plug.py +++ b/app/intapp/controller/index/plug.py @@ -67,6 +67,7 @@ def plug_list(modular="intapp",pagenow=1,group=''): def uploadplug(): "打包插件上传" + G.setadminlog="打包插件上传" kcwebuserinfo=file_get_content(kcwebuserinfopath+str(G.userinfo['id'])) if kcwebuserinfo: kcwebuserinfo=json_decode(kcwebuserinfo) @@ -90,6 +91,7 @@ def uploadplug(): return errorjson(msg="请先配置kcweb账号") def installplug(): "安装或更新插件" + G.setadminlog="安装或更新插件" arr=request.get_json() #备份插件文稿数据 dirname="app/"+arr['modular']+"/controller/"+arr['name']+"/common/file" @@ -142,6 +144,7 @@ def installplug(): def uninstallplug(): "卸载插件" + G.setadminlog="卸载插件" arr=request.get_json() #备份插件文稿数据 dirname="app/"+arr['modular']+"/controller/"+arr['name']+"/common/file" diff --git a/app/intapp/controller/index/pub.py b/app/intapp/controller/index/pub.py index bfbd2ae6cfae3b48c6607165b5c5a9818a73c995..bb1d152b1adf884c6e09d3f87a5e8dfa02d5968d 100644 --- a/app/intapp/controller/index/pub.py +++ b/app/intapp/controller/index/pub.py @@ -5,6 +5,7 @@ def before_request(): def checkserver(): return successjson() def outlogin(): + G.setadminlog="退出系统" account_token=request.args.get("account_token") if account_token: del_cache(account_token) @@ -13,6 +14,7 @@ def outlogin(): return successjson() def get_account_token(username,sign,timestamp,random,types="get_account_token"): "获取用户token" + G.setadminlog="获取用户token" status,code,msg,account_token=serlogin(username,sign,timestamp,random,types) if status: return successjson(data={"account_token":account_token},msg=msg) @@ -20,6 +22,7 @@ def get_account_token(username,sign,timestamp,random,types="get_account_token"): return errorjson(code=code,msg=msg) def login(username,sign,timestamp,random,types="session"): "登录" + G.setadminlog="登录系统" status,code,msg,account_token=serlogin(username,sign,timestamp,random,types) if status: return successjson(data=account_token,msg=msg) @@ -58,6 +61,7 @@ def gitpull(): Queues.insert(target=PUBLICOther.gitpull,args=(path,shell),title=title,describes="执行命令:"+shell) shell='git pull' Queues.insert(target=PUBLICOther.gitpull,args=(path,shell),title=title,describes="执行命令:"+shell) + G.setadminlog="执行命令:"+shell return successjson("命令已添加到任务队列中") class PUBLICOther(): def gitpull(path,shell): diff --git a/app/intapp/controller/index/role.txt b/app/intapp/controller/index/role.txt index 9add180e0264d63722c38ef7ea3faf715bc7c11b..4bbe3061daf21117b66dc573c59ffb3614af8760 100644 --- a/app/intapp/controller/index/role.txt +++ b/app/intapp/controller/index/role.txt @@ -8,7 +8,13 @@ cpu和内存以及网络,/intapp/index/index/cpume shell执行能力,/intapp/index/index/shell 重启,/intapp/index/index/reboot -管理员页面,/intapp/index/admin/index +管理员入口,/intapp/index/admin/index +管理员页面,/intapp/index/admin/admin +权限页面,/intapp/index/admin/role +操作日志页面,/intapp/index/admin/adminlog +日志列表,/intapp/index/admin/loglist +日志明细,/intapp/index/admin/logdeta +删除日志,/intapp/index/admin/deletelog 路由列表,/intapp/index/admin/getpluglist 管理员列表,/intapp/index/admin/getlist 添加管理员,/intapp/index/admin/insert @@ -16,11 +22,11 @@ shell执行能力,/intapp/index/index/shell 编辑管理员,/intapp/index/admin/update 设置管理员密码,/intapp/index/admin/setpwd 设置自己的密码,/intapp/index/admin/setmypwd -权限页面,/intapp/index/admin/role 角色列表,/intapp/index/admin/getrolelist 添加角色,/intapp/index/admin/insertrole 更新角色,/intapp/index/admin/updaterole 删除角色,/intapp/index/admin/deleterole +退出所有会话,/intapp/index/admin/dellogin 导航页面,/intapp/index/menu/index 导航列表,/intapp/index/menu/menulist diff --git a/app/intapp/controller/index/setup.py b/app/intapp/controller/index/setup.py index 0aa83a584873307b8ccbbd0e88208e9595497394..51265e75d553031e81d1718238f83ae47d0b4bd6 100644 --- a/app/intapp/controller/index/setup.py +++ b/app/intapp/controller/index/setup.py @@ -31,6 +31,7 @@ def pythonrun(): return response.tpl() def restart(types='stop'): "启动/停止项目管理" + G.setadminlog="启动/停止项目管理" data=request.get_json() interpreter=md5(data['paths']+data['types']+data['filename']+data['other']) #解释器 if types=='start': @@ -61,6 +62,7 @@ def restart(types='stop'): return successjson() def setpythonrun(): "设置/添加项目管理" + G.setadminlog="设置/添加项目管理" if 'Linux' in get_sysinfo()['platform']: data=request.get_json() @@ -105,12 +107,14 @@ def setpythonrun(): return errorjson(msg="不支持该系统,当前只支持linux") def logpythonrun(id): "项目管理日志" + G.setadminlog="项目管理日志" arr=sqlite("pythonrun").where('id',id).find() interpreter=md5(arr['paths']+arr['types']+arr['filename']+arr['other']) #解释器 data=file_get_content(arr['paths']+"/"+interpreter+".log") return successjson(data) def delpythonrun(id=''): "删除项目管理" + G.setadminlog="删除项目管理" try: if id: id=[id] @@ -157,6 +161,7 @@ def pythonrulists(id=''): return successjson(data) def setbaseconfig(types='get'): "保存配置信息" + if types=='get': if os.path.isfile("app/common/file/config.conf"): data=json_decode(file_get_content("app/common/file/config.conf")) @@ -166,12 +171,14 @@ def setbaseconfig(types='get'): data={} return successjson(data) else: + G.setadminlog="保存配置信息" config=request.get_json() file_set_content("app/common/file/config.conf",json_encode(config)) return successjson(msg="保存成功") def addstart(): "添加启动项" + G.setadminlog="添加启动项" data=request.get_json() if sqlite("start").connect(model_app_path).where("value",data['value']).count(): return errorjson(msg="禁止重复添加") @@ -184,6 +191,7 @@ def addstart(): else: return errorjson(msg="添加失败,该系统支不支持") def delstart(): + G.setadminlog="删除启动项" data=request.get_json() if system_start.del_Boot_up(cmd=data['value'],id=data['id']): return successjson() @@ -267,6 +275,7 @@ def aliyunossdownload(types=""): return successjson() def backup(types=''): "备份全部" + G.setadminlog="备份全部" paths=request.args.get("paths") if paths: #备份目录 app/common/file shutil.copytree(paths,"backup/"+paths) @@ -311,6 +320,7 @@ def backup(types=''): return successjson(msg="所有文稿备份成功") def recovery(): "恢复文稿" + G.setadminlog="恢复文稿" paths=request.args.get("paths") if paths: #恢复指定目录 app/common/file shutil.copytree("backup/"+paths,paths) @@ -329,6 +339,7 @@ def recovery(): return errorjson(msg="备份目录不存在") def download(name=""): "下载备份文件" + G.setadminlog="下载备份文件" if os.path.exists("backup"): zip.packzip("backup","backup.zip") f=open("backup.zip","rb") @@ -340,6 +351,7 @@ def download(name=""): return "没有备份文件,请备份文件后再下载" def postsup(): "上传备份文件" + G.setadminlog="上传备份文件" if request.binary.save('file',"backup."+request.binary.filesuffix('file')): zip.unzip_file("backup.zip","backup") os.remove("backup.zip") @@ -348,10 +360,12 @@ def postsup(): return errorjson(msg="上传失败") def dowfile(name=''): "下载指定文件" + G.setadminlog="下载指定文件" pathname=request.args.get("pathname") return response.download(pathname) def uploadfile(): "上传文件导指定目录" + G.setadminlog="上传文件导指定目录" pathname=request.args.get("pathname") if request.binary.save('file',pathname): return successjson() @@ -359,6 +373,7 @@ def uploadfile(): return errorjson(msg="上传失败") def backxz(name=''): "压缩指定文件夹并下载" + G.setadminlog="压缩指定文件夹并下载" paths=request.args.get("paths") zip.packzip(paths,"backxz.zip") f=open("backxz.zip","rb") @@ -368,6 +383,7 @@ def backxz(name=''): return body,"200 ok",{"Content-Type":"application/zip","Accept-Ranges":"bytes"} def upunback(): "上传zip压缩包并解压指定文件夹" + G.setadminlog="上传zip压缩包并解压指定文件夹" paths=request.args.get("paths") if request.binary.save('file',"backxz."+request.binary.filesuffix('file')): try: diff --git a/app/intapp/controller/index/tpl/admin/admin.html b/app/intapp/controller/index/tpl/admin/admin.html new file mode 100644 index 0000000000000000000000000000000000000000..52c5c770b650bfe83b491992c96df5465a21bae4 --- /dev/null +++ b/app/intapp/controller/index/tpl/admin/admin.html @@ -0,0 +1,263 @@ + + + + +kcwebplus + + + + + + + + + + + + + + + + + + + +
+
+    + + + 搜索 + 添加管理员账户 + + + 清除所有会话 + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+    删除选中  + + +
+
+ +
+ + + + + + + 选择图片 + + + + + + + + + + + + + + + + {{item.title}} + + + + + 取 消 + 修改 + 添加 + +
+
+
+ + + diff --git a/app/intapp/controller/index/tpl/admin/adminlog.html b/app/intapp/controller/index/tpl/admin/adminlog.html new file mode 100644 index 0000000000000000000000000000000000000000..20b2e38b4a02081a13d4c9f419986f218304e0bf --- /dev/null +++ b/app/intapp/controller/index/tpl/admin/adminlog.html @@ -0,0 +1,238 @@ + + + + +kcwebplus + + + + + + + + + + + + + + + + + + + + + + +
+
+    + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+    删除选中  + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
用户头像
操作用户{{deta.name}}
用户手机{{deta.phone}}
操作名称{{deta.title}}
操作类型 + 删除操作(DELETE) + 更新操作(PUT) + 提交操作(POST) + 获取操作(GET) + {{deta.method}} +
路由/{{deta.modular}}/{{deta.plug}}/{{deta.controller}}/{{deta.function}} + /{{item}} + {{deta.getparam}} +
post参数 +
+

+                    
+
+
+
+
+ + + diff --git a/app/intapp/controller/index/tpl/admin/index.html b/app/intapp/controller/index/tpl/admin/index.html index d1fe2c7f552ff7cf76d87b9631d8f4fe76a6f648..887f9517db9374df61bb16f892c68ac0a4530c2f 100644 --- a/app/intapp/controller/index/tpl/admin/index.html +++ b/app/intapp/controller/index/tpl/admin/index.html @@ -1,5 +1,6 @@ + kcwebplus @@ -19,131 +20,49 @@ + - -
-
-    - - - 搜索 - 添加管理员账户 - - - 角色管理 - 清除所有会话 - - -
-
- - - - - - - - - - - - - - - - - - - - - - - -
-    删除选中  - - +
+ + 管理员列表 + 角色管理 + 操作日志 + +
+ +
+
+
+ +
+ +
+
- - - - - - - - 选择图片 - - - - - - - - - - - - - - - - {{item.title}} - - - - - - 取 消 - 修改 - 添加 - -
- + \ No newline at end of file diff --git a/app/intapp/controller/index/tpl/admin/role.html b/app/intapp/controller/index/tpl/admin/role.html index 30637bd14ce4ff1d656c40409f063cf41d9527a3..9d7b39a66d88a67f47ebc9c4ba915793b58728a5 100644 --- a/app/intapp/controller/index/tpl/admin/role.html +++ b/app/intapp/controller/index/tpl/admin/role.html @@ -64,10 +64,7 @@
- + @@ -75,7 +72,7 @@ -
+
{{item1.name}} @@ -85,8 +82,8 @@ 取 消 - 修改 - 添加 + 修改角色 + 添加角色
@@ -160,7 +157,7 @@ var vm = new Vue({ for(var i=0;i { - self.get("/intapp/index/admin/dellogin").then(function(res){ + self.delete("/intapp/index/admin/dellogin").then(function(res){ self.$notify({type: 'success',message: '所有用户已退出!'}); setTimeout(function(){ top.location.reload(); @@ -195,14 +195,14 @@ function setimgmt(domain,paths,item){ }, setpwd:function(){ var self=this; - self.post('/intapp/index/admin/setpwd',{'id':self.items.id,password:md5('kcw'+self.password)},'设置中').then(function(res){ + self.put('/intapp/index/admin/setpwd',{'id':self.items.id,password:md5('kcw'+self.password)},'设置中').then(function(res){ self.$notify({type: 'success',message: '您设置的新密码是: ' + self.password}); self.show=false;self.settabbarheight(70) }) }, update:function(){ var self=this - self.post("/intapp/index/admin/update",self.items,"更新中").then(function(res){ + self.put("/intapp/index/admin/update",self.items,"更新中").then(function(res){ self.show1=false;self.settabbarheight(70) self.$notify({type: 'success',message: '更新成功'}); }) @@ -247,7 +247,7 @@ function setimgmt(domain,paths,item){ message: '确定要删除该管理员', }) .then(() => { - self.get("/intapp/index/admin/delete/"+id,null,'正在删除').then(function(res){ + self.delete("/intapp/index/admin/delete/"+id,null,'正在删除').then(function(res){ self.data.pagenow=1 self.getlist() }) diff --git a/app/intapp/controller/index/tplm/index/index.html b/app/intapp/controller/index/tplm/index/index.html index 13241bd64a33e215b45e5fec4c312083415cd7e4..4d188b6ea4d2f8347d50d363f9e8f21a7b8a90b5 100644 --- a/app/intapp/controller/index/tplm/index/index.html +++ b/app/intapp/controller/index/tplm/index/index.html @@ -341,7 +341,7 @@ function topgethtml(url,title,icon){ }, outlogin:function(){ self=this - self.get('/intapp/index/pub/outlogin',null,'正在退出').then(function(res){ + self.delete('/intapp/index/pub/outlogin',null,'正在退出').then(function(res){ if(res.code==0){ location.reload() } diff --git a/app/intapp/controller/index/tplm/modular/index.html b/app/intapp/controller/index/tplm/modular/index.html index aa0313c40a80d0cce3fc04022e2ffb16db516a7d..e5da9f1ee79977fc4928fdc6863eb7f7eee43638 100644 --- a/app/intapp/controller/index/tplm/modular/index.html +++ b/app/intapp/controller/index/tplm/modular/index.html @@ -179,7 +179,7 @@ title: '提示', message: '确定要卸载该模块', }).then(function(){ - self.post("/intapp/index/modular/uninstallmodular/",item,'正在卸载模块,请稍后...').then(function(res){ + self.delete("/intapp/index/modular/uninstallmodular/",item,'正在卸载模块,请稍后...').then(function(res){ item.status=0 self.$notify({message: "卸载成功",type: 'success'}); }) diff --git a/app/intapp/controller/index/tplm/plug/index.html b/app/intapp/controller/index/tplm/plug/index.html index a3e4b254c8505be1c4e1d9d25b23eb7a9680fdc4..7a7da04b377662bf49a9bead3cb962a3a8364330 100644 --- a/app/intapp/controller/index/tplm/plug/index.html +++ b/app/intapp/controller/index/tplm/plug/index.html @@ -186,7 +186,7 @@ title: '提示', message: '确定要卸载该模块', }).then(function(){ - self.post("/intapp/index/plug/uninstallplug/",item,'正在卸载模块,请稍后...').then(function(res){ + self.delete("/intapp/index/plug/uninstallplug/",item,'正在卸载模块,请稍后...').then(function(res){ item.status=0 self.$notify({message: "卸载成功",type: 'success'}); }) diff --git a/app/intapp/controller/index/tplm/setup/bacrecpage.html b/app/intapp/controller/index/tplm/setup/bacrecpage.html index 36c4bb1989c4b5e39fad6c53636c42297c7e96a7..3190616a81f6040c890a2811fbdb626c173fb0e1 100644 --- a/app/intapp/controller/index/tplm/setup/bacrecpage.html +++ b/app/intapp/controller/index/tplm/setup/bacrecpage.html @@ -100,7 +100,7 @@ title: '警告', message: '该操作会还原系统备份文稿,是否继续', }).then(function(){ - self.get("/intapp/index/setup/aliyunossdownload",{filepath:filepath},"正在恢复...").then(function(res){ + self.put("/intapp/index/setup/aliyunossdownload?filepath="+filepath,{},"正在恢复...").then(function(res){ self.$notify({message: res.msg,type: 'success'}); }) }).catch(function(){}); @@ -116,7 +116,7 @@ title: '警告', message: '该操作会还原mysql备份数据,是否继续', }).then(function(){ - self.get("/intapp/soft/mysql/recovery/whole/1/"+edition,{db:filepath},"正在恢复...").then(function(res){ + self.put("/intapp/soft/mysql/recovery/whole/1/"+edition+"?db="+filepath,{},"正在恢复...").then(function(res){ self.$notify({message: res.msg,type: 'success'}); }) }).catch(function(){}); @@ -138,7 +138,7 @@ }, backup:function(dirname){ var self=this; - self.get("/intapp/index/setup/backup",{dirname:dirname},'正在备份').then(function(res){ + self.post("/intapp/index/setup/backup?dirname="+dirname,{},'正在备份').then(function(res){ if(res.code==0){ self.$notify({message:res.msg,type: 'success'}); }else if(res.code==1){ @@ -146,7 +146,7 @@ title: '温馨提示', message: res.msg, }).then(function(){ - self.get("/intapp/index/setup/backup",{dirname:dirname,qzx:1}).then(function(res){ + self.post("/intapp/index/setup/backup?dirname="+dirname+"&qzx=1",{}).then(function(res){ if(res.code==0){ self.$notify({message:res.msg,type: 'success'}); }else if(res.code==1){ @@ -158,7 +158,7 @@ }) },recovery:function(dirname){ var self=this; - self.get("/intapp/index/setup/recovery",{dirname:dirname},'正在恢复').then(function(res){ + self.put("/intapp/index/setup/recovery?dirname="+dirname,{},'正在恢复').then(function(res){ if(res.code==0){ self.$notify({message:res.msg,type: 'success'}); }else if(res.code==1){ diff --git a/app/intapp/controller/index/tplm/setup/pythonrun.html b/app/intapp/controller/index/tplm/setup/pythonrun.html index 50df67920401087013f911f17fc02918765e8a1a..24e7474b1d3df74d0ec75993f4bc67a4b0870012 100644 --- a/app/intapp/controller/index/tplm/setup/pythonrun.html +++ b/app/intapp/controller/index/tplm/setup/pythonrun.html @@ -258,7 +258,7 @@ function setfile(paths,item){ title: '删除提醒', message: '此操作将永久删除该记录, 是否继续?', }).then(function(){ - self.post("/intapp/index/setup/delpythonrun/"+id,null,"正在删除中...").then(function(res){ + self.delete("/intapp/index/setup/delpythonrun/"+id,null,"正在删除中...").then(function(res){ self.data.pagenow=1 self.getlist() self.$notify({type: 'success',message: '选中记录已删除!'}); diff --git a/app/intapp/controller/index/tplm/setup/startpage.html b/app/intapp/controller/index/tplm/setup/startpage.html index b3f6ac70b7e6a11aaf6f61f54ddd173db72ada75..d03c53210f112573422f3a26980a1c59fc1f573b 100644 --- a/app/intapp/controller/index/tplm/setup/startpage.html +++ b/app/intapp/controller/index/tplm/setup/startpage.html @@ -136,12 +136,12 @@ function setimgmt(domain,paths,item){ title: '警告', message: '这是系统添加的启动项,确定要删除', }).then(function(){ - self.post("/intapp/index/setup/delstart",item,"请稍后...").then(function(res){ + self.delete("/intapp/index/setup/delstart",item,"请稍后...").then(function(res){ self.obtain() }) }).catch(function(){}); }else{ - self.post("/intapp/index/setup/delstart",item,"请稍后...").then(function(res){ + self.delete("/intapp/index/setup/delstart",item,"请稍后...").then(function(res){ self.obtain() }) } diff --git a/app/static/js/function.js b/app/static/js/function.js index 29e6de1d2d77cbafd7287e747eca5d85aa4853b4..2937bea6ce2131186413715686f058d65e62f8f6 100644 --- a/app/static/js/function.js +++ b/app/static/js/function.js @@ -192,6 +192,39 @@ Vue.prototype.put=function(url,params,text){ }) }) } +Vue.prototype.update=function(url,params,text){ + self=this + if(text){ + var Loading = self.$loading({lock: true,text: text,spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.7)'}); + } + return new Promise(function(resolve,reject) { + axios_instance.update(url,params) + .then(function(res) { + if(text){setTimeout(function(){Loading.close();},100)} + if(res.data.code==0){ + resolve(res.data); + }else{ + self.$message({message: res.data.msg,type: 'error'}); + } + }) + .catch(function(err) { + if(text){setTimeout(function(){Loading.close();},100)} + if (err.response) { + if (err.response.data.hasOwnProperty('msg')){ + msg=err.response.data.msg + }else{ + msg=err.response.data + } + self.$message({message: "错误码:"+err.response.status+","+msg,type: 'error'}); + }else if (err.request){ + self.$message({message: "无法链接到服务器",type: 'error'}); + }else{ + self.$message({message: "网络异常,",type: 'error'}); + } + reject(err) + }) + }) +} //get请求 获取内容 Vue.prototype.getcontent=function(url,text,data){ diff --git a/kcweb/README.md b/kcweb/README.md index 7dee6dd9b198d69f9dc93c34c6ad9647cf5e8914..e3f3a9c856c65da3904f5190344f28ea4aacf057 100644 --- a/kcweb/README.md +++ b/kcweb/README.md @@ -1,66 +1,20 @@ -完整文档请参考:http://intapp.kwebapp.cn/index/index/doc/docde/1 -#### 创建应用 -- 新建一个server.py文件,内容如下,执行python3 server.py创建应用 -- 如下面的代码创建了一个app应用,同时在app应用下创建了一个api模块 -```server.py -from kcweb.create import create -create("app","api") # 创建项目 -``` -- 您的目录结构应该是这样,如下: -``` -├─./ 框架目录 -├─app 公共方法目录 -│ ├─common 公共函数目录 -│ │ ├─__init__.py 函数文件 -│ ├─config 配置目录 -│ │ ├─__init__.py 配置文件 -│ ├─api 模块目录 -│ │ ├─common 该模块的公共函数目录 -│ │ │ ├─__init__.py 函数文件 -│ │ ├─controller 控制器目录 -│ │ │ ├─__init__.py 版本初始化文件 -│ │ │ ├─v1 -│ │ │ │ ├─__init__.py 函数初始化文件 -│ │ │ │ ├─index.py 控制器文件 -│ │ │ ├─v2 -│ │ │ │ ├─__init__.py 函数初始化文件 -│ │ │ │ ├─index.py 控制器文件 -│ │ ├─tpl 模板文件目录 -│ │ │ ├─v1 -│ │ │ │ ├─index -│ │ │ │ │ ├─index.html 模块文件 -│ │ │ ├─v1 -│ │ │ │ ├─index -│ │ │ │ │ ├─index.html 模块文件 -│ │ ├─__init__.py 控制器初始化文件 -│ ├─static 静态资源目录 -│ ├─runtime 缓存目录 -│ ├─__init__.py 自动导入模块文件 -├─server.py 应用创建后生成的运行文件(应用创建时自动创建) -``` -- 其中server.py文件内容将被修改如下 -``` -# #gunicorn -b 0.0.0.0:39001 server:app -from kcweb import web -import app as application -app=web(__name__,application) -if __name__ == "__main__": - #app 是当前文件名 host监听ip port端口 name python解释器名字 (windows一般是python linux一般是python3) - app.run("server",host="0.0.0.0",port="39001",name="python") -``` -- 如果您当前系统的python解释器名字是python3,你应该是在当前目录下执行python3 server.py。 然后访问127.0.0.1:39001 +

kcweb==4.12.3框架简要说明

+kcweb作为web开发而设计的高性能框架,采用全新的架构思想,注重易用性。遵循MIT开源许可协议发布,意味着个人和企业可以免费使用kcweb,甚至允许把你基于kcweb开发的应用开源或商业产品发布或销售。 -- 如果您当前系统的python解释器名字是python,您应该修改server.py代码如下 -``` -# #gunicorn -b 0.0.0.0:39001 server:app -from kcweb import web -import app as application -app=web(__name__,application) -if __name__ == "__main__": - #app 是当前文件名 host监听ip port端口 - app.run("server",host="0.0.0.0",port="39001",name="python") -``` -然后访问127.0.0.1:39001 +[官方完整文档](https://intapp.kwebapp.cn/intapp/doc/index/finddoc/1/29/1 "官方文档") +------------ + +-

状态

+> +开发版 + +---- + +-

兼容性

+> +向下兼容到4.12.2 + +----- diff --git a/kcweb/app.py b/kcweb/app.py index ebf10f982bce01a59420027a2bcac8c796167aff..96a717ea4331dec76a88de4dd7da8382401c6477 100644 --- a/kcweb/app.py +++ b/kcweb/app.py @@ -563,7 +563,7 @@ class web: if self.__config.app['after_request']: #请求后执行的函数 try: - data=getattr(obj,self.__config.app['after_request'])() + data=getattr(obj,self.__config.app['after_request'])(body,status,resheader) if data: body,status,resheader=web.__tran(self,data,status,resheader) except (AttributeError,UnboundLocalError):pass diff --git a/kcweb/common/autoload.py b/kcweb/common/autoload.py index 6a5bcb6839bf52a660e7b580ab3681732410c076..a015f40f0cfff3d1adde492eb1d36e360646cf3e 100644 --- a/kcweb/common/autoload.py +++ b/kcweb/common/autoload.py @@ -587,6 +587,7 @@ class kcwtar: return False class response: + tpldata={} #公共模板变量 def tpl(path=None,status='200 ok',response_cache=False,ETag=None,header={"Content-Type":"text/html; charset=utf-8"},**context): """返回模板内容 @@ -600,6 +601,13 @@ class response: header 响应头 """ + for k in dir(response): + if k not in ['download','json','pic','redirect','tpl','tpldata','video'] and k[-2:]!='__': + try: + context[k]=response.__dict__[k] + except KeyError: + pass + context['config']=config headers=copy.deepcopy(header) getroutecomponent=globals.VAR.component if path: @@ -629,16 +637,16 @@ class response: else: headers['response_cache']="default" set_cache(ETag,1) - body=Template(Temppath,config=config,**context) + body=Template(Temppath,**context) dateArray = core_datetime.datetime.utcfromtimestamp(times()-86400) otherStyleTime = dateArray.strftime('%a, %d %b %Y %H:%M:%S GMT') headers['Last-Modified']=otherStyleTime headers['ETag']=ETag return body,status,headers elif status: - return Template(Temppath,config=config,**context),status,headers + return Template(Temppath,tpldata=response.tpldata,**context),status,headers else: - return Template(Temppath,config=config,**context),'200 ok',headers + return Template(Temppath,tpldata=response.tpldata,**context),'200 ok',headers def json(res=[],status='200 ok',response_cache=False,ETag=None,header={"Content-Type":"application/json; charset=utf-8","Access-Control-Allow-Origin":"*"}): """响应json内容 diff --git a/server.py b/server.py index 42d1075fef7564131535327a3964b0fb78606e71..4cd79c71b01e1e28183914cd3fca2b3d912d19fe 100644 --- a/server.py +++ b/server.py @@ -4,5 +4,5 @@ from kcweb import web import app as application app=web(__name__,application) if __name__ == "__main__": - #host监听ip port端口 name python解释器名字 (windows一般是python linux一般是python3) + #host监听ip port端口 name python解释器名字 (windows一般是python linux一般是python3) app.run(host="0.0.0.0",port="39001",name="python") \ No newline at end of file