diff --git a/client/src/api/contacts.js b/client/src/api/contacts.js new file mode 100644 index 0000000..4143a90 --- /dev/null +++ b/client/src/api/contacts.js @@ -0,0 +1,45 @@ +import request from '@/utils/request' + + + +export function getCtAll(query) { + return request({ + url: '/info/contact/', + method: 'get', + params: query + }) + } + + + export function getCt(id) { + return request({ + url: `/info/contact/${id}/`, + method: 'get' + }) + } + + + export function updateContact(id, data) { + return request({ + url: `/info/contact/${id}/`, + method: 'put', + data + }) + } + + export function createCt(data) { + return request({ + url: `/info/contact/`, + method: 'post', + data + }) + } + + + + export function del_contact(id) { + return request({ + url: `/info/contact/${id}/`, + method: 'delete' + }) + } diff --git a/client/src/api/review.js b/client/src/api/review.js new file mode 100644 index 0000000..24cb412 --- /dev/null +++ b/client/src/api/review.js @@ -0,0 +1,51 @@ +import request from '@/utils/request' + + + +export function getRsAll(query) { + return request({ + url: '/info/ar/', + method: 'get', + params: query + }) + } + +export function getMyRs(query) { + return request({ + url: '/info/ar/review_info/', + method: 'get', + params: query + }) +} + + export function getRs(id) { + return request({ + url: `/info/ar/${id}/`, + method: 'get' + }) + } + + + export function updateRs(id, data) { + return request({ + url: `/info/ar/${id}/`, + method: 'put', + data + }) + } + + export function createRs(data) { + return request({ + url: `/info/ar/`, + method: 'post', + data + }) + } + + + export function delRs(id) { + return request({ + url: `/info/ar/${id}/`, + method: 'delete' + }) + } diff --git a/client/src/router/index.js b/client/src/router/index.js index 8f0a33a..f520003 100644 --- a/client/src/router/index.js +++ b/client/src/router/index.js @@ -407,52 +407,52 @@ export const asyncRoutes = [ ] }, //信息收集 - // { - // path: '/infoCollect', - // component: Layout, - // redirect: '/infoCollect/', - // name: 'informationCollect', - // meta: { title: '信息收集', icon: 'PT', perms: ['infoCollect'] }, - // alwaysShow: true, - // children: [ - // { - // path: 'reviewStatus', - // name: 'reviewStatus', - // component: () => import('@/views/informatiomCollect/reviewStatus.vue'), - // meta: { title: '评审情况', perms: ['infoCollect_RS'] } - // }, - // { - // path: 'qualityCommend', - // name: 'qualityCommend', - // component: () => import('@/views/informatiomCollect/qualityCommend.vue'), - // meta: { title: '质量活动', perms: ['infoCollect_QC'] } - // }, - // { - // path: 'qualityActive.', - // name: 'qualityActive.', - // component: () => import('@/views/informatiomCollect/qualityActive.vue'), - // meta: { title: '质量表彰', perms: ['infoCollect_QA'] } - // }, - // { - // path: 'laboratoryContact', - // name: 'laboratoryContact', - // component: () => import('@/views/informatiomCollect/laboratoryContact.vue'), - // meta: { title: '实验室联系方式', perms: ['infoCollect_LC'] } - // }, - // { - // path: 'externalAuditor', - // name: 'externalAuditor', - // component: () => import('@/views/informatiomCollect/externalAuditor.vue'), - // meta: { title: '外审员情况', perms: ['infoCollect_EA'] } - // }, - // { - // path: 'inspectionStats', - // name: 'inspectionStats', - // component: () => import('@/views/informatiomCollect/inspectionStats.vue'), - // meta: { title: '检验检测统计', perms: ['infoCollect_IS'] } - // }, - // ] - // }, + { + path: '/infoCollect', + component: Layout, + redirect: '/infoCollect/', + name: 'informationCollect', + meta: { title: '信息收集', icon: 'PT', perms: ['infoCollect'] }, + alwaysShow: true, + children: [ + { + path: 'reviewStatus', + name: 'reviewStatus', + component: () => import('@/views/informatiomCollect/reviewStatus.vue'), + meta: { title: '评审情况', perms: ['infoCollect_RS'] } + }, + { + path: 'qualityCommend', + name: 'qualityCommend', + component: () => import('@/views/informatiomCollect/qualityCommend.vue'), + meta: { title: '质量表彰', perms: ['infoCollect_QC'] } + }, + { + path: 'qualityActive.', + name: 'qualityActive.', + component: () => import('@/views/informatiomCollect/qualityActive.vue'), + meta: { title: '质量活动', perms: ['infoCollect_QA'] } + }, + { + path: 'laboratoryContact', + name: 'laboratoryContact', + component: () => import('@/views/informatiomCollect/laboratoryContact.vue'), + meta: { title: '实验室联系方式', perms: ['infoCollect_LC'] } + }, + { + path: 'externalAuditor', + name: 'externalAuditor', + component: () => import('@/views/informatiomCollect/externalAuditor.vue'), + meta: { title: '外审员情况', perms: ['infoCollect_EA'] } + }, + { + path: 'inspectionStats', + name: 'inspectionStats', + component: () => import('@/views/informatiomCollect/inspectionStats.vue'), + meta: { title: '检验检测统计', perms: ['infoCollect_IS'] } + }, + ] + }, { path: '/test', component: Layout, diff --git a/client/src/views/informatiomCollect/laboratoryContact.vue b/client/src/views/informatiomCollect/laboratoryContact.vue index c7a3911..6523b71 100644 --- a/client/src/views/informatiomCollect/laboratoryContact.vue +++ b/client/src/views/informatiomCollect/laboratoryContact.vue @@ -7,27 +7,49 @@ - + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + @@ -35,13 +57,42 @@ - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
取消 @@ -66,16 +116,38 @@ import Pagination from "@/components/Pagination"; // secondary package based on import Treeselect from "@riophae/vue-treeselect"; import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import { getDictList, getDictTypeList } from "@/api/dict"; +import {createCt, del_contact, updateContact, getCtAll, getCt } from "@/api/contacts"; import { upUrl, upHeaders } from "@/api/file"; const defaultContent = { - name: "", - description: "", - file: null + name: "", + address: "", + header: "", + tel: "", + email: "", + head_technology: "", + tel_technology: "", + email_technology: "", + head_quality: "", + tel_quality: "", + email_quality: "" }; export default { components: { Pagination, Treeselect }, - data() { + data(){ return { + form: { + name: "", + address: "", + header: "", + tel: "", + email: "", + head_technology: "", + tel_technology: "", + email_technology: "", + head_quality: "", + tel_quality: "", + email_quality: "" + }, upHeaders: upHeaders(), upUrl: upUrl(), fileList: [], @@ -142,9 +214,18 @@ export default { }, getList() { + this.listLoading = true; + this.tableData.results =[]; + this.tableData.count =0; + getCtAll(this.listQuery).then((response) => { + console.log(response); + if (response.data) { + this.tableData = response.data; + } + this.listLoading = false; + }); }, - - + handleFilter() { this.listQuery.page = 1; this.getList(); @@ -181,9 +262,9 @@ export default { type: "error", }) .then(async () => { - // await deleteDoc(scope.row.id); - // this.getList(); - // this.$message.success("成功"); + await del_contact(scope.row.id); + this.getList(); + this.$message.success("成功"); }) .catch((err) => { console.error(err); @@ -194,10 +275,24 @@ export default { if (valid) { const isEdit = this.dialogType === "edit"; if (isEdit) { - console.log(this.Content) - + console.log(this.Content); + updateContact(this.Content.id, this.Content).then((response) => { + if (response.data) { + this.tableData = response.data; + } + this.listLoading = false; + this.dialogVisible = false; + this.getTableList(); + }); } else { - + createCt(this.Content).then((response) => { + if (response.data) { + this.tableData = response.data; + } + this.listLoading = false; + this.dialogVisible = false; + this.getTableList(); + }); } } else { return false; @@ -205,6 +300,8 @@ export default { }); }, }, + }; +@/api/contacts \ No newline at end of file diff --git a/client/src/views/informatiomCollect/qualityActive.vue b/client/src/views/informatiomCollect/qualityActive.vue index d943632..dc1c9b8 100644 --- a/client/src/views/informatiomCollect/qualityActive.vue +++ b/client/src/views/informatiomCollect/qualityActive.vue @@ -28,11 +28,11 @@ --> diff --git a/client/src/views/informatiomCollect/qualityCommend.vue b/client/src/views/informatiomCollect/qualityCommend.vue index 0c61b8b..2b551b7 100644 --- a/client/src/views/informatiomCollect/qualityCommend.vue +++ b/client/src/views/informatiomCollect/qualityCommend.vue @@ -26,7 +26,7 @@ - + @@ -56,10 +56,10 @@ - + - + @@ -70,7 +70,7 @@ - + - - + + - - + + - + + + + + + + + + + + + + + + + + @@ -35,13 +51,65 @@ - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
取消 @@ -66,16 +133,47 @@ import Pagination from "@/components/Pagination"; // secondary package based on import Treeselect from "@riophae/vue-treeselect"; import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import { getDictList, getDictTypeList } from "@/api/dict"; +import { createRs, delRs, updateRs, getMyRs, getRs } from "@/api/review"; import { upUrl, upHeaders } from "@/api/file"; const defaultContent = { name: "", - description: "", - file: null + qualification_name: "", + judging_method: "", + judging_type: "", + add_param: "", + review_date: "", + now_count: "", + add_count: "" }; export default { components: { Pagination, Treeselect }, - data() { + data(){ return { + form: { + name: "", + qualification_name: "", + judging_method: "", + judging_type: "", + add_param: "", + review_date: "", + now_count: "", + add_count: "" + }, + method_options: [{value: 0,label: '文审'},{value: 10,label: '现场'}], + type_options: [{ + value: 0, + label: '初次'}, + { + value: 10, + label: '扩项'}, + { + value: 20, + label: '变更'},{ + value: 30, + label: '复评'}, + { + value: 40, + label: '迁址'}], upHeaders: upHeaders(), upUrl: upUrl(), fileList: [], @@ -95,7 +193,7 @@ export default { name: [{ required: true, message: "请输入名称", trigger: "blur" }], }, filterOrgText: "", - tableHeight:null, + tableHeight: null, }; }, computed: {}, @@ -105,19 +203,19 @@ export default { }, }, created() { - + }, mounted() { - let that = this; + let that = this; let height1 = document.getElementsByClassName('app-main')[0].clientHeight; let height2 = document.getElementsByClassName('elHeader')[0].clientHeight; that.tableHeight = height1 - height2 - 70; console.log(that.tableHeight) that.getList(); - + }, methods: { - getTableList() { + getTableList() { this.getList(); }, handlePreview(file) { @@ -142,9 +240,18 @@ export default { }, getList() { + this.listLoading = true; + this.tableData.results =[]; + this.tableData.count =0; + getMyRs(this.listQuery).then((response) => { + console.log(response); + if (response.data) { + this.tableData = response.data; + } + this.listLoading = false; + }); }, - - + handleFilter() { this.listQuery.page = 1; this.getList(); @@ -181,9 +288,9 @@ export default { type: "error", }) .then(async () => { - // await deleteDoc(scope.row.id); - // this.getList(); - // this.$message.success("成功"); + await delRs(scope.row.id); + this.getList(); + this.$message.success("成功"); }) .catch((err) => { console.error(err); @@ -195,9 +302,23 @@ export default { const isEdit = this.dialogType === "edit"; if (isEdit) { console.log(this.Content) - + updateRs(this.Content.id, this.Content).then((response) => { + if (response.data) { + this.tableData = response.data; + } + this.listLoading = false; + this.dialogVisible = false; + this.getTableList(); + }); } else { - + createRs(this.Content).then((response) => { + if (response.data) { + this.tableData = response.data; + } + this.listLoading = false; + this.dialogVisible = false; + this.getTableList(); + }); } } else { return false; @@ -205,7 +326,7 @@ export default { }); }, }, + }; - + diff --git a/server/apps/information/migrations/0012_auto_20240402_0939.py b/server/apps/information/migrations/0012_auto_20240402_0939.py new file mode 100644 index 0000000..7d174e0 --- /dev/null +++ b/server/apps/information/migrations/0012_auto_20240402_0939.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.12 on 2024-04-02 01:39 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0023_alter_user_first_name'), + ('information', '0011_rename_organizational_units_qualityactivities_orgunits'), + ] + + operations = [ + migrations.AlterField( + model_name='qualityactivities', + name='department', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='system.organization', verbose_name='组织单位'), + ), + migrations.AlterField( + model_name='qualitycommendation', + name='department', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='system.organization', verbose_name='所属单位'), + ), + ] diff --git a/server/apps/information/migrations/0013_abilityreview_department.py b/server/apps/information/migrations/0013_abilityreview_department.py new file mode 100644 index 0000000..0da8a79 --- /dev/null +++ b/server/apps/information/migrations/0013_abilityreview_department.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2024-04-02 02:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0023_alter_user_first_name'), + ('information', '0012_auto_20240402_0939'), + ] + + operations = [ + migrations.AddField( + model_name='abilityreview', + name='department', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='system.organization', verbose_name='所属单位'), + ), + ] diff --git a/server/apps/information/migrations/0014_contact_department.py b/server/apps/information/migrations/0014_contact_department.py new file mode 100644 index 0000000..1a2b3ce --- /dev/null +++ b/server/apps/information/migrations/0014_contact_department.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2024-04-02 06:55 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0023_alter_user_first_name'), + ('information', '0013_abilityreview_department'), + ] + + operations = [ + migrations.AddField( + model_name='contact', + name='department', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='system.organization', verbose_name='组织单位'), + ), + ] diff --git a/server/apps/information/migrations/0015_remove_contact_department.py b/server/apps/information/migrations/0015_remove_contact_department.py new file mode 100644 index 0000000..4f9de37 --- /dev/null +++ b/server/apps/information/migrations/0015_remove_contact_department.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.12 on 2024-04-02 06:59 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('information', '0014_contact_department'), + ] + + operations = [ + migrations.RemoveField( + model_name='contact', + name='department', + ), + ] diff --git a/server/apps/information/migrations/0016_auto_20240402_1558.py b/server/apps/information/migrations/0016_auto_20240402_1558.py new file mode 100644 index 0000000..48ffc9e --- /dev/null +++ b/server/apps/information/migrations/0016_auto_20240402_1558.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.12 on 2024-04-02 07:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('information', '0015_remove_contact_department'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='email', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='负责人邮箱'), + ), + migrations.AlterField( + model_name='contact', + name='email_quality', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='质量负责人邮箱'), + ), + migrations.AlterField( + model_name='contact', + name='email_technology', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='技术负责人邮箱'), + ), + ] diff --git a/server/apps/information/models.py b/server/apps/information/models.py index e0cb825..7a52ad1 100644 --- a/server/apps/information/models.py +++ b/server/apps/information/models.py @@ -18,7 +18,7 @@ class AbilityReview(models.Model): review_date = models.DateField(verbose_name='评审日期', null=True) now_count = models.IntegerField(default=0, verbose_name='现有场所数量') add_count = models.IntegerField(default=0, verbose_name='新增场所数量') - + department = models.ForeignKey(Organization, on_delete=models.PROTECT, null=True, verbose_name='所属单位') class Meta: verbose_name = '评审情况' db_table = 'ability_review' @@ -32,7 +32,7 @@ class QualityCommendation(models.Model): awardee_people = models.CharField(max_length=20, verbose_name='获奖人', null=True) awarded_by = models.CharField(max_length=20, verbose_name='颁奖单位') awarded_date = models.DateField(verbose_name='获奖日期', null=True) - department = models.ForeignKey(Organization, on_delete=models.CASCADE, null=True, verbose_name='所属单位') + department = models.ForeignKey(Organization, on_delete=models.PROTECT, null=True, verbose_name='所属单位') class Meta: verbose_name = '质量表彰' @@ -49,7 +49,7 @@ class QualityActivities(models.Model): participations = models.IntegerField(verbose_name='活动参与单位数量', null=True, blank=True) function = models.CharField(max_length=100, verbose_name='活动中发挥的作用', null=True) earnings = models.FloatField(verbose_name='活动收益', null=True) - department = models.ForeignKey(Organization, on_delete=models.CASCADE, null=True, verbose_name='组织单位') + department = models.ForeignKey(Organization, on_delete=models.PROTECT, null=True, verbose_name='组织单位') class Meta: verbose_name = '质量活动' @@ -61,14 +61,13 @@ class Contact(models.Model): address = models.CharField(max_length=100, verbose_name='地址') header = models.CharField(max_length=20, verbose_name='负责人') tel = models.CharField(max_length=20, verbose_name='负责人电话') - email = models.CharField(max_length=50, verbose_name='负责人邮箱', null=True) + email = models.CharField(max_length=50, verbose_name='负责人邮箱', null=True, blank=True) head_technology = models.CharField(max_length=50, verbose_name='技术负责人') tel_technology = models.CharField(max_length=20, verbose_name='技术负责人电话') - email_technology = models.CharField(max_length=50, verbose_name='技术负责人邮箱', null=True) + email_technology = models.CharField(max_length=50, verbose_name='技术负责人邮箱', null=True, blank=True) head_quality = models.CharField(max_length=50, verbose_name='质量负责人') tel_quality = models.CharField(max_length=20, verbose_name='质量负责人电话') - email_quality = models.CharField(max_length=50, verbose_name='质量负责人邮箱', null=True) - + email_quality = models.CharField(max_length=50, verbose_name='质量负责人邮箱', null=True, blank=True) class Meta: verbose_name = '实验室联系方式' db_table = 'contact' diff --git a/server/apps/information/views.py b/server/apps/information/views.py index 9b1d295..99d17df 100644 --- a/server/apps/information/views.py +++ b/server/apps/information/views.py @@ -7,8 +7,6 @@ from django.conf import settings from rest_framework.decorators import action from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet -# from .models import AbilityReview, QualityCommendation, QualityActivities, Contact, ExternalAuditors -# from .serializers import AbilityReviewSerializer, QualityCommendationSerializer, QualityActivitiesSerializer,ContactSerializer, ExternalAuditorsSerializer from utils.queryset import get_child_queryset2 from rest_framework.response import Response from apps.system.permission import has_permission @@ -21,19 +19,31 @@ from .serializers import * from datetime import datetime import os - -class AbilityReviewViewSet( mixins.CreateModelMixin, - mixins.ListModelMixin, - mixins.DestroyModelMixin, - mixins.UpdateModelMixin, - viewsets.GenericViewSet): + +class AbilityReviewViewSet(ModelViewSet): queryset = AbilityReview.objects.all() serializer_class = AbilityReviewSerializer - #自定义查询 - def get_queryset(self): - pass - + # 查询子以及已经本公司的评审情况 + @action(detail=False, methods=['get']) + def review_info(self, request, *args, **kwargs): + father_dept = request.user.dept + child_dept = get_child_queryset2(father_dept) + query = AbilityReview.objects.filter(department__in=child_dept) + serializer = AbilityReviewSerializer(query, many=True) + data = {'count':len(serializer.data), 'results':serializer.data} + return Response(data, status = status.HTTP_200_OK) + + def create(self, request): + if Organization.objects.filter(name=request.data['name']).exists(): + department_id = Organization.objects.filter(name=request.data['name']).first().id + request.data['department'] = department_id + serializer = self.get_serializer(data=request.data) + if serializer.is_valid(raise_exception=True): + serializer.save() + return Response(serializer.data, status = status.HTTP_201_CREATED) + else: + raise ParseError("公司名称不存在") class ImpMixin: def get_queryset(self): mydept = self.request.user.dept @@ -91,29 +101,27 @@ class ImpMixin: return Response({'uploaded': 'File uploaded successfully'}, status=status.HTTP_201_CREATED) - -class QualityCommendationViewSet(ImpMixin, ModelViewSet): +class QualityCommendationViewSet(ModelViewSet): queryset = QualityCommendation.objects.all() serializer_class = QualityCommendationSerializer - perms_map = {"get": "*", "post": "*", "put": "*", "delete": "*"} - def create(self): - if Organization.objects.filter(name=self.request.data['awardee_company']).exists(): - department_id = Organization.objects.filter(name=self.request.data['awardee_company']).first().id - self.request.data['department'] = department_id - serializer = self.get_serializer(data=self.request.data) + def create(self, request, *args, **kwargs): + if Organization.objects.filter(name=request.data['awardee_company']).exists(): + department_id = Organization.objects.filter(name=request.data['awardee_company']).first().id + request.data['department'] = department_id + serializer = self.get_serializer(data=request.data) if serializer.is_valid(raise_exception=True): serializer.save() return Response(serializer.data, status = status.HTTP_201_CREATED) # 人名存在重复 else: - raise ParseError("部门不存在") + raise ParseError("获奖单位不存在") - # 导入表格 - @action(methods=['post'], detail=False) - @transaction.atomic - def imp(self, request, *args, **kwargs): - return self.gen_imp_view(request, 5, QualityCommendationSerializer, 'qt') + # # 导入表格 + # @action(methods=['post'], detail=False) + # @transaction.atomic + # def imp(self, request, *args, **kwargs): + # return self.gen_imp_view(request, 5, QualityCommendationSerializer, 'qt') #构造导入的数据格式 def build_qt_data(self, sheet): @@ -160,10 +168,10 @@ class QualityActivitiesViewSet(ModelViewSet): serializer_class = QualityActivitiesSerializer def create(self, request): - if Organization.objects.filter(name=self.request.data['orgunits']).exists(): - department_id = Organization.objects.filter(name=self.request.data['orgunits']).first().id - self.request.data['department'] = department_id - serializer = self.get_serializer(data=self.request.data) + if Organization.objects.filter(name=request.data['orgunits']).exists(): + department_id = Organization.objects.filter(name=request.data['orgunits']).first().id + request.data['department'] = department_id + serializer = self.get_serializer(data=request.data) if serializer.is_valid(raise_exception=True): serializer.save() return Response(serializer.data, status = status.HTTP_201_CREATED)