启动脚本
This commit is contained in:
parent
48900fec5e
commit
d00e4f20f8
|
@ -0,0 +1,9 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function getTaskList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/task/',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
|
@ -103,6 +103,12 @@ export const asyncRoutes = [
|
||||||
name: 'File',
|
name: 'File',
|
||||||
component: () => import('@/views/system/file'),
|
component: () => import('@/views/system/file'),
|
||||||
meta: { title: '文件库', icon: 'documentation', perms: ['file_room'] }
|
meta: { title: '文件库', icon: 'documentation', perms: ['file_room'] }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'task',
|
||||||
|
name: 'Task',
|
||||||
|
component: () => import('@/views/system/task'),
|
||||||
|
meta: { title: '定时任务', icon: 'list', perms: ['task_manage'] }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<div>
|
||||||
|
<el-select
|
||||||
|
v-model="listQuery.enabled"
|
||||||
|
placeholder="是否启用"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
class="filter-item"
|
||||||
|
@change="handleFilter"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in enabledOptions"
|
||||||
|
:key="item.key"
|
||||||
|
:label="item.display_name"
|
||||||
|
:value="item.key"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-input
|
||||||
|
v-model="listQuery.search"
|
||||||
|
placeholder="任务名"
|
||||||
|
style="width: 300px;"
|
||||||
|
class="filter-item"
|
||||||
|
@keyup.enter.native="handleFilter"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
class="filter-item"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-search"
|
||||||
|
@click="handleFilter"
|
||||||
|
>搜索</el-button>
|
||||||
|
<el-button
|
||||||
|
class="filter-item"
|
||||||
|
style="margin-left: 10px;"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
@click="resetFilter"
|
||||||
|
>刷新重置</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-loading="listLoading"
|
||||||
|
:data="dataList.results"
|
||||||
|
style="width: 100%;margin-top:10px;"
|
||||||
|
border
|
||||||
|
fit
|
||||||
|
stripe
|
||||||
|
highlight-current-row
|
||||||
|
max-height="600"
|
||||||
|
>
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
<el-table-column align="center" label="名称">
|
||||||
|
<template slot-scope="scope">{{ scope.row.name }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="header-center" label="描述">
|
||||||
|
<template slot-scope="scope">{{ scope.row.description }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="header-center" label="执行次数">
|
||||||
|
<template slot-scope="scope">{{ scope.row.total_run_count }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="header-center" label="最后执行时间">
|
||||||
|
<template slot-scope="scope">{{ scope.row.last_run_at }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="是否启用">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ scope.row.enabled }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="dataList.count>0"
|
||||||
|
:total="dataList.count"
|
||||||
|
:page.sync="listQuery.page"
|
||||||
|
:limit.sync="listQuery.page_size"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { getTaskList } from "@/api/task"
|
||||||
|
import Pagination from "@/components/Pagination"
|
||||||
|
export default {
|
||||||
|
components: { Pagination },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dataList: {count:0},
|
||||||
|
listLoading: true,
|
||||||
|
listQuery: {
|
||||||
|
page: 1,
|
||||||
|
page_size: 20
|
||||||
|
},
|
||||||
|
enabledOptions: [
|
||||||
|
{ key: "true", display_name: "启用" },
|
||||||
|
{ key: "false", display_name: "禁用" },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.listLoading = true;
|
||||||
|
getTaskList(this.listQuery).then(response => {
|
||||||
|
if (response.data) {
|
||||||
|
this.dataList = response.data
|
||||||
|
}
|
||||||
|
this.listLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
resetFilter() {
|
||||||
|
this.listQuery = {
|
||||||
|
page: 1,
|
||||||
|
page_size: 20
|
||||||
|
};
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handleFilter() {
|
||||||
|
this.listQuery.page = 1;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
BIN
docs/~$模块细分.docx
BIN
docs/~$模块细分.docx
Binary file not shown.
|
@ -8,6 +8,7 @@ from simple_history.models import HistoricalRecords
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Position(BaseModel):
|
class Position(BaseModel):
|
||||||
"""
|
"""
|
||||||
职位/岗位
|
职位/岗位
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from django_celery_beat.models import PeriodicTask
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from .models import Organization, Permission, Role, User, Position, DictType, Dict, File
|
from .models import (Dict, DictType, File, Organization, Permission, Position,
|
||||||
|
Role, User)
|
||||||
|
|
||||||
|
class TaskSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = PeriodicTask
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class FileSerializer(serializers.ModelSerializer):
|
class FileSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Create your tasks here
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from celery import shared_task
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def add(x, y):
|
||||||
|
return x + y
|
|
@ -1,5 +1,5 @@
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from .views import UserViewSet, OrganizationViewSet, PermissionViewSet, RoleViewSet, PositionViewSet, TestView, DictTypeViewSet, DictViewSet
|
from .views import UserViewSet, OrganizationViewSet, PermissionViewSet, RoleViewSet, PositionViewSet, TestView, DictTypeViewSet, DictViewSet, TaskViewSet
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ router.register('role', RoleViewSet, basename="role")
|
||||||
router.register('position', PositionViewSet, basename="position")
|
router.register('position', PositionViewSet, basename="position")
|
||||||
router.register('dicttype', DictTypeViewSet, basename="dicttype")
|
router.register('dicttype', DictTypeViewSet, basename="dicttype")
|
||||||
router.register('dict', DictViewSet, basename="dict")
|
router.register('dict', DictViewSet, basename="dict")
|
||||||
|
router.register('task', TaskViewSet, basename="task")
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
path('test/', TestView.as_view())
|
path('test/', TestView.as_view())
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth.hashers import check_password, make_password
|
from django.contrib.auth.hashers import check_password, make_password
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from django_celery_beat.models import PeriodicTask
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
@ -10,6 +12,8 @@ from rest_framework.mixins import (CreateModelMixin, DestroyModelMixin,
|
||||||
ListModelMixin, RetrieveModelMixin,
|
ListModelMixin, RetrieveModelMixin,
|
||||||
UpdateModelMixin)
|
UpdateModelMixin)
|
||||||
from rest_framework.pagination import PageNumberPagination
|
from rest_framework.pagination import PageNumberPagination
|
||||||
|
from rest_framework.parsers import (FileUploadParser, JSONParser,
|
||||||
|
MultiPartParser)
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
@ -19,15 +23,16 @@ from rest_framework_simplejwt.tokens import RefreshToken
|
||||||
from utils.queryset import get_child_queryset2
|
from utils.queryset import get_child_queryset2
|
||||||
|
|
||||||
from .filters import UserFilter
|
from .filters import UserFilter
|
||||||
from .models import (Dict, DictType, Organization, Permission, Position, Role,
|
from .mixins import CreateModelAMixin
|
||||||
User, File)
|
from .models import (Dict, DictType, File, Organization, Permission, Position,
|
||||||
|
Role, User)
|
||||||
from .permission import RbacPermission, get_permission_list
|
from .permission import RbacPermission, get_permission_list
|
||||||
from .permission_data import RbacFilterSet
|
from .permission_data import RbacFilterSet
|
||||||
from .serializers import (DictSerializer, DictTypeSerializer,
|
from .serializers import (DictSerializer, DictTypeSerializer, FileSerializer,
|
||||||
OrganizationSerializer, PermissionSerializer,
|
OrganizationSerializer, PermissionSerializer,
|
||||||
PositionSerializer, RoleSerializer,
|
PositionSerializer, RoleSerializer, TaskSerializer,
|
||||||
UserCreateSerializer, UserListSerializer,
|
UserCreateSerializer, UserListSerializer,
|
||||||
UserModifySerializer, FileSerializer)
|
UserModifySerializer)
|
||||||
|
|
||||||
logger = logging.getLogger('log')
|
logger = logging.getLogger('log')
|
||||||
# logger.info('请求成功! response_code:{};response_headers:{};response_body:{}'.format(response_code, response_headers, response_body[:251]))
|
# logger.info('请求成功! response_code:{};response_headers:{};response_body:{}'.format(response_code, response_headers, response_body[:251]))
|
||||||
|
@ -40,6 +45,14 @@ class LogoutView(APIView):
|
||||||
def get(self, request, *args, **kwargs): # 可将token加入黑名单
|
def get(self, request, *args, **kwargs): # 可将token加入黑名单
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
class TaskViewSet(ModelViewSet):
|
||||||
|
queryset = PeriodicTask.objects.all()
|
||||||
|
serializer_class = TaskSerializer
|
||||||
|
search_fields = ['^name']
|
||||||
|
filterset_fields = ['enabled']
|
||||||
|
ordering = '-pk'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DictTypeViewSet(ModelViewSet):
|
class DictTypeViewSet(ModelViewSet):
|
||||||
"""
|
"""
|
||||||
|
@ -211,9 +224,6 @@ class UserViewSet(ModelViewSet):
|
||||||
}
|
}
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
from rest_framework.parsers import MultiPartParser, JSONParser, FileUploadParser
|
|
||||||
from .mixins import CreateModelAMixin
|
|
||||||
from django.conf import settings
|
|
||||||
class FileViewSet(ModelViewSet):
|
class FileViewSet(ModelViewSet):
|
||||||
"""
|
"""
|
||||||
文件:增删改查
|
文件:增删改查
|
||||||
|
@ -243,4 +253,3 @@ class FileViewSet(ModelViewSet):
|
||||||
instance = serializer.save(create_by = self.request.user, name=name, size=size, type=type, mime=mime)
|
instance = serializer.save(create_by = self.request.user, name=name, size=size, type=type, mime=mime)
|
||||||
instance.path = settings.MEDIA_URL + instance.file.name
|
instance.path = settings.MEDIA_URL + instance.file.name
|
||||||
instance.save()
|
instance.save()
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,4 @@
|
||||||
|
@echo off
|
||||||
|
call venv\scripts\activate.bat
|
||||||
|
celery -A server beat -l info
|
||||||
|
pause
|
|
@ -0,0 +1,4 @@
|
||||||
|
@echo off
|
||||||
|
call venv\scripts\activate.bat
|
||||||
|
celery -A server worker -l info -P eventlet
|
||||||
|
pause
|
|
@ -1,2 +0,0 @@
|
||||||
c:\Basepackage\redis\redis-server.exe c:\Basepackage\redis\redis.windows.conf
|
|
||||||
pause
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
@echo off
|
||||||
|
call venv\scripts\activate.bat
|
||||||
|
python manage.py runserver
|
|
@ -0,0 +1,7 @@
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
# This will make sure the app is always imported when
|
||||||
|
# Django starts so that shared_task will use this app.
|
||||||
|
from .celery import app as celery_app
|
||||||
|
|
||||||
|
__all__ = ('celery_app',)
|
|
@ -0,0 +1,24 @@
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
# set the default Django settings module for the 'celery' program.
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings_dev')
|
||||||
|
|
||||||
|
app = Celery('server')
|
||||||
|
|
||||||
|
# Using a string here means the worker doesn't have to serialize
|
||||||
|
# the configuration object to child processes.
|
||||||
|
# - namespace='CELERY' means all celery-related configuration keys
|
||||||
|
# should have a `CELERY_` prefix.
|
||||||
|
app.config_from_object('django.conf:settings', namespace='CELERY')
|
||||||
|
|
||||||
|
# Load task modules from all registered Django app configs.
|
||||||
|
app.autodiscover_tasks()
|
||||||
|
|
||||||
|
|
||||||
|
@app.task(bind=True)
|
||||||
|
def debug_task(self):
|
||||||
|
print('Request: {0!r}'.format(self.request))
|
|
@ -38,6 +38,8 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'django_redis',
|
||||||
|
'django_celery_beat',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'corsheaders',
|
'corsheaders',
|
||||||
"django_filters",
|
"django_filters",
|
||||||
|
@ -157,17 +159,15 @@ SIMPLE_JWT = {
|
||||||
'ACCESS_TOKEN_LIFETIME': timedelta(days=1),
|
'ACCESS_TOKEN_LIFETIME': timedelta(days=1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 跨域配置
|
||||||
CORS_ORIGIN_ALLOW_ALL = True
|
CORS_ORIGIN_ALLOW_ALL = True
|
||||||
|
|
||||||
|
# Auth配置
|
||||||
AUTH_USER_MODEL = 'system.User'
|
AUTH_USER_MODEL = 'system.User'
|
||||||
|
|
||||||
|
|
||||||
# 用户认证
|
|
||||||
AUTHENTICATION_BACKENDS = (
|
AUTHENTICATION_BACKENDS = (
|
||||||
'apps.system.authentication.CustomBackend',
|
'apps.system.authentication.CustomBackend',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# 缓存配置
|
# 缓存配置
|
||||||
CACHES = {
|
CACHES = {
|
||||||
"default": {
|
"default": {
|
||||||
|
@ -179,6 +179,8 @@ CACHES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# 日志配置
|
# 日志配置
|
||||||
# 创建日志的路径
|
# 创建日志的路径
|
||||||
LOG_PATH = os.path.join(BASE_DIR, 'log')
|
LOG_PATH = os.path.join(BASE_DIR, 'log')
|
||||||
|
|
|
@ -10,3 +10,10 @@ DATABASES = {
|
||||||
'PORT': '5432',
|
'PORT': '5432',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# Celery配置
|
||||||
|
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
|
||||||
|
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
|
||||||
|
CELERY_BROKER_TRANSPORT = 'redis'
|
||||||
|
CELERYD_MAX_TASKS_PER_CHILD = 10
|
||||||
|
CELERY_TIMEZONE = TIME_ZONE
|
||||||
|
CELERY_ENABLE_UTC=True
|
||||||
|
|
|
@ -10,3 +10,10 @@ DATABASES = {
|
||||||
'PORT': '5432',
|
'PORT': '5432',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# Celery配置
|
||||||
|
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
|
||||||
|
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
|
||||||
|
CELERY_BROKER_TRANSPORT = 'redis'
|
||||||
|
CELERYD_MAX_TASKS_PER_CHILD = 10
|
||||||
|
CELERY_TIMEZONE = TIME_ZONE
|
||||||
|
CELERY_ENABLE_UTC=True
|
||||||
|
|
Loading…
Reference in New Issue