diff --git a/client/src/utils/request.js b/client/src/utils/request.js
index d4641f5..9c15d5b 100644
--- a/client/src/utils/request.js
+++ b/client/src/utils/request.js
@@ -77,7 +77,7 @@ service.interceptors.response.use(
error => {
// console.log(error,response) // for debug
Message({
- message: error.message,
+ message: '服务器错误',
type: 'error',
duration: 5 * 1000
})
diff --git a/client/src/views/system/dict.vue b/client/src/views/system/dict.vue
index 2c56ee5..54ba93e 100644
--- a/client/src/views/system/dict.vue
+++ b/client/src/views/system/dict.vue
@@ -13,7 +13,6 @@
v-loading="treeLoding"
class="filter-tree"
:data="dictTypeData"
- default-expand-all
highlight-current
:expand-on-click-node="false"
:filter-node-method="filterNode"
@@ -46,31 +45,42 @@
字典详情
- 新增
+
+ 新增
+
-
+
+
{{ scope.row.name }}
-
+
+ {{ scope.row.code }}
+
+
{{ scope.row.desc }}
-
- {{ scope.row.sort }}
+
+
+
+ 有效
+ 无效
+
-
+
-
+ /> -->
点击左侧类型查看字典
-
+ /> -->
@@ -115,24 +126,39 @@
-
+
取消
确认
-
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
取消
确认
-
+
@@ -165,20 +191,20 @@ const defaultDict = {
name: '',
desc: '',
sort: 1,
- type: null
+ type: null,
+ is_used: true,
+ pid:null
}
export default {
components: { Pagination, Treeselect },
data() {
return {
- dicttype: defaultDictType,
- dict: defaultDict,
- dictList: { count: 0 },
+ dicttype: Object.assign({}, defaultDictType),
+ dict: Object.assign({}, defaultDict),
+ search:'',
+ dictList: [],
listLoading: true,
- listQuery: {
- page: 1,
- page_size: 20
- },
+ listQuery: {},
dgV1: false,
dgT1: 'new',
rule1: {
@@ -192,7 +218,7 @@ export default {
},
filterDictTypeText: '',
treeLoding: false,
- dictTypeData: []
+ dictTypeData: [],
}
},
computed: {},
@@ -202,7 +228,6 @@ export default {
}
},
created() {
- this.getList()
this.getDictTypeList()
},
methods: {
@@ -212,20 +237,15 @@ export default {
return data.label.indexOf(value) !== -1
},
handleDictTypeClick(obj, node, vue) {
- this.listQuery.page = 1
this.listQuery.type = obj.id
this.getList()
},
getList() {
this.listLoading = true
- getDictList(this.listQuery).then(response => {
- if (response.code >= 200) {
- if (response.data.results) {
- this.dictList = response.data
- }
- this.listLoading = false
- }
- })
+ getDictList(this.listQuery).then(response =>{
+ this.dictList = genTree(response.data)
+ this.listLoading = false
+ }).catch(error=>{this.listLoading = false})
},
getDictTypeList() {
this.treeLoding = true
@@ -259,8 +279,8 @@ export default {
this.$refs['Form2'].clearValidate()
})
},
- handleEditDictType(val) {
- this.dicttype = val // copy obj
+ handleEditDictType(data) {
+ this.dicttype = Object.assign({}, data) // copy obj
this.dgT1 = 'edit'
this.dgV1 = true
this.$nextTick(() => {
@@ -277,7 +297,7 @@ export default {
.then(async() => {
const { code } = await deleteDict(scope.row.id)
if (code>=200){
- this.dictList.results.splice(scope.row.index, 1)
+ this.dictList.splice(scope.row.index, 1)
this.$message({
type: 'success',
message: '成功删除!'
@@ -294,30 +314,22 @@ export default {
const isEdit = this.dgT1 === 'edit'
if (isEdit) {
updateDictType(this.dicttype.id, this.dicttype).then(res => {
- if (res.code >= 200) {
this.getDictTypeList()
this.dgV1 = false
- this.$notify({
- title: '成功',
+ this.$message({
message: '编辑成功',
type: 'success',
- duration: 2000
})
- }
- })
+ }).catch(error=>{})
} else {
createDictType(this.dicttype).then(res => {
- if (res.code >= 200) {
this.getDictTypeList()
this.dgV1 = false
- this.$notify({
- title: '成功',
+ this.$message({
message: '新增成功',
type: 'success',
- duration: 2000
})
- }
- })
+ }).catch(error=>{})
}
} else {
return false
@@ -330,30 +342,22 @@ export default {
const isEdit = this.dgT2 === 'edit'
if (isEdit) {
updateDict(this.dict.id, this.dict).then(res => {
- if (res.code >= 200) {
this.getList()
this.dgV2 = false
- this.$notify({
- title: '成功',
+ this.$message({
message: '编辑成功',
type: 'success',
- duration: 2000
})
- }
- })
+ }).catch(error=>{})
} else {
createDict(this.dict).then(res => {
- if (res.code >= 200) {
this.getList()
this.dgV2 = false
- this.$notify({
- title: '成功',
+ this.$message({
message: '新增成功',
type: 'success',
- duration: 2000
})
- }
- })
+ }).catch(error=>{})
}
} else {
return false
diff --git a/server/apps/supervision/__init__.py b/server/apps/supervision/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/server/apps/supervision/admin.py b/server/apps/supervision/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/server/apps/supervision/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/server/apps/supervision/apps.py b/server/apps/supervision/apps.py
new file mode 100644
index 0000000..7da9691
--- /dev/null
+++ b/server/apps/supervision/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class SupervisionConfig(AppConfig):
+ name = 'supervision'
diff --git a/server/apps/supervision/migrations/0001_initial.py b/server/apps/supervision/migrations/0001_initial.py
new file mode 100644
index 0000000..5ab6657
--- /dev/null
+++ b/server/apps/supervision/migrations/0001_initial.py
@@ -0,0 +1,56 @@
+# Generated by Django 3.0.5 on 2021-03-11 00:33
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('system', '0007_auto_20210311_0833'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Content',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
+ ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
+ ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
+ ('name', models.CharField(max_length=100, verbose_name='名称')),
+ ('desc', models.CharField(max_length=1000, verbose_name='详情')),
+ ('can_doself', models.BooleanField(default=False, verbose_name='可随时主动报送')),
+ ('belong_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='content_belong_to', to='system.Organization', verbose_name='所属部门')),
+ ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='content_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
+ ('type', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='system.Dict', verbose_name='材料类型')),
+ ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='content_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
+ ],
+ options={
+ 'verbose_name': '报送清单',
+ 'verbose_name_plural': '报送清单',
+ },
+ ),
+ migrations.CreateModel(
+ name='Record',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
+ ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
+ ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
+ ('is_lock', models.BooleanField(default=False, verbose_name='是否锁住')),
+ ('is_yes', models.BooleanField(default=True, verbose_name='是否适用')),
+ ('note', models.TextField(verbose_name='说明')),
+ ('content', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='supervision.Content', verbose_name='材料内容')),
+ ],
+ options={
+ 'verbose_name': '上报记录',
+ 'verbose_name_plural': '上报记录',
+ },
+ ),
+ ]
diff --git a/server/apps/supervision/migrations/0002_remove_content_belong_to.py b/server/apps/supervision/migrations/0002_remove_content_belong_to.py
new file mode 100644
index 0000000..fe54334
--- /dev/null
+++ b/server/apps/supervision/migrations/0002_remove_content_belong_to.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.0.5 on 2021-03-11 00:39
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('supervision', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='content',
+ name='belong_to',
+ ),
+ ]
diff --git a/server/apps/supervision/migrations/__init__.py b/server/apps/supervision/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/server/apps/supervision/models.py b/server/apps/supervision/models.py
new file mode 100644
index 0000000..f7006c2
--- /dev/null
+++ b/server/apps/supervision/models.py
@@ -0,0 +1,37 @@
+from django.db import models
+from utils.model import BaseModel
+from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict
+# Create your models here.
+
+class Content(CommonAModel):
+ """
+ 资料清单
+ """
+ name = models.CharField('名称', max_length=100)
+ desc = models.CharField('详情', max_length=1000)
+ type = models.ForeignKey(Dict, verbose_name='材料类型', on_delete= models.DO_NOTHING)
+ can_doself = models.BooleanField('可随时主动报送', default=False)
+
+ class Meta:
+ verbose_name = '报送清单'
+ verbose_name_plural = verbose_name
+
+
+# class Task(CommonBModel):
+# name = models.CharField('名称', max_length=100)
+# pass
+
+
+class Record(BaseModel):
+ """
+ 上报记录
+ """
+ content = models.ForeignKey(Content, verbose_name='材料内容', on_delete=models.DO_NOTHING)
+ # task = models.ForeignKey(Task, verbose_name='关联任务', null=True, blank=True, on_delete=models.SET_NULL)
+ is_lock = models.BooleanField('是否锁住', default=False)
+ is_yes = models.BooleanField('是否适用', default=True)
+ note = models.TextField('说明')
+ class Meta:
+ verbose_name = '上报记录'
+ verbose_name_plural = verbose_name
+
\ No newline at end of file
diff --git a/server/apps/supervision/serializers.py b/server/apps/supervision/serializers.py
new file mode 100644
index 0000000..40ed624
--- /dev/null
+++ b/server/apps/supervision/serializers.py
@@ -0,0 +1,21 @@
+from rest_framework import serializers
+from .models import *
+from apps.system.serializers import OrganizationSerializer
+
+class ContentSerializer(serializers.ModelSerializer):
+ type_ = serializers.SerializerMethodField()
+ class Meta:
+ model = Content
+ fields = '__all__'
+
+ @staticmethod
+ def setup_eager_loading(queryset):
+ """ Perform necessary eager loading of data. """
+ queryset = queryset.select_related('type')
+ return queryset
+
+ def get_type_ (self, obj):
+ data = obj.type.name
+ if obj.type.pid:
+ data = obj.type.pid.name + '/' + data
+ return data
diff --git a/server/apps/supervision/tests.py b/server/apps/supervision/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/server/apps/supervision/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/server/apps/supervision/urls.py b/server/apps/supervision/urls.py
new file mode 100644
index 0000000..390942a
--- /dev/null
+++ b/server/apps/supervision/urls.py
@@ -0,0 +1,9 @@
+from django.urls import path, include
+from rest_framework import routers
+from .views import ContentViewSet
+
+router = routers.DefaultRouter()
+router.register('content', ContentViewSet, basename="content")
+urlpatterns = [
+ path('', include(router.urls))
+]
\ No newline at end of file
diff --git a/server/apps/supervision/views.py b/server/apps/supervision/views.py
new file mode 100644
index 0000000..c354aa8
--- /dev/null
+++ b/server/apps/supervision/views.py
@@ -0,0 +1,28 @@
+from django.shortcuts import render
+from rest_framework.mixins import ListModelMixin
+from rest_framework.viewsets import GenericViewSet, ModelViewSet
+from .models import *
+from .serializers import *
+from rest_framework.decorators import action
+from django.conf import settings
+from rest_framework import status
+from rest_framework.response import Response
+from apps.system.models import Organization
+from openpyxl import Workbook, load_workbook
+from django.db.models import Count
+from utils.pagination import PageOrNot
+from apps.system.mixins import CreateModelAMixin
+
+# Create your views here.
+
+class ContentViewSet(CreateModelAMixin, ModelViewSet):
+ """
+ 资料清单:增删改查
+ """
+ perms_map = {'get': '*', 'post': 'content_create',
+ 'put': 'content_update', 'delete': 'content_delete'}
+ queryset = Content.objects.all()
+ serializer_class = ContentSerializer
+ search_fields = ['name', 'desc']
+ filterset_fields = ['type']
+ ordering = ['type__sort', 'create_time']
\ No newline at end of file
diff --git a/server/apps/system/migrations/0007_auto_20210311_0833.py b/server/apps/system/migrations/0007_auto_20210311_0833.py
new file mode 100644
index 0000000..05b74a5
--- /dev/null
+++ b/server/apps/system/migrations/0007_auto_20210311_0833.py
@@ -0,0 +1,25 @@
+# Generated by Django 3.0.5 on 2021-03-11 00:33
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('system', '0006_auto_20201230_1730'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='file',
+ name='create_by',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='file_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'),
+ ),
+ migrations.AlterField(
+ model_name='file',
+ name='update_by',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='file_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'),
+ ),
+ ]
diff --git a/server/apps/system/migrations/0008_auto_20210311_0919.py b/server/apps/system/migrations/0008_auto_20210311_0919.py
new file mode 100644
index 0000000..8f7761f
--- /dev/null
+++ b/server/apps/system/migrations/0008_auto_20210311_0919.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.0.5 on 2021-03-11 01:19
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('system', '0007_auto_20210311_0833'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='dict',
+ name='is_used',
+ field=models.BooleanField(default=True, verbose_name='是否有效'),
+ ),
+ migrations.AddField(
+ model_name='historicaldict',
+ name='is_used',
+ field=models.BooleanField(default=True, verbose_name='是否有效'),
+ ),
+ ]
diff --git a/server/apps/system/models.py b/server/apps/system/models.py
index 1e63d48..ab9547f 100644
--- a/server/apps/system/models.py
+++ b/server/apps/system/models.py
@@ -155,6 +155,7 @@ class Dict(SoftModel):
sort = models.IntegerField('排序', default=1)
pid = models.ForeignKey('self', null=True, blank=True,
on_delete=models.SET_NULL, verbose_name='父')
+ is_used = models.BooleanField('是否有效', default=True)
history = HistoricalRecords()
class Meta:
@@ -170,9 +171,9 @@ class CommonAModel(SoftModel):
业务用基本表A,包含create_by, update_by字段
"""
create_by = models.ForeignKey(
- User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='create_by')
+ User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='%(class)s_create_by')
update_by = models.ForeignKey(
- User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='update_by')
+ User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='%(class)s_update_by')
class Meta:
abstract = True
@@ -182,11 +183,11 @@ class CommonBModel(SoftModel):
业务用基本表B,包含create_by, update_by, belong_to字段
"""
create_by = models.ForeignKey(
- User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='create_by')
+ User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='%(class)s_create_by')
update_by = models.ForeignKey(
- User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='update_by')
+ User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='%(class)s_update_by')
belong_to = models.ForeignKey(
- Organization, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='所属部门', related_name='belong_to')
+ Organization, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='所属部门', related_name='%(class)s_belong_to')
class Meta:
abstract = True
diff --git a/server/apps/system/views.py b/server/apps/system/views.py
index 5f43b33..6274a24 100644
--- a/server/apps/system/views.py
+++ b/server/apps/system/views.py
@@ -64,6 +64,9 @@ import datetime
class Login2View(APIView):
+ """
+ 邮箱验证码登录
+ """
authentication_classes = []
permission_classes = []
def post(self, request):
@@ -139,6 +142,16 @@ class DictViewSet(ModelViewSet):
search_fields = ['^name']
ordering_fields = ['id']
ordering = 'id'
+ def paginate_queryset(self, queryset):
+ """
+ 如果查询参数里没有page但有type或type__code时则不分页,否则请求分页
+ 也可用utils.pageornot方法
+ """
+ if self.paginator is None:
+ return None
+ elif (not self.request.query_params.get('page', None)) and ((self.request.query_params.get('type__code', None)) or (self.request.query_params.get('type', None))):
+ return None
+ return self.paginator.paginate_queryset(queryset, self.request, view=self)
class PositionViewSet(ModelViewSet):
diff --git a/server/requirements.txt b/server/requirements.txt
index 5e1431f..f38aec5 100644
Binary files a/server/requirements.txt and b/server/requirements.txt differ
diff --git a/server/server/settings.py b/server/server/settings.py
index 9d0a244..3f28a85 100644
--- a/server/server/settings.py
+++ b/server/server/settings.py
@@ -43,7 +43,8 @@ INSTALLED_APPS = [
"django_filters",
'apps.system',
'apps.crm',
- 'apps.ability'
+ 'apps.ability',
+ 'apps.supervision'
]
MIDDLEWARE = [
diff --git a/server/server/urls.py b/server/server/urls.py
index aff0004..7c0a0b3 100644
--- a/server/server/urls.py
+++ b/server/server/urls.py
@@ -58,16 +58,14 @@ class MyTokenObtainPairView(TokenViewBase):
urlpatterns = [
path('', TemplateView.as_view(template_name="index.html")),
path('api/admin/', admin.site.urls),
- path('api/login/', MyTokenObtainPairView.as_view(), name='my_login'),
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token2/', Login2View.as_view(), name='token_obtain_2'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/token/black/', LogoutView.as_view(), name='token_black'),
path('api/system/', include('apps.system.urls')),
path('api/ability/', include('apps.ability.urls')),
- path('api/docs/', include_docs_urls(title="接口文档",
- authentication_classes=[], permission_classes=[])),
+ path('api/supervision/', include('apps.supervision.urls')),
+ path('api/docs/', include_docs_urls(title="接口文档",authentication_classes=[], permission_classes=[])),
path('api/', include(router.urls)),
- url(r'^static/(?P.*)$', serve,
- {'document_root': settings.STATIC_ROOT}, name='static'),
+ url(r'^static/(?P.*)$', serve,{'document_root': settings.STATIC_ROOT}, name='static'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)