精简功能
This commit is contained in:
@@ -112,10 +112,6 @@ MYSQL_DATABASE=PearAdminFlask
|
||||
MYSQL_USERNAME=root
|
||||
MYSQL_PASSWORD=root
|
||||
|
||||
# Redis 配置
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PORT=6379
|
||||
|
||||
# 密钥配置
|
||||
SECRET_KEY='pear-admin-flask'
|
||||
|
||||
@@ -140,7 +136,7 @@ flask db migrate
|
||||
flask db upgrade
|
||||
flask admin init
|
||||
|
||||
# windoes
|
||||
# windows
|
||||
run.bat
|
||||
|
||||
# linux
|
||||
@@ -149,16 +145,7 @@ chmod +x run.sh
|
||||
```
|
||||
|
||||
|
||||
#### 命令行创建视图
|
||||
|
||||
```bash
|
||||
# 示例
|
||||
|
||||
flask new --type view --name test/a
|
||||
|
||||
# 自动注册蓝图
|
||||
# 访问http://127.0.0.1:5000/test/a/
|
||||
```
|
||||
|
||||
#### 使用docker-compose运行项目
|
||||
|
||||
|
||||
@@ -498,71 +498,6 @@ powerdata = [
|
||||
create_time=now_time,
|
||||
enable=1,
|
||||
|
||||
), Power(
|
||||
id=52,
|
||||
name='定时任务',
|
||||
type='0',
|
||||
code='',
|
||||
url='',
|
||||
open_type='',
|
||||
parent_id='0',
|
||||
icon='layui-icon layui-icon-log',
|
||||
sort=3,
|
||||
create_time=now_time,
|
||||
enable=1,
|
||||
|
||||
), Power(
|
||||
id=53,
|
||||
name='任务管理',
|
||||
type='1',
|
||||
code='admin:task:main',
|
||||
url='/admin/task',
|
||||
open_type='_iframe',
|
||||
parent_id='52',
|
||||
icon='layui-icon ',
|
||||
sort=1,
|
||||
create_time=now_time,
|
||||
enable=1,
|
||||
|
||||
), Power(
|
||||
id=54,
|
||||
name='任务增加',
|
||||
type='2',
|
||||
code='admin:task:add',
|
||||
url='',
|
||||
open_type='',
|
||||
parent_id='53',
|
||||
icon='layui-icon ',
|
||||
sort=1,
|
||||
create_time=now_time,
|
||||
enable=1,
|
||||
|
||||
), Power(
|
||||
id=55,
|
||||
name='任务修改',
|
||||
type='2',
|
||||
code='admin:task:edit',
|
||||
url='',
|
||||
open_type='',
|
||||
parent_id='53',
|
||||
icon='layui-icon ',
|
||||
sort=2,
|
||||
create_time=now_time,
|
||||
enable=1,
|
||||
|
||||
), Power(
|
||||
id=56,
|
||||
name='任务删除',
|
||||
type='2',
|
||||
code='admin:task:remove',
|
||||
url='',
|
||||
open_type='',
|
||||
parent_id='53',
|
||||
icon='layui-icon ',
|
||||
sort=23,
|
||||
create_time=now_time,
|
||||
enable=1,
|
||||
|
||||
), Power(
|
||||
id=57,
|
||||
name='邮件管理',
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import os
|
||||
|
||||
import jinja2
|
||||
|
||||
|
||||
class NewViewModular():
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def path_is_exists(self):
|
||||
return os.path.exists(f"applications/view/{self.name.split('/')[0]}")
|
||||
|
||||
def new_dirs(self):
|
||||
if not self.path_is_exists():
|
||||
# 如果不存在则创建目录
|
||||
|
||||
# 创建目录操作函数
|
||||
os.makedirs(f"applications/view/{self.name.split('/')[0]}")
|
||||
|
||||
print(self.name + ' 创建成功')
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def add_view(self):
|
||||
# jinja渲染
|
||||
templateLoader = jinja2.FileSystemLoader(searchpath='applications/common/script/newmodular/template/')
|
||||
templateEnv = jinja2.Environment(loader=templateLoader)
|
||||
TEMPLATE_FILE = "view"
|
||||
template = templateEnv.get_template(TEMPLATE_FILE, )
|
||||
templateVars = {"name": self.name}
|
||||
outputText = template.render(templateVars)
|
||||
with open(f"applications/view/{self.name}.py", "a", encoding='utf-8') as f:
|
||||
f.write(outputText)
|
||||
f.close()
|
||||
|
||||
def add_init(self):
|
||||
# 判断__init__.py
|
||||
if os.path.exists(f"applications/view/{self.name.split('/')[0]}/__init__.py"):
|
||||
with open(f"applications/view/{self.name.split('/')[0]}/__init__.py", "r") as file:
|
||||
lines = file.readlines()
|
||||
print(lines)
|
||||
file.close()
|
||||
import_line_num = 0
|
||||
for line in lines:
|
||||
if 'def' in line:
|
||||
import_line_num = lines.index(line) - 2
|
||||
with open(f"applications/view/{self.name.split('/')[0]}/__init__.py", "w") as file:
|
||||
lines.insert(import_line_num,
|
||||
f"from applications.view.{self.name.replace('/', '.')} import {self.name.replace('/', '_')}\n")
|
||||
print(lines)
|
||||
lines.insert(len(lines) - 1, f" app.register_blueprint({self.name.replace('/', '_')})\n")
|
||||
print(lines)
|
||||
file.writelines(lines)
|
||||
file.close()
|
||||
return True
|
||||
else:
|
||||
templateLoader = jinja2.FileSystemLoader(searchpath='applications/common/script/newmodular/template/')
|
||||
templateEnv = jinja2.Environment(loader=templateLoader)
|
||||
TEMPLATE_FILE = "__init__"
|
||||
template = templateEnv.get_template(TEMPLATE_FILE, )
|
||||
templateVars = {"name": self.name}
|
||||
output = template.render(templateVars)
|
||||
with open(f"applications/view/{self.name.split('/')[0]}/__init__.py", "a", encoding='utf-8') as f:
|
||||
f.write(output)
|
||||
f.close()
|
||||
self.add_root_init()
|
||||
return True
|
||||
|
||||
def add_root_init(self):
|
||||
with open(f"applications/view/__init__.py", "r") as file:
|
||||
lines = file.readlines()
|
||||
file.close()
|
||||
import_line_num = 0
|
||||
for line in lines:
|
||||
if 'def' in line:
|
||||
import_line_num = lines.index(line) - 2
|
||||
with open(f"applications/view/__init__.py", "w") as file:
|
||||
lines.insert(
|
||||
import_line_num,
|
||||
f"from applications.view.{self.name.split('/')[0]} import register_{self.name.split('/')[0]}_views\n")
|
||||
print(lines)
|
||||
lines.insert(len(lines) - 1, f" register_{self.name.split('/')[0]}_views(app)\n")
|
||||
print(lines)
|
||||
file.writelines(lines)
|
||||
file.close()
|
||||
|
||||
def new_view(self):
|
||||
self.new_dirs()
|
||||
self.add_view()
|
||||
self.add_init()
|
||||
@@ -1,6 +0,0 @@
|
||||
from flask import Flask
|
||||
from applications.view.{{name.replace('/','.')}} import {{name.replace('/','_')}}
|
||||
|
||||
|
||||
def register_{{name.split('/')[0]}}_views(app: Flask):
|
||||
app.register_blueprint({{name.replace('/','_')}})
|
||||
@@ -1,8 +0,0 @@
|
||||
from flask import Blueprint
|
||||
|
||||
{{name.replace('/','_')}} = Blueprint('{{name.replace('/','_')}}', __name__, url_prefix='/{{name}}')
|
||||
|
||||
|
||||
@{{name.replace('/','_')}}.route('/')
|
||||
def index():
|
||||
return "这是{{name}}路由"
|
||||
@@ -1,54 +0,0 @@
|
||||
from apscheduler.events import (
|
||||
EVENT_JOB_ADDED,
|
||||
EVENT_JOB_ERROR,
|
||||
EVENT_JOB_EXECUTED,
|
||||
EVENT_JOB_MISSED,
|
||||
EVENT_JOB_REMOVED,
|
||||
EVENT_JOB_SUBMITTED,
|
||||
)
|
||||
|
||||
from applications.extensions.init_apscheduler import scheduler
|
||||
|
||||
|
||||
def job_missed(event):
|
||||
"""Job missed event."""
|
||||
with scheduler.app.app_context():
|
||||
print(event) # noqa: T001
|
||||
|
||||
|
||||
def job_error(event):
|
||||
"""Job error event."""
|
||||
with scheduler.app.app_context():
|
||||
print(event) # noqa: T001
|
||||
|
||||
|
||||
def job_executed(event):
|
||||
"""Job executed event."""
|
||||
with scheduler.app.app_context():
|
||||
print(event) # noqa: T001
|
||||
|
||||
|
||||
def job_added(event):
|
||||
"""Job added event."""
|
||||
with scheduler.app.app_context():
|
||||
print(event) # noqa: T001
|
||||
|
||||
|
||||
def job_removed(event):
|
||||
"""Job removed event."""
|
||||
with scheduler.app.app_context():
|
||||
print(event) # noqa: T001
|
||||
|
||||
|
||||
def job_submitted(event):
|
||||
"""Job scheduled to run event."""
|
||||
with scheduler.app.app_context():
|
||||
print(event) # noqa: T001
|
||||
|
||||
|
||||
scheduler.add_listener(job_missed, EVENT_JOB_MISSED)
|
||||
scheduler.add_listener(job_error, EVENT_JOB_ERROR)
|
||||
scheduler.add_listener(job_executed, EVENT_JOB_EXECUTED)
|
||||
scheduler.add_listener(job_added, EVENT_JOB_ADDED)
|
||||
scheduler.add_listener(job_removed, EVENT_JOB_REMOVED)
|
||||
scheduler.add_listener(job_submitted, EVENT_JOB_SUBMITTED)
|
||||
@@ -1,15 +0,0 @@
|
||||
import datetime
|
||||
|
||||
task_list = ['task2', 'task3', 'task4']
|
||||
|
||||
|
||||
def task2(a, b):
|
||||
print(f'定时任务_1_{a},{b},{datetime.datetime.now()}')
|
||||
|
||||
|
||||
def task3(a, b):
|
||||
print(f'定时任务_2_{a}{b}{datetime.datetime.now()}')
|
||||
|
||||
|
||||
def task4(a, b):
|
||||
print(f'定时任务_4_{a}{b}{datetime.datetime.now()}')
|
||||
+1
-23
@@ -1,9 +1,6 @@
|
||||
import logging
|
||||
from urllib.parse import quote_plus as urlquote
|
||||
|
||||
from apscheduler.executors.pool import ThreadPoolExecutor
|
||||
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
|
||||
|
||||
|
||||
class BaseConfig:
|
||||
SUPERADMIN = 'admin'
|
||||
@@ -37,10 +34,6 @@ class BaseConfig:
|
||||
|
||||
SECRET_KEY = "pear-admin-flask"
|
||||
|
||||
# redis配置
|
||||
REDIS_HOST = "127.0.0.1"
|
||||
REDIS_PORT = 6379
|
||||
|
||||
# mysql 配置
|
||||
MYSQL_USERNAME = "root"
|
||||
MYSQL_PASSWORD = "123456"
|
||||
@@ -53,7 +46,7 @@ class BaseConfig:
|
||||
|
||||
# 默认日志等级
|
||||
LOG_LEVEL = logging.WARN
|
||||
#
|
||||
# flask-mail配置
|
||||
MAIL_SERVER = 'smtp.qq.com'
|
||||
MAIL_USE_TLS = False
|
||||
MAIL_USE_SSL = True
|
||||
@@ -62,20 +55,6 @@ class BaseConfig:
|
||||
MAIL_PASSWORD = 'XXXXX' # 生成的授权码
|
||||
MAIL_DEFAULT_SENDER = MAIL_USERNAME
|
||||
|
||||
# 設置 APSCHEDULER 參數
|
||||
SCHEDULER_API_ENABLED = False
|
||||
SCHEDULER_JOBSTORES: dict = {
|
||||
'default': SQLAlchemyJobStore(
|
||||
url=f'mysql+pymysql://{MYSQL_USERNAME}:{urlquote(MYSQL_PASSWORD)}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}')
|
||||
}
|
||||
SCHEDULER_EXECUTORS: dict = {
|
||||
'default': ThreadPoolExecutor(20)
|
||||
}
|
||||
SCHEDULER_JOB_DEFAULTS: dict = {
|
||||
'coalesce': False,
|
||||
'max_instances': 3
|
||||
}
|
||||
|
||||
# 插件配置,填写插件的文件名名称,默认不启用插件。
|
||||
PLUGIN_ENABLE_FOLDERS = []
|
||||
|
||||
@@ -98,4 +77,3 @@ class BaseConfig:
|
||||
# 'testOracle': 'oracle+cx_oracle://test:123456@192.168.1.1:1521/test',
|
||||
# 'testSQLite': 'sqlite:///database.db
|
||||
# }
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ from .init_login import init_login_manager
|
||||
from .init_template_directives import init_template_directives
|
||||
from .init_error_views import init_error_views
|
||||
from .init_mail import init_mail, mail as flask_mail
|
||||
from .init_apscheduler import init_scheduler
|
||||
from .init_upload import init_upload
|
||||
from .init_migrate import init_migrate
|
||||
|
||||
@@ -16,6 +15,5 @@ def init_plugs(app: Flask) -> None:
|
||||
init_template_directives(app)
|
||||
init_error_views(app)
|
||||
init_mail(app)
|
||||
init_scheduler(app)
|
||||
init_upload(app)
|
||||
init_migrate(app)
|
||||
@@ -1,12 +0,0 @@
|
||||
from flask import Flask
|
||||
from flask_apscheduler import APScheduler
|
||||
|
||||
scheduler = APScheduler()
|
||||
|
||||
|
||||
def init_scheduler(app: Flask):
|
||||
scheduler.init_app(app)
|
||||
with app.app_context():
|
||||
from applications.common.tasks import tasks
|
||||
scheduler.start()
|
||||
from applications.common.tasks import events
|
||||
@@ -8,7 +8,6 @@ from applications.view.admin.power import admin_power
|
||||
from applications.view.admin.role import admin_role
|
||||
from applications.view.admin.user import admin_user
|
||||
from applications.view.admin.monitor import admin_monitor_bp
|
||||
from applications.view.admin.task import admin_task
|
||||
from applications.view.admin.mail import admin_mail
|
||||
|
||||
|
||||
@@ -21,5 +20,4 @@ def register_admin_views(app: Flask):
|
||||
app.register_blueprint(admin_power)
|
||||
app.register_blueprint(admin_role)
|
||||
app.register_blueprint(admin_dict)
|
||||
app.register_blueprint(admin_task)
|
||||
app.register_blueprint(admin_mail)
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
from flask import Blueprint, request, render_template
|
||||
from flask_apscheduler.utils import job_to_dict
|
||||
from datetime import datetime as dt
|
||||
from applications.common.tasks import tasks
|
||||
from applications.common.tasks.tasks import task_list
|
||||
from applications.common.utils.http import table_api, fail_api, success_api
|
||||
from applications.extensions.init_apscheduler import scheduler
|
||||
|
||||
admin_task = Blueprint('adminTask', __name__, url_prefix='/admin/task')
|
||||
|
||||
|
||||
@admin_task.route('/add_job', methods=['GET'])
|
||||
def add_task():
|
||||
scheduler.add_job(func=tasks.get(), id='4', args=(1, 1), trigger='interval', seconds=3,
|
||||
replace_existing=True)
|
||||
return '6'
|
||||
|
||||
|
||||
@admin_task.get('/')
|
||||
def main():
|
||||
return render_template('admin/task/main.html')
|
||||
|
||||
|
||||
@admin_task.route('/data', methods=['GET'])
|
||||
def get_task(): # 获取
|
||||
jobs = scheduler.get_jobs()
|
||||
jobs_list = []
|
||||
for job in jobs:
|
||||
jobs_list.append(job_to_dict(job))
|
||||
return table_api(data=jobs_list, count=len(jobs_list))
|
||||
|
||||
|
||||
# 增加
|
||||
@admin_task.get('/add')
|
||||
def add():
|
||||
return render_template('admin/task/add.html', task_list=task_list)
|
||||
|
||||
|
||||
@admin_task.post('/save')
|
||||
def save():
|
||||
_id = request.get_json(force=True).get("id")
|
||||
name = request.get_json(force=True).get("id")
|
||||
type = request.get_json(force=True).get("type")
|
||||
functions = request.get_json(force=True).get("functions")
|
||||
datetime = request.get_json(force=True).get("datetime")
|
||||
time = request.get_json(force=True).get("time")
|
||||
if not hasattr(tasks, functions):
|
||||
return fail_api()
|
||||
if type == 'date':
|
||||
scheduler.add_job(
|
||||
func=getattr(tasks, functions),
|
||||
id=_id,
|
||||
name=name,
|
||||
args=(1, 1),
|
||||
trigger=type,
|
||||
run_date=datetime,
|
||||
replace_existing=True)
|
||||
elif type == 'interval':
|
||||
# load time
|
||||
time = dt.strptime(time, "%H:%M:%S").time()
|
||||
interval_seconds = 0
|
||||
if time.hour != 0:
|
||||
interval_seconds += time.hour * 60 * 60
|
||||
if time.minute != 0:
|
||||
interval_seconds += time.minute * 60
|
||||
if time.second != 0:
|
||||
interval_seconds += time.second
|
||||
scheduler.add_job(
|
||||
func=getattr(tasks, functions),
|
||||
id=_id,
|
||||
name=name,
|
||||
args=(1, 1),
|
||||
trigger=type,
|
||||
seconds=interval_seconds,
|
||||
replace_existing=True)
|
||||
elif type == 'cron':
|
||||
scheduler.add_job(
|
||||
func=getattr(tasks, functions),
|
||||
id=_id,
|
||||
name=name,
|
||||
args=(1, 1),
|
||||
trigger=type,
|
||||
replace_existing=True)
|
||||
return success_api()
|
||||
|
||||
|
||||
# 恢复
|
||||
@admin_task.put('/enable')
|
||||
def enable():
|
||||
_id = request.get_json(force=True).get('id')
|
||||
# print(id)
|
||||
if _id:
|
||||
scheduler.resume_job(str(_id))
|
||||
return success_api(msg="启动成功")
|
||||
return fail_api(msg="数据错误")
|
||||
|
||||
|
||||
# 暂停
|
||||
@admin_task.put('/disable')
|
||||
def dis_enable():
|
||||
_id = request.get_json(force=True).get('id')
|
||||
if _id:
|
||||
scheduler.pause_job(str(_id))
|
||||
return success_api(msg="暂停成功")
|
||||
return fail_api(msg="数据错误")
|
||||
|
||||
|
||||
@admin_task.delete('/remove/<string:_id>/')
|
||||
def remove_job(_id): # 移除
|
||||
scheduler.remove_job(_id)
|
||||
return success_api(msg="删除成功")
|
||||
|
||||
# scheduler.add_job(func=task1, id='2', args=(1, 1), trigger='cron', day_of_week='0-6', hour=18, minute=24,
|
||||
# second=10, replace_existing=True)
|
||||
|
||||
# scheduler.add_job(func=task4, id='4', args=(2, 2), trigger='interval', seconds=3,
|
||||
# replace_existing=True, misfire_grace_time=3)
|
||||
|
||||
# # trigger='interval' 表示是一个循环任务,每隔多久执行一次
|
||||
# scheduler.add_job(func=task2, id='3', args=(2, 2), trigger='interval', seconds=3,
|
||||
# replace_existing=True)
|
||||
Reference in New Issue
Block a user