增加相关中间表的操作

This commit is contained in:
caoqianming 2021-04-30 09:46:03 +08:00
parent 27591e5fd3
commit fc1199bb31
16 changed files with 228 additions and 80 deletions

View File

@ -13,13 +13,25 @@
/**
* h5app-plus(nvue下也为app-plus)mp-weixinmp-alipay......
*/
this.$u.api.getUserInfo().then(res=>{
this.$u.vuex('vuex_user', res.data)
}).catch(e=>{
uni.reLaunch({
var that=this
// 小程序自动登录
uni.login({
provider: 'weixin',
success: function (loginRes) {
that.$u.api.wxmplogin({code:loginRes.code}).then(res=>{
that.$u.vuex('vuex_token', res.data.access)
}).catch(e=>{uni.reLaunch({
url:'/pages/login/login'
})
})
})})
}
});
// this.$u.api.getUserInfo().then(res=>{
// this.$u.vuex('vuex_user', res.data)
// }).catch(e=>{
// uni.reLaunch({
// url:'/pages/login/login'
// })
// })
},
}
</script>

View File

@ -19,6 +19,10 @@ const install = (Vue, vm) => {
let login = (params = {}) => vm.$u.post('/token/', params); //账户密码登录
// 将各个定义的接口名称统一放进对象挂载到vm.$u.api(因为vm就是this也即this.$u.api)下
let wxmplogin = (params = {}) => vm.$u.post('/wxmplogin/', params); //微信登录
let bindmp = (params = {}) => vm.$u.post('/system/user/bindwxmp/', params); //微信绑定
let getMyInspectTaskList = (params = {}) => vm.$u.get('/quality/subinspecttask/self/', params);
let getSubinspectTask = (id, params)=> vm.$u.get(`/quality/subinspecttask/${id}/`, params);
@ -43,6 +47,8 @@ const install = (Vue, vm) => {
getCode,
codeLogin,
login,
wxmplogin,
bindmp,
getMyInspectTaskList,
getSubinspectTask,
getSubtaskDepts,

View File

@ -13,7 +13,7 @@
<view style="margin-bottom: 12rpx;">
<u-grid :col="3" :border="false">
<u-grid-item v-for="(item, index) in grids" v-bind:key="index" @click="clickGrid(item)">
<u-icon :name="item.icon" :size="60" color="#2b85e4" size="72"></u-icon>
<u-icon :name="item.icon" color="#2b85e4" size="80"></u-icon>
<view class="grid-text">{{item.name}}</view>
</u-grid-item>
</u-grid>
@ -116,9 +116,9 @@
}).then(res => {
this.myinspecttaskList = res.data
}).catch(e => {
uni.reLaunch({
url:'/pages/login/login'
})
// uni.reLaunch({
// url:'/pages/login/login'
// })
})
},
openPage(path) {

View File

@ -48,7 +48,7 @@
</u-card> -->
<view v-show="currentIndex==0" style="text-align: right;">
<u-checkbox v-model="mutiSelect" @change="mutiSelectChange">多选</u-checkbox>
<u-checkbox v-model="mutiSelect" @change="mutiSelectChange" v-if="initData.leader==vuex_user.id">多选</u-checkbox>
<u-button type="primary" size="mini" style="margin-left:6rpx" @click="membersShow"
v-if="initData.leader==vuex_user.id && mutiSelect">指派给</u-button>
</view>

View File

@ -111,7 +111,7 @@
// console.log(sData.imgs)
this.$u.api.checkInspectRecord(sData.id, sData).then(res => {
this.$u.toast('提交成功');
uni.navigateBack({
})

View File

@ -1,9 +1,8 @@
<template>
<view class="wrap">
<view class="top"></view>
<u-image :src="imageURL" mode="widthFix"></u-image>
<view class="content">
<view style="text-align: center;font-weight: 500;font-size: 40rpx;">国检集团</view>
<view class="title">能力共享和质量监督平台</view>
<u-form :model="loginForm" :rules="rules" ref="uForm" :errorType="errorType">
<u-form-item label="邮箱号" prop="mail" label-width="150">
<u-input placeholder="请输入邮箱号" v-model="loginForm.mail" type="text">
@ -17,7 +16,7 @@
<!-- <button :style="[inputStyle]" class="getCaptcha">登录</button> -->
<!-- <u-gap height="0.5" bg-color="#bbb"></u-gap> -->
<view style="margin-top: 16rpx;">
<u-button @click="submit" type="primary" >登录</u-button>
<u-button @click="submit" type="warning" >登录</u-button>
</view>
<view class="alternative">
<navigator url="login_password" class="password" open-type="redirect">密码登录</navigator>
@ -43,6 +42,7 @@
export default {
data() {
return {
imageURL: 'http://testsearch.ctc.ac.cn:8000/media/default/banner3.jpg',
loginForm:{
mail:"",
msg:""
@ -85,6 +85,7 @@ export default {
},
onReady() {
this.$refs.uForm.setRules(this.rules);
uni.hideHomeButton()
},
computed: {
inputStyle() {

View File

@ -1,9 +1,10 @@
<template>
<view class="wrap">
<view class="top"></view>
<u-image :src="imageURL" mode="widthFix"></u-image>
<view class="content">
<view style="text-align: center;font-weight: 500;font-size: 40rpx;">国检集团</view>
<view class="title">能力共享和质量监督平台</view>
<!-- <view style="text-align: center;font-weight: 500;font-size: 40rpx;">国检集团</view>
<view class="title">能力共享和质量监督平台</view> -->
<u-form :model="loginForm" :rules="rules" ref="uForm" :errorType="errorType">
<u-form-item label="账户" prop="username" label-width="150">
<u-input placeholder="请输入账户" v-model="loginForm.username" type="text"></u-input>
@ -13,7 +14,7 @@
</u-form-item>
</u-form>
<view style="margin-top: 16rpx;">
<u-button @click="submit" type="primary" >登录</u-button>
<u-button @click="submit" type="warning" >登录</u-button>
</view>
</view>
</view>
@ -23,6 +24,7 @@
export default {
data() {
return {
imageURL: 'http://testsearch.ctc.ac.cn:8000/media/default/banner3.jpg',
loginForm:{
username:"",
password:""
@ -58,6 +60,7 @@ export default {
},
onReady() {
this.$refs.uForm.setRules(this.rules);
uni.hideHomeButton()
},
computed: {
inputStyle() {

View File

@ -13,7 +13,8 @@
</view>
<view class="u-flex-1">
<view class="u-font-18 u-p-b-20">{{vuex_user.name}}</view>
<view class="u-font-14 u-tips-color">{{vuex_user.username}}-{{vuex_user.dept_name}}</view>
<view class="u-font-14 u-type-info">{{vuex_user.username}}-{{vuex_user.dept_name}}</view>
<view class="u-font-14 u-tips-color" v-if="vuex_user.wxmp_openid">已绑定微信</view>
</view>
<!-- <view class="u-m-l-10 u-p-10">
<u-icon name="scan" color="#969799" size="28"></u-icon>
@ -40,6 +41,7 @@
<view class="u-m-t-20">
<u-cell-group>
<u-cell-item icon="weixin-fill" title="绑定微信" :arrow="false" @click="bindMP" v-if="!vuex_user.wxmp_openid"></u-cell-item>
<u-cell-item icon="close" title="退出" @click="Logout"></u-cell-item>
</u-cell-group>
</view>
@ -63,6 +65,20 @@
uni.redirectTo({
url: '/pages/login/login'
});
},
bindMP(){
uni.login({
provider: 'weixin',
success: (loginRes)=>{
this.$u.api.bindmp({code:loginRes.code}).then(res=>{
this.$u.toast('绑定成功');
this.$u.vuex('vuex_user.wxmp_openid', res.data.wxmp_openid)
uni.reLaunch({
url:'/pages/my/my'
})
}).catch(e=>{})
}
});
}
}
}

View File

@ -34,12 +34,12 @@ const store = new Vuex.Store({
vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {},
vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
// vuex_host: 'http://127.0.0.1:8000',
// vuex_api: 'http://127.0.0.1:8000/api',
// vuex_apifile: 'http://127.0.0.1:8000/api/file/',
vuex_api: 'http://127.0.0.1:8000/api',
vuex_apifile: 'http://127.0.0.1:8000/api/file/',
vuex_host: 'https://testsearch.ctc.ac.cn',
vuex_api: 'https://testsearch.ctc.ac.cn/api',
vuex_apifile: 'https://testsearch.ctc.ac.cn/api/file/',
// vuex_api: 'https://testsearch.ctc.ac.cn/api',
// vuex_apifile: 'https://testsearch.ctc.ac.cn/api/file/',
// 如果vuex_version无需保存到本地永久存储无需lifeData.vuex_version方式
// vuex_version: '1.0.1',

View File

@ -101,6 +101,17 @@ class InspectRecordDetailSerializer(serializers.ModelSerializer):
queryset = queryset.prefetch_related('imgs',)
return queryset
class InspectTeamSerializer(serializers.ModelSerializer):
member_ = UserSimpleSerializer(source='member', read_only=True)
class Meta:
model = InspectTeam
fields = '__all__'
@staticmethod
def setup_eager_loading(queryset):
queryset = queryset.select_related('member')
return queryset
class InspectDeptSerializer(serializers.ModelSerializer):
dept__name = serializers.CharField(source='dept.name', read_only=True)
leader = serializers.SerializerMethodField()

View File

@ -7,7 +7,7 @@ from django.shortcuts import render
from django.utils import timezone
from rest_framework import status
from rest_framework.decorators import action, permission_classes
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.mixins import DestroyModelMixin, ListModelMixin, RetrieveModelMixin
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ModelViewSet
@ -46,7 +46,7 @@ class InspectItemViewSet(PageOrNot, CreateUpdateCustomMixin, ModelViewSet):
ordering = ['sortnum', 'cate__sort', 'create_time']
class InspectTaskViewSet(CreateUpdateCustomMixin, ModelViewSet):
class InspectTaskViewSet(OptimizationMixin, CreateUpdateCustomMixin, ModelViewSet):
perms_map = {'get': '*', 'post': 'inspecttask_create',
'put': 'inspecttask_update', 'delete': 'inspecttask_delete'}
queryset = InspectTask.objects.all()
@ -84,6 +84,8 @@ class SubtaskViewSet(PageOrNot, CreateUpdateCustomMixin, OptimizationMixin, Mode
def get_queryset(self):
queryset = self.queryset
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset)
if has_permission('inspecttask_create', self.request.user):
return queryset
else:
@ -111,6 +113,7 @@ class SubtaskViewSet(PageOrNot, CreateUpdateCustomMixin, OptimizationMixin, Mode
instance = self.get_object()
if request.data.get('name', None):
instance.name = request.data.get('name')
instance.update_by = request.user
instance.save()
return Response(status=status.HTTP_200_OK)
@ -164,11 +167,10 @@ class SubtaskViewSet(PageOrNot, CreateUpdateCustomMixin, OptimizationMixin, Mode
records.append(InspectRecord(**r))
for member in request.data['members']:
mmember = User.objects.get(pk=member)
if not InspectTeam.objects.filter(member=mmember, subtask=obj).exists():
data = {}
data['member'] = mmember
data['subtask'] = obj
members.append(InspectTeam(**data))
data = {}
data['member'] = mmember
data['subtask'] = obj
members.append(InspectTeam(**data))
InspectTeam.objects.bulk_create(members)
InspectDept.objects.bulk_create(depts)
InspectRecord.objects.bulk_create(records)
@ -176,13 +178,31 @@ class SubtaskViewSet(PageOrNot, CreateUpdateCustomMixin, OptimizationMixin, Mode
return Response('组织和成员不能为空', status=status.HTTP_400_BAD_REQUEST)
class InspectDeptViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
class InspectDeptViewSet(OptimizationMixin, ListModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
"""
子任务对检查组织的提交
子任务涉及组织表
"""
perms_map = {'get':'*'}
perms_map = {'get':'*', 'put':'inspecttask_update', 'post':'inspecttask_update', 'delete':'inspecttask_update'}
queryset = InspectDept.objects.all()
serializer_class = InspectDeptSerializer
filterset_fields = ['subtask']
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
obj = serializer.save(create_time=timezone.now())
records = []
if not InspectRecord.objects.filter(dept=obj.dept, subtask=obj.subtask).exists():
for i in InspectItem.objects.filter(is_deleted=False, template=obj.subtask.inspecttask.template):
r = {}
r['dept'] = obj.dpet
r['item'] = i
r['subtask'] = obj.subtask
r['create_by'] = request.user
records.append(InspectRecord(**r))
InspectRecord.objects.bulk_create(records)
return Response(status=status.HTTP_201_CREATED)
@action(methods=['put'], detail=True, perms_map = {'put':'inspectrecord_update'},
permission_classes=[IsAdminUser|IsSubInspectTaskLeader])
@ -205,24 +225,36 @@ class InspectDeptViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
组长对该组织检查结果提交
"""
obj = self.get_object()
if InspectRecord.objects.filter(checked=False, subtask=obj.subtask, dept=obj.dept).exists():
return Response('存在未完成检查记录', status=status.HTTP_400_BAD_REQUEST)
if obj.state == '检查中':
if InspectRecord.objects.filter(checked=False, subtask=obj.subtask, dept=obj.dept).exists():
return Response('存在未完成检查记录', status=status.HTTP_400_BAD_REQUEST)
else:
if 'note' in request.data and request.data['note']:
obj.note = request.data['note']
obj.state = '已提交'
obj.save()
# 更新主任务和子任务状态
if not InspectDept.objects.filter(subtask=obj.subtask).exclude(state='已提交').exists():
obj.subtask.state = '已完成'
obj.subtask.save()
if not SubInspectTask.objects.filter(inspecttask=obj.subtask.inspecttask).exclude(state='已完成').exists():
obj.subtask.inspecttask.state = '已完成'
obj.subtask.inspecttask.save()
return Response(InspectDeptSerializer(instance=obj).data, status=status.HTTP_200_OK)
else:
if 'note' in request.data and request.data['note']:
obj.note = request.data['note']
obj.state = '已提交'
obj.save()
# 更新主任务和子任务状态
if not InspectDept.objects.filter(subtask=obj.subtask).exclude(state='已提交').exists():
obj.subtask.state = '已完成'
obj.subtask.save()
if not SubInspectTask.objects.filter(inspecttask=obj.subtask.inspecttask).exclude(state='已完成').exists():
obj.subtask.inspecttask.state = '已完成'
obj.subtask.inspecttask.save()
return Response(InspectDeptSerializer(instance=obj).data, status=status.HTTP_200_OK)
return Response('检查状态错误', status=status.HTTP_400_BAD_REQUEST)
class InspectRecordViewSet(PageOrNot, ModelViewSet):
class InspectTeamViewSet(OptimizationMixin, ListModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
"""
子任务涉及组员表
"""
perms_map = {'get':'*', 'put':'inspecttask_update', 'post':'inspecttask_update', 'delete':'inspecttask_update'}
queryset = InspectTeam.objects.all()
serializer_class = InspectTeamSerializer
filterset_fields = ['subtask']
class InspectRecordViewSet(OptimizationMixin, PageOrNot, ModelViewSet):
perms_map = {'get': '*', 'post': 'inspectrecord_create',
'put': 'inspectrecord_update', 'delete': 'inspectrecord_delete'}
queryset = InspectRecord.objects.all()

View File

@ -0,0 +1,24 @@
# Generated by Django 3.0.5 on 2021-04-29 07:49
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('system', '0016_auto_20210331_1040'),
]
operations = [
migrations.CreateModel(
name='UserThird',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.CharField(choices=[('wx_mp', '微信小程序')], default='wx_mp', max_length=50, verbose_name='类型')),
('openid', models.CharField(blank=True, max_length=200, null=True, verbose_name='第三方账号')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='third_user', to=settings.AUTH_USER_MODEL, verbose_name='关联账户')),
],
),
]

View File

@ -217,3 +217,16 @@ class File(CommonAModel):
class Message(BaseModel):
mail = models.CharField('发送邮箱', max_length=200)
msg = models.CharField('验证码', max_length=200)
class UserThird(models.Model):
"""
第三方账户
"""
type_choices = (
('wx_mp', '微信小程序'),
)
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='关联账户', related_name='third_user')
type = models.CharField('类型', max_length=50, choices=type_choices, default='wx_mp')
openid = models.CharField('第三方账号', null=True, blank=True, max_length=200)

View File

@ -1,9 +1,12 @@
import logging
from django.conf import settings
from django.contrib.auth.hashers import check_password, make_password
from django.contrib.auth.models import UserManager
from django.core.cache import cache
from django.db.models import Count
from django.http import request
from django.http.response import JsonResponse
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status
from rest_framework.decorators import (action, authentication_classes,
@ -13,18 +16,19 @@ from rest_framework.mixins import (CreateModelMixin, DestroyModelMixin,
ListModelMixin, RetrieveModelMixin,
UpdateModelMixin)
from rest_framework.pagination import PageNumberPagination
from rest_framework.parsers import (FileUploadParser, JSONParser,
MultiPartParser)
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from rest_framework_simplejwt.tokens import RefreshToken
from utils.queryset import get_child_queryset2
from django.db.models import Count
from utils.pagination import PageOrNot
from utils.queryset import get_child_queryset2
from .filters import UserFilter
from .models import (Dict, DictType, File, Message, Organization, Permission,
Position, Role, User)
Position, Role, User, UserThird)
from .permission import RbacPermission, get_permission_list
from .permission_data import RbacFilterSet
from .serializers import (DictSerializer, DictTypeSerializer, FileSerializer,
@ -32,7 +36,9 @@ from .serializers import (DictSerializer, DictTypeSerializer, FileSerializer,
PositionSerializer, RoleSerializer,
UserCreateSerializer, UserListSerializer,
UserModifySerializer)
import requests
import json
from rest_framework.exceptions import AuthenticationFailed
logger = logging.getLogger('log')
# logger.info('请求成功! response_code:{}response_headers:{}response_body:{}'.format(response_code, response_headers, response_body[:251]))
# logger.error('请求出错:{}'.format(error))
@ -308,9 +314,14 @@ class UserViewSet(PageOrNot, ModelViewSet):
'avatar': request._request._current_scheme_host + user.avatar,
'perms': perms,
}
try:
user = UserThird.objects.get(user=user,type='wx_mp').user
data['wxmp_openid'] = user.openid
except:
pass
return Response(data)
@action(methods=['put'], detail=True, url_name='userpw_reset', perms_map={'put':'userpw_reset'})
@action(methods=['put'], detail=True, url_name='userpw_reset', permission_classes=[IsAuthenticated])
def resetpw(self, request, pk=None):
"""
重置密码
@ -322,9 +333,43 @@ class UserViewSet(PageOrNot, ModelViewSet):
return Response('密码已重置为0000', status=status.HTTP_200_OK)
return Response('权限不足', status=status.HTTP_400_BAD_REQUEST)
from django.conf import settings
from rest_framework.parsers import (FileUploadParser, JSONParser,
MultiPartParser)
@action(methods=['post'], detail=False, permission_classes=[IsAuthenticated])
def bindwxmp(self, request, pk=None):
"""
绑定微信
"""
code = request.data['code']
info = requests.get('https://api.weixin.qq.com/sns/jscode2session?appid='+settings.WX_APPID+'&secret='+settings.WX_APPSECRET+'&js_code=' +
code+'&grant_type=authorization_code').content.decode('utf-8')
info = json.loads(info)
openid = info['openid']
UserThird.objects.get_or_create(openid=openid, type='wx_mp', user=request.user, defaults={'openid':openid, 'user':request.user, 'type':'wx_mp'})
return Response({'wxmp_openid':openid},status=status.HTTP_200_OK)
class WXMPlogin(APIView):
authentication_classes=[]
permission_classes=[]
def post(self,request):
"""
微信登录
"""
code = request.data['code']
info = requests.get('https://api.weixin.qq.com/sns/jscode2session?appid='+settings.WX_APPID+'&secret='+settings.WX_APPSECRET+'&js_code=' +
code+'&grant_type=authorization_code').content.decode('utf-8')
info = json.loads(info)
openid = info['openid']
session_key = info['session_key']
try:
user = UserThird.objects.get(openid=openid,type='wx_mp').user
return Response(get_tokens_for_user(user), status=status.HTTP_200_OK)
except:
raise AuthenticationFailed
class FileViewSet(ModelViewSet):
@ -357,4 +402,6 @@ class FileViewSet(ModelViewSet):
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.save()

View File

@ -262,3 +262,6 @@ LOGGING = {
},
}
}
WX_APPID = 'wx0605643660b9b2ec'
WX_APPSECRET = '94527cb8cb8d696f1af3b2b99b7fb01d'

View File

@ -30,34 +30,14 @@ from django.conf.urls import url
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenViewBase
from apps.system.permission import get_permission_list
class MyloginSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
data = super().validate(attrs)
from apps.system.views import WXMPlogin
refresh = self.get_token(self.user)
data['refresh'] = str(refresh)
data['access'] = str(refresh.access_token)
user = self.user
perms = get_permission_list(user)
data['user'] = {
'id': user.id,
'username': user.username,
'name': user.name,
'roles': user.roles.all().values_list('name', flat=True),
# 'avatar': request._request._current_scheme_host + '/media/' + str(user.image),
'avatar': user.avatar,
'perms': perms,
}
return data
class MyTokenObtainPairView(TokenViewBase):
serializer_class = MyloginSerializer
urlpatterns = [
path('', TemplateView.as_view(template_name="index.html")),
path('api/admin/', admin.site.urls),
path('api/wxmplogin/',WXMPlogin.as_view()),
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'),