定时任务完成
parent
29993485bb
commit
3226d7eb7e
|
@ -101,11 +101,14 @@ npm run build:prod
|
||||||
5. 执行迁移命令:
|
5. 执行迁移命令:
|
||||||
python3 manage.py makemigrations
|
python3 manage.py makemigrations
|
||||||
python3 manage.py migrate
|
python3 manage.py migrate
|
||||||
5. 初始化数据
|
6. 初始化数据
|
||||||
python3 manage.py init
|
python3 manage.py init
|
||||||
6. 启动项目
|
7. 启动项目
|
||||||
python3 manage.py runserver 0.0.0.0:8000
|
python3 manage.py runserver 0.0.0.0:8000
|
||||||
|
|
||||||
|
定时任务启动命令:
|
||||||
|
celery -A application worker -B --loglevel=info
|
||||||
|
|
||||||
初始账号:admin 密码:123456
|
初始账号:admin 密码:123456
|
||||||
|
|
||||||
后端接口文档地址:http://127.0.0.1:8000/docs/
|
后端接口文档地址:http://127.0.0.1:8000/docs/
|
||||||
|
|
|
@ -113,28 +113,27 @@ services:
|
||||||
- dvadmin_net
|
- dvadmin_net
|
||||||
|
|
||||||
|
|
||||||
# docker-celery:
|
dvadmin-celery:
|
||||||
# build:
|
build:
|
||||||
# context: .
|
context: .
|
||||||
# dockerfile: ./docker_env/celery/Dockerfile
|
dockerfile: ./docker_env/celery/Dockerfile
|
||||||
# # image: celery:1.0
|
# image: django:2.2
|
||||||
# container_name: docker-celery
|
container_name: dvadmin-celery
|
||||||
# working_dir: /dvadmin-backend
|
working_dir: /dvadmin-backend
|
||||||
# # command: bash
|
# command: bash -c "python manage.py makemigrations && python manage.py migrate && python manage.py collectstatic --noinput && python manage.py runserver"
|
||||||
# depends_on:
|
# command: bash
|
||||||
# - dvadmin-mysql
|
depends_on:
|
||||||
# - dvadmin-redis
|
- dvadmin-mysql
|
||||||
# - dvadmin-django
|
- dvadmin-redis
|
||||||
# volumes:
|
environment:
|
||||||
# - ./dvadmin-backend:/dvadmin-backend
|
- REDIS_HOST=dvadmin-redis
|
||||||
# - ./logs/log:/var/log
|
- DATABASE_HOST=dvadmin-mysql
|
||||||
# ports:
|
volumes:
|
||||||
# - "5672:5672"
|
- ./dvadmin-backend:/dvadmin-backend
|
||||||
# expose:
|
- ./logs/log:/var/log
|
||||||
# - "5672"
|
restart: always
|
||||||
# restart: always
|
networks:
|
||||||
# networks:
|
- dvadmin_net
|
||||||
# - dvadmin_net
|
|
||||||
|
|
||||||
|
|
||||||
dvadmin-nginx:
|
dvadmin-nginx:
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
FROM python:3.7
|
FROM python:3.7
|
||||||
# ENV PYTHONUNBUFFERED 1
|
# ENV PYTHONUNBUFFERED 1
|
||||||
# RUN sed -i s/deb.debian.org/mirrors.163.com/g /etc/apt/sources.list
|
# RUN sed -i s/deb.debian.org/mirrors.163.com/g /etc/apt/sources.list
|
||||||
# RUN cat /etc/apt/sources.list
|
# RUN cat /etc/apt/sources.list
|
||||||
# RUN apt-get clean
|
# RUN apt-get clean
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install -y build-essential
|
RUN apt-get install -y build-essential
|
||||||
RUN apt-get install -y python3.7-dev libpq-dev libopencv-dev python-opencv
|
RUN apt-get install -y python3.7-dev libpq-dev libopencv-dev python-opencv
|
||||||
RUN apt-get install -y redis-tools
|
RUN apt-get install -y redis-tools
|
||||||
|
|
||||||
COPY ./docker_env/celery/requirement.txt /
|
COPY ./docker_env/celery/requirement.txt /
|
||||||
RUN mkdir /backend
|
RUN mkdir /backend
|
||||||
WORKDIR /backend
|
WORKDIR /backend
|
||||||
RUN python3.7 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r /requirement.txt --use-feature=2020-resolver
|
RUN python3.7 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ -r /requirement.txt --use-feature=2020-resolver
|
||||||
CMD ["celery", "-A", "azcrm", "worker", "-B", "--loglevel=info"]
|
CMD ["celery", "-A", "application", "worker", "-B", "--loglevel=info"]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
import django
|
||||||
|
from celery import Celery, platforms
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', "application.settings")
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
app = Celery(f"dvadmin")
|
||||||
|
|
||||||
|
app.config_from_object('django.conf:settings')
|
||||||
|
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
||||||
|
platforms.C_FORCE_ROOT = True
|
|
@ -45,7 +45,7 @@ INSTALLED_APPS = [
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'corsheaders',
|
'corsheaders',
|
||||||
'captcha',
|
'captcha',
|
||||||
'djcelery',
|
'django_celery_beat',
|
||||||
# 自定义app
|
# 自定义app
|
||||||
'apps.vadmin.permission',
|
'apps.vadmin.permission',
|
||||||
'apps.vadmin.op_drf',
|
'apps.vadmin.op_drf',
|
||||||
|
@ -320,3 +320,5 @@ CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
|
||||||
API_LOG_ENABLE = True
|
API_LOG_ENABLE = True
|
||||||
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||||
# API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE']
|
# API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE']
|
||||||
|
BROKER_URL = f'redis://:{REDIS_PASSWORD if REDIS_PASSWORD else ""}@{os.getenv("REDIS_HOST") or REDIS_HOST}:{REDIS_PORT}/2' #Broker使用Redis, 使用0数据库(暂时不是很清楚原理)
|
||||||
|
CELERYBEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler' #Backend数据库
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import django_filters
|
import django_filters
|
||||||
from djcelery.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
from django_celery_beat.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
||||||
|
|
||||||
|
|
||||||
class IntervalScheduleFilter(django_filters.rest_framework.FilterSet):
|
class IntervalScheduleFilter(django_filters.rest_framework.FilterSet):
|
||||||
|
@ -11,7 +11,7 @@ class IntervalScheduleFilter(django_filters.rest_framework.FilterSet):
|
||||||
class CrontabScheduleFilter(django_filters.rest_framework.FilterSet):
|
class CrontabScheduleFilter(django_filters.rest_framework.FilterSet):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CrontabSchedule
|
model = CrontabSchedule
|
||||||
fields = '__all__'
|
exclude = ('timezone',)
|
||||||
|
|
||||||
|
|
||||||
class PeriodicTaskFilter(django_filters.rest_framework.FilterSet):
|
class PeriodicTaskFilter(django_filters.rest_framework.FilterSet):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from djcelery.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
from django_celery_beat.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from ..op_drf.serializers import CustomModelSerializer
|
from ..op_drf.serializers import CustomModelSerializer
|
||||||
|
@ -23,7 +23,7 @@ class CrontabScheduleSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CrontabSchedule
|
model = CrontabSchedule
|
||||||
fields = '__all__'
|
exclude = ('timezone',)
|
||||||
|
|
||||||
|
|
||||||
class PeriodicTaskSerializer(CustomModelSerializer):
|
class PeriodicTaskSerializer(CustomModelSerializer):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from djcelery.admin import TaskSelectWidget
|
from django_celery_beat.admin import TaskSelectWidget
|
||||||
from djcelery.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
from django_celery_beat.models import IntervalSchedule, CrontabSchedule, PeriodicTask
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
from ..celery.filters import IntervalScheduleFilter, CrontabScheduleFilter, PeriodicTaskFilter
|
from ..celery.filters import IntervalScheduleFilter, CrontabScheduleFilter, PeriodicTaskFilter
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import datetime
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from captcha.models import CaptchaStore
|
||||||
|
|
||||||
|
from ..utils.decorators import BaseCeleryApp
|
||||||
|
from ..utils.response import SuccessResponse
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
@BaseCeleryApp(name='apps.vadmin.permission.tasks.clear_invalid_captcha')
|
||||||
|
def clear_invalid_captcha():
|
||||||
|
"""
|
||||||
|
清除数据库中废弃失效的验证码
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
queryset = CaptchaStore.objects.filter(expiration__lt=datetime.datetime.now())
|
||||||
|
msg = f"成功删除 {queryset.count()} 条失效验证码!"
|
||||||
|
logger.info(msg)
|
||||||
|
queryset.delete()
|
||||||
|
return SuccessResponse(msg=msg)
|
|
@ -7,4 +7,5 @@ from ..models.message_push import MessagePush
|
||||||
from ..models.message_push import MessagePushUser
|
from ..models.message_push import MessagePushUser
|
||||||
from ..models.logininfor import LoginInfor
|
from ..models.logininfor import LoginInfor
|
||||||
from ..models.operation_log import OperationLog
|
from ..models.operation_log import OperationLog
|
||||||
|
from ..models.celery_log import CeleryLog
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
from django.db.models import CharField, BooleanField, TextField
|
||||||
|
|
||||||
|
from ...op_drf.models import CoreModel
|
||||||
|
|
||||||
|
|
||||||
|
class CeleryLog(CoreModel):
|
||||||
|
name = CharField(max_length=256, verbose_name='任务名称', help_text='任务名称')
|
||||||
|
kwargs = TextField(max_length=1024, verbose_name='执行参数', help_text='运行参数')
|
||||||
|
seconds = CharField(max_length=8, verbose_name='执行时间')
|
||||||
|
state = BooleanField(default=False, verbose_name='运行状态')
|
||||||
|
result = TextField(max_length=10240, verbose_name='任务结果', help_text='任务返回内容')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'celery定时日志'
|
||||||
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.creator and self.creator.name}"
|
|
@ -1,17 +1,22 @@
|
||||||
"""
|
"""
|
||||||
常用的装饰器以及DRF的装饰器
|
常用的装饰器以及DRF的装饰器
|
||||||
"""
|
"""
|
||||||
|
import functools
|
||||||
|
import logging
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from datetime import datetime
|
|
||||||
import functools
|
|
||||||
from collections import Iterable
|
from collections import Iterable
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from rest_framework_extensions.settings import extensions_api_settings
|
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.decorators import available_attrs
|
from django.utils.decorators import available_attrs
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework_extensions.settings import extensions_api_settings
|
||||||
|
|
||||||
|
from application.celery import app
|
||||||
from .string_util import bas64_encode_text, bas64_decode_text
|
from .string_util import bas64_encode_text, bas64_decode_text
|
||||||
|
from ..system.models import CeleryLog
|
||||||
|
|
||||||
|
|
||||||
def get_cache(alias=None):
|
def get_cache(alias=None):
|
||||||
|
@ -19,12 +24,46 @@ def get_cache(alias=None):
|
||||||
return caches[alias or extensions_api_settings.DEFAULT_USE_CACHE]
|
return caches[alias or extensions_api_settings.DEFAULT_USE_CACHE]
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def BaseCeleryApp(name):
|
||||||
|
def wraps(func):
|
||||||
|
@app.task(name=name)
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
obj = CeleryLog()
|
||||||
|
obj.name = str(func.__name__)
|
||||||
|
obj.kwargs = f"*args:{args}\n**kwargs:{kwargs}"
|
||||||
|
start_time = datetime.now()
|
||||||
|
res = None
|
||||||
|
try:
|
||||||
|
res = func(*args, **kwargs)
|
||||||
|
obj.result = str(res)
|
||||||
|
obj.state = True
|
||||||
|
except Exception as exc:
|
||||||
|
obj.state = False
|
||||||
|
obj.result = f"执行失败,错误信息:{exc}"
|
||||||
|
logger.info(f"传入参数:{args, kwargs}")
|
||||||
|
logger.error(f"执行失败,错误信息:{exc}")
|
||||||
|
end_time = datetime.now()
|
||||||
|
seconds = (end_time - start_time).seconds
|
||||||
|
obj.seconds = seconds
|
||||||
|
obj.save()
|
||||||
|
return res
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return wraps
|
||||||
|
|
||||||
|
|
||||||
def print_fun_time(logger=None):
|
def print_fun_time(logger=None):
|
||||||
"""
|
"""
|
||||||
打印函数执行时间
|
打印函数执行时间
|
||||||
:param logger:
|
:param logger:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(func):
|
def wrapper(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
|
@ -37,28 +76,34 @@ def print_fun_time(logger=None):
|
||||||
else:
|
else:
|
||||||
print(f"{func.__name__}耗时:{seconds}秒")
|
print(f"{func.__name__}耗时:{seconds}秒")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def print_time(logger=None):
|
def print_time(logger=None):
|
||||||
"""
|
"""
|
||||||
打印函数执行时间
|
打印函数执行时间
|
||||||
:param logger:
|
:param logger:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(func):
|
def wrapper(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
res = func(*args, **kwargs)
|
res = func(*args, **kwargs)
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
seconds = "%.3f"% (end_time - start_time)
|
seconds = "%.3f" % (end_time - start_time)
|
||||||
if logger:
|
if logger:
|
||||||
logger.info(f"{func.__name__}耗时:{seconds}秒")
|
logger.info(f"{func.__name__}耗时:{seconds}秒")
|
||||||
else:
|
else:
|
||||||
print(f"{func.__name__}耗时:{seconds}秒")
|
print(f"{func.__name__}耗时:{seconds}秒")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,11 +113,13 @@ def bas64_encode(func):
|
||||||
:param func:
|
:param func:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
text = func(*args, **kwargs)
|
text = func(*args, **kwargs)
|
||||||
if isinstance(text, str):
|
if isinstance(text, str):
|
||||||
text = bas64_encode_text(text)
|
text = bas64_encode_text(text)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,11 +129,13 @@ def bas64_decode(func):
|
||||||
:param func:
|
:param func:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
text = func(*args, **kwargs)
|
text = func(*args, **kwargs)
|
||||||
if isinstance(text, str):
|
if isinstance(text, str):
|
||||||
text = bas64_decode_text(text)
|
text = bas64_decode_text(text)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,6 +144,7 @@ def decode(crypto=""):
|
||||||
解密装饰器:BASE64
|
解密装饰器:BASE64
|
||||||
:param crypto: 解密算法名称(忽略大小写)
|
:param crypto: 解密算法名称(忽略大小写)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(func):
|
def wrapper(func):
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
text = func(*args, **kwargs)
|
text = func(*args, **kwargs)
|
||||||
|
@ -104,7 +154,9 @@ def decode(crypto=""):
|
||||||
else:
|
else:
|
||||||
text = text
|
text = text
|
||||||
return text
|
return text
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,11 +165,14 @@ def encode(crypto=""):
|
||||||
解密装饰器:BASE64
|
解密装饰器:BASE64
|
||||||
:param crypto: 解密算法名称(忽略大小写)
|
:param crypto: 解密算法名称(忽略大小写)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(func):
|
def wrapper(func):
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
text = func(*args, **kwargs)
|
text = func(*args, **kwargs)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,6 +188,7 @@ def envFunction(envs='', execute=True, result=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(func):
|
def wrapper(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
|
@ -141,14 +197,16 @@ def envFunction(envs='', execute=True, result=None):
|
||||||
environments = []
|
environments = []
|
||||||
elif isinstance(envs, str):
|
elif isinstance(envs, str):
|
||||||
environments = [envs, ]
|
environments = [envs, ]
|
||||||
elif isinstance(envs, (Iterable, )):
|
elif isinstance(envs, (Iterable,)):
|
||||||
environments = envs
|
environments = envs
|
||||||
if settings.PROJECT_ENV in environments and execute:
|
if settings.PROJECT_ENV in environments and execute:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
elif settings.PROJECT_ENV not in environments and not execute:
|
elif settings.PROJECT_ENV not in environments and not execute:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,6 +219,7 @@ def exceptionHandler(logger=None, throw=False, result=None, message=None):
|
||||||
:param message: 错误信息
|
:param message: 错误信息
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(func):
|
def wrapper(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
|
@ -174,7 +233,9 @@ def exceptionHandler(logger=None, throw=False, result=None, message=None):
|
||||||
if throw:
|
if throw:
|
||||||
raise e
|
raise e
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -203,6 +264,7 @@ class CacheResponse(object):
|
||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
this = self
|
this = self
|
||||||
|
|
||||||
@functools.wraps(func, assigned=available_attrs(func))
|
@functools.wraps(func, assigned=available_attrs(func))
|
||||||
def inner(self, request, *args, **kwargs):
|
def inner(self, request, *args, **kwargs):
|
||||||
return this.process_cache_response(
|
return this.process_cache_response(
|
||||||
|
@ -212,6 +274,7 @@ class CacheResponse(object):
|
||||||
args=args,
|
args=args,
|
||||||
kwargs=kwargs,
|
kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
def process_cache_response(self,
|
def process_cache_response(self,
|
||||||
|
@ -274,4 +337,3 @@ class CacheResponse(object):
|
||||||
|
|
||||||
|
|
||||||
cache_response = CacheResponse
|
cache_response = CacheResponse
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
asgiref==3.3.1
|
asgiref==3.3.1
|
||||||
Django==2.2.16
|
Django==2.2.16
|
||||||
django-cors-headers==3.7.0
|
django-cors-headers==3.7.0
|
||||||
django-celery==3.2.2
|
django_celery_beat==2.2.0
|
||||||
django-filter==2.4.0
|
django-filter==2.4.0
|
||||||
django-ranged-response==0.2.0
|
django-ranged-response==0.2.0
|
||||||
django-redis==4.12.1
|
django-redis==4.12.1
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
</el-autocomplete>
|
</el-autocomplete>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :rules="[{ required: true, message: '名称不能为空'}]" prop="name" label="名称:">
|
<el-form-item :rules="[{ required: true, message: '名称不能为空'}]" prop="name" label="名称:">
|
||||||
<el-input v-model="form.name" placeholder="例如: 主机表同步任务" style="width: 400px;"/>
|
<el-input v-model="form.name" placeholder="例如: XXX同步任务" style="width: 400px;"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="interval" label="任务频率:">
|
<el-form-item prop="interval" label="任务频率:">
|
||||||
<el-select v-model="form.interval" placeholder="请选择任务频率" style="width: 400px;" @change="form.crontab = ''">
|
<el-select v-model="form.interval" placeholder="请选择任务频率" style="width: 400px;" @change="form.crontab = ''">
|
||||||
|
|
Loading…
Reference in New Issue