小程序端
This commit is contained in:
parent
806f9df685
commit
95b67942cd
|
@ -36,7 +36,9 @@
|
||||||
"pages/admin/login",
|
"pages/admin/login",
|
||||||
"pages/admin/exam/add",
|
"pages/admin/exam/add",
|
||||||
"pages/admin/exam/detail",
|
"pages/admin/exam/detail",
|
||||||
"pages/admin/exam/index"
|
"pages/admin/exam/index",
|
||||||
|
"pages/candidate/show",
|
||||||
|
"pages/admin/candidate/index"
|
||||||
],
|
],
|
||||||
"window": {
|
"window": {
|
||||||
"backgroundTextStyle": "light",
|
"backgroundTextStyle": "light",
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,98 @@
|
||||||
|
// pages/admin/exam/index.js
|
||||||
|
const api = require("../../../utils/request.js");
|
||||||
|
Page({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面的初始数据
|
||||||
|
*/
|
||||||
|
data: {
|
||||||
|
page:1,
|
||||||
|
isLoadedAll:false,
|
||||||
|
count:0,
|
||||||
|
results:[]
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面加载
|
||||||
|
*/
|
||||||
|
onLoad: function (options) {
|
||||||
|
this.getList(1)
|
||||||
|
},
|
||||||
|
getList: function(page) {
|
||||||
|
wx.showLoading({
|
||||||
|
title: '正在加载...',
|
||||||
|
})
|
||||||
|
api.requesta('/crm/candidate/', 'GET', {page:page}).then(res=>{
|
||||||
|
wx.hideLoading()
|
||||||
|
let results = this.data.results
|
||||||
|
let isLoadedAll = false
|
||||||
|
if(res.data.results){
|
||||||
|
if(page==1){results=res.data.results}else{
|
||||||
|
results = results.concat(res.data.results)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!res.data.next){
|
||||||
|
isLoadedAll = true
|
||||||
|
}
|
||||||
|
this.setData({
|
||||||
|
count:res.data.count,
|
||||||
|
results:results,
|
||||||
|
page:page,
|
||||||
|
isLoadedAll: isLoadedAll
|
||||||
|
})
|
||||||
|
}).catch(
|
||||||
|
wx.hideLoading()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面初次渲染完成
|
||||||
|
*/
|
||||||
|
onReady: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面显示
|
||||||
|
*/
|
||||||
|
onShow: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面隐藏
|
||||||
|
*/
|
||||||
|
onHide: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面卸载
|
||||||
|
*/
|
||||||
|
onUnload: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面相关事件处理函数--监听用户下拉动作
|
||||||
|
*/
|
||||||
|
onPullDownRefresh: function () {
|
||||||
|
this.getList(1)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面上拉触底事件的处理函数
|
||||||
|
*/
|
||||||
|
onReachBottom: function () {
|
||||||
|
if(!this.data.isLoadedAll){
|
||||||
|
this.data.page=this.data.page+1
|
||||||
|
this.getList(this.data.page)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击右上角分享
|
||||||
|
*/
|
||||||
|
onShareAppMessage: function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"usingComponents": {},
|
||||||
|
"navigationBarTitleText": "出征记录",
|
||||||
|
"enablePullDownRefresh":true
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<view class="page__bd">
|
||||||
|
<view class="weui-panel weui-panel_access">
|
||||||
|
<view class="weui-panel__hd">已发布的证书,共{{count}}张</view>
|
||||||
|
<view class="weui-panel__bd">
|
||||||
|
<navigator class="weui-media-box weui-media-box_text" wx:for="{{results}}" wx:key="unique" url="/pages/candidate/detail?id={{item.id}}">
|
||||||
|
<h4 class="weui-media-box__title">
|
||||||
|
<text style="color:blue;">{{item.consumer_name}}</text>
|
||||||
|
{{item.number}}
|
||||||
|
</h4>
|
||||||
|
<view class="weui-media-box__desc">
|
||||||
|
身份证号:{{item.ID_number}}
|
||||||
|
</view>
|
||||||
|
<view class="weui-media-box__desc">
|
||||||
|
工作类别:{{item.workscope_name}}
|
||||||
|
</view>
|
||||||
|
<view class="weui-media-box__desc">
|
||||||
|
期限:{{item.start_date}}至{{item.end_date}}
|
||||||
|
</view>
|
||||||
|
</navigator>
|
||||||
|
</view>
|
||||||
|
<view class="weui-loadmore weui-loadmore_line" wx:if="{{isLoadedAll}}">
|
||||||
|
<text class="weui-loadmore__tips">到底了</text>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="weui-panel__ft">
|
||||||
|
<a class="weui-cell weui-cell_active weui-cell_access weui-cell_link">
|
||||||
|
<view class="weui-cell__bd">查看更多</view>
|
||||||
|
<text class="weui-cell__ft"></text>
|
||||||
|
</a>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
|
@ -0,0 +1 @@
|
||||||
|
/* pages/admin/candidate/index.wxss */
|
|
@ -102,5 +102,11 @@ Page({
|
||||||
wx.navigateTo({
|
wx.navigateTo({
|
||||||
url: '/pages/test/detail?id='+e.currentTarget.dataset.id,
|
url: '/pages/test/detail?id='+e.currentTarget.dataset.id,
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
goCandidate:function(e){
|
||||||
|
let candidate_ = e.currentTarget.dataset.candidate_;
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/candidate/show?number='+candidate_.number,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -22,7 +22,7 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="weui-panel weui-panel_access">
|
<view class="weui-panel weui-panel_access">
|
||||||
<view class="weui-panel__hd">共{{tests.length}}名人员参加考试</view>
|
<view class="weui-panel__hd">共{{tests.length}}次考试记录</view>
|
||||||
<view class="weui-panel__bd">
|
<view class="weui-panel__bd">
|
||||||
<view class="weui-media-box weui-media-box_text" wx:for="{{tests}}" wx:key="unique">
|
<view class="weui-media-box weui-media-box_text" wx:for="{{tests}}" wx:key="unique">
|
||||||
<h4 class="weui-media-box__title">
|
<h4 class="weui-media-box__title">
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
<text style="color:darkblue">{{item.candidate_.number}}</text>
|
<text style="color:darkblue">{{item.candidate_.number}}</text>
|
||||||
</view>
|
</view>
|
||||||
<view style="text-align:right;padding-right:8rpx">
|
<view style="text-align:right;padding-right:8rpx">
|
||||||
<button type="default" size="mini" bindtap="goCandidate" style="margin-left:4px" data-id="{{item.id}}" wx:if="{{item.candidate_}}">查看证书</button>
|
<button type="default" size="mini" bindtap="goCandidate" style="margin-left:4px" data-id="{{item.id}}" data-candidate_="{{item.candidate_}}" wx:if="{{item.candidate_}}">查看证书</button>
|
||||||
<button type="primary" size="mini" bindtap="issue" data-id="{{item.id}}" data-index="{{index}}" wx:else>颁发证书</button>
|
<button type="primary" size="mini" bindtap="issue" data-id="{{item.id}}" data-index="{{index}}" wx:else>颁发证书</button>
|
||||||
<button type="default" size="mini" bindtap="godetail" style="margin-left:4px" data-id="{{item.id}}">答卷详情</button>
|
<button type="default" size="mini" bindtap="godetail" style="margin-left:4px" data-id="{{item.id}}">答卷详情</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
</view>
|
</view>
|
||||||
<view class="weui-grid__label">考试记录</view>
|
<view class="weui-grid__label">考试记录</view>
|
||||||
</navigator>
|
</navigator>
|
||||||
<navigator class="weui-grid" url="/pages/cuoti/index">
|
<navigator class="weui-grid" url="/pages/admin/candidate/index">
|
||||||
<view class="weui-grid__icon">
|
<view class="weui-grid__icon">
|
||||||
<image src="/images/candidate.svg" alt></image>
|
<image src="/images/candidate.svg" alt></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// pages/candidate/detail.js
|
// pages/candidate/detail.js
|
||||||
|
const api = require("../../utils/request.js");
|
||||||
Page({
|
Page({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,12 +13,16 @@ Page({
|
||||||
* 生命周期函数--监听页面加载
|
* 生命周期函数--监听页面加载
|
||||||
*/
|
*/
|
||||||
onLoad: function (options) {
|
onLoad: function (options) {
|
||||||
console.log(getApp().globalData.candidate_url)
|
let id = options.id
|
||||||
this.setData({
|
this.getDetail(id)
|
||||||
url:getApp().globalData.candidate_url
|
},
|
||||||
|
getDetail: function(id){
|
||||||
|
api.request(`/crm/candidate/${id}/`, 'GET').then(res=>{
|
||||||
|
this.setData({
|
||||||
|
candidate:res.data
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生命周期函数--监听页面初次渲染完成
|
* 生命周期函数--监听页面初次渲染完成
|
||||||
*/
|
*/
|
||||||
|
@ -65,5 +70,18 @@ Page({
|
||||||
*/
|
*/
|
||||||
onShareAppMessage: function () {
|
onShareAppMessage: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
godetail: function(e){
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/test/detail?id='+this.data.candidate.examtest,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
goCandidate:function(e){
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/candidate/show?number='+this.data.candidate.number,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
downDoc: function(e){
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -1,2 +1,24 @@
|
||||||
<!--pages/candidate/detail.wxml-->
|
<!--pages/candidate/detail.wxml-->
|
||||||
<web-view src="{{url}}"></web-view>
|
<view style="margin-left:4px;margin-right:4px">
|
||||||
|
<image style="width: 100%;height:200px" src="/images/bg.png" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<view class="weui-panel__bd">
|
||||||
|
<view class="weui-media-box weui-media-box_text" style="text-align:center">
|
||||||
|
<h4 class="weui-media-box__title">
|
||||||
|
<text style="color:blue;">{{candidate.consumer_name}}</text>
|
||||||
|
{{candidate.number}}
|
||||||
|
</h4>
|
||||||
|
<view class="weui-media-box__desc">
|
||||||
|
{{candidate.ID_number}}
|
||||||
|
</view>
|
||||||
|
<view class="weui-media-box__desc">
|
||||||
|
{{candidate.workscope_name}}
|
||||||
|
</view>
|
||||||
|
<view class="weui-media-box__desc">
|
||||||
|
{{candidate.start_date}}至{{candidate.end_date}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<a class="weui-btn weui-btn_primary" bindtap="goCandidate">查看证书</a>
|
||||||
|
<a class="weui-btn weui-btn_default" bindtap="godetail">答题信息</a>
|
||||||
|
<a class="weui-btn weui-btn_default" bindtap="downDoc">下载完整文档</a>
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
// pages/candidate/show.js
|
||||||
|
Page({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面的初始数据
|
||||||
|
*/
|
||||||
|
data: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面加载
|
||||||
|
*/
|
||||||
|
onLoad: function (options) {
|
||||||
|
let number = options.number;
|
||||||
|
this.setData({
|
||||||
|
url:getApp().globalData.host+'/crm/candidate/img/'+number+'/'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面初次渲染完成
|
||||||
|
*/
|
||||||
|
onReady: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面显示
|
||||||
|
*/
|
||||||
|
onShow: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面隐藏
|
||||||
|
*/
|
||||||
|
onHide: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面卸载
|
||||||
|
*/
|
||||||
|
onUnload: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面相关事件处理函数--监听用户下拉动作
|
||||||
|
*/
|
||||||
|
onPullDownRefresh: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面上拉触底事件的处理函数
|
||||||
|
*/
|
||||||
|
onReachBottom: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击右上角分享
|
||||||
|
*/
|
||||||
|
onShareAppMessage: function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<view class="page-body">
|
||||||
|
<view class="page-section page-section-gap">
|
||||||
|
<web-view src="{{url}}"></web-view>
|
||||||
|
</view>
|
||||||
|
</view>
|
|
@ -0,0 +1 @@
|
||||||
|
/* pages/candidate/show.wxss */
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Generated by Django 3.0.4 on 2021-06-07 05:44
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('crm', '0033_auto_20210606_2209'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='candidate',
|
||||||
|
name='create_admin',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='创建管理员'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -120,7 +120,7 @@ class Candidate(CommonModel):
|
||||||
start_date = models.DateField('有效期始', null=True, blank=True)
|
start_date = models.DateField('有效期始', null=True, blank=True)
|
||||||
end_date = models.DateField('有效期止', null=True, blank=True)
|
end_date = models.DateField('有效期止', null=True, blank=True)
|
||||||
examtest = models.OneToOneField(to='examtest.examtest', verbose_name='关联考试', null=True, blank=True, on_delete=models.DO_NOTHING)
|
examtest = models.OneToOneField(to='examtest.examtest', verbose_name='关联考试', null=True, blank=True, on_delete=models.DO_NOTHING)
|
||||||
|
create_admin = models.ForeignKey(UserProfile, verbose_name="创建管理员", null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '证书'
|
verbose_name = '证书'
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from .models import Company, Consumer, PaySubject, ConsumerPerm, ConsumerRole
|
from .models import Candidate, Company, Consumer, PaySubject, ConsumerPerm, ConsumerRole
|
||||||
from question.models import Question, Questioncat
|
from question.models import Question, Questioncat
|
||||||
from .permission import get_consumerperm_list
|
from .permission import get_consumerperm_list
|
||||||
from rbac.serializers.user_serializer import UserListSerializer
|
from rbac.serializers.user_serializer import UserListSerializer
|
||||||
|
@ -73,3 +73,9 @@ class ConsumerDetailSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
def get_perms(self,obj):
|
def get_perms(self,obj):
|
||||||
return get_consumerperm_list(obj)
|
return get_consumerperm_list(obj)
|
||||||
|
|
||||||
|
|
||||||
|
class CandidateSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Candidate
|
||||||
|
fields = '__all__'
|
|
@ -120,20 +120,22 @@
|
||||||
draggable="true">
|
draggable="true">
|
||||||
<div class="editable" style="background-color: transparent; word-break: break-all;"
|
<div class="editable" style="background-color: transparent; word-break: break-all;"
|
||||||
contenteditable="false"><span contenteditable="false" class="inner-cell"
|
contenteditable="false"><span contenteditable="false" class="inner-cell"
|
||||||
data-tag="name">高彩眉</span>,<span contenteditable="false" class="inner-cell"
|
data-tag="name">{{candidate.consumer_name}}</span>,
|
||||||
data-tag="gender">女</span>,<span contenteditable="false" class="inner-cell"
|
<!-- <span contenteditable="false" class="inner-cell" data-tag="gender">女</span>,
|
||||||
data-tag="birthday">1994年03月04日</span>生,<span contenteditable="false" class="inner-cell"
|
<span contenteditable="false" class="inner-cell" data-tag="birthday">1994年03月04日</span>生, -->
|
||||||
data-tag="idtype">身份证</span>:<span contenteditable="false" class="inner-cell"
|
<span contenteditable="false"
|
||||||
data-tag="idno">342921199403040528</span>,于<span contenteditable="false" class="inner-cell"
|
class="inner-cell" data-tag="idtype">身份证</span>:<span contenteditable="false"
|
||||||
data-tag="examyear">2021</span>年<span contenteditable="false" class="inner-cell"
|
class="inner-cell" data-tag="idno">{{candidate.ID_number}}</span>,于
|
||||||
data-tag="exammonth">01</span>月参加 <span contenteditable="false" class="inner-cell"
|
<!-- <span contenteditable="false" class="inner-cell" data-tag="examyear">2021</span>年 -->
|
||||||
data-tag="pworktype">医学其他</span> 辐射安全与防护考核,成绩合格。</div>
|
<span contenteditable="false" class="inner-cell" data-tag="exammonth">{{candidate.examtest.start_time|date}}</span>参加
|
||||||
|
<span contenteditable="false"
|
||||||
|
class="inner-cell" data-tag="pworktype">{{candidate.workscope_name}}</span> 辐射安全与防护考核,成绩合格。</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="8cBDPhuQ2bx7BMR7gCEXwo" class="cell moveable " title="自定义文本"
|
<div id="8cBDPhuQ2bx7BMR7gCEXwo" class="cell moveable " title="自定义文本"
|
||||||
style="position: absolute; width: 63mm; min-height: 5mm; line-height: 2; text-indent: 1em; top: 89.56mm; left: 28.92mm; font-size: 12pt; color: rgb(0, 0, 0);"
|
style="position: absolute; width: 63mm; min-height: 5mm; line-height: 2; text-indent: 1em; top: 89.56mm; left: 28.92mm; font-size: 12pt; color: rgb(0, 0, 0);"
|
||||||
draggable="true">
|
draggable="true">
|
||||||
<div class="editable" style="background-color: transparent; word-break: break-all;">编号:<span
|
<div class="editable" style="background-color: transparent; word-break: break-all;">编号:<span
|
||||||
contenteditable="false" class="inner-cell" data-tag="certnumber">FS21ZJ0000070</span>
|
contenteditable="false" class="inner-cell" data-tag="certnumber">{{candidate.number}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="XrsAo57jnLFhfiMUeea7DK" class="cell moveable " title="自定义文本"
|
<div id="XrsAo57jnLFhfiMUeea7DK" class="cell moveable " title="自定义文本"
|
||||||
|
@ -141,9 +143,11 @@
|
||||||
draggable="true">
|
draggable="true">
|
||||||
<!-- <div class="editable" style="background-color: transparent; word-break: break-all;"
|
<!-- <div class="editable" style="background-color: transparent; word-break: break-all;"
|
||||||
contenteditable="false">报告单查询网址:fushe.mee.gov.cn</div> -->
|
contenteditable="false">报告单查询网址:fushe.mee.gov.cn</div> -->
|
||||||
</div><img id="Q4vEwUqGDkSh5U74XDvaeq" class="cell moveable " src="./报告单_files/qrcode" title="二维码"
|
</div>
|
||||||
|
<div id="qrcode" style="position: absolute; width: 25mm; height: 25mm; top: 101.48mm; left: 152.69mm;"></div>
|
||||||
|
<!-- <img id="qrcode" class="cell moveable " src="./报告单_files/qrcode" title="二维码"
|
||||||
alt="二维码" style="position: absolute; width: 25mm; height: 25mm; top: 101.48mm; left: 152.69mm;"
|
alt="二维码" style="position: absolute; width: 25mm; height: 25mm; top: 101.48mm; left: 152.69mm;"
|
||||||
draggable="true">
|
draggable="true"> -->
|
||||||
<div id="AkTVQPAB5skpWAwyV5QGPm" class="cell moveable " title="自定义文本"
|
<div id="AkTVQPAB5skpWAwyV5QGPm" class="cell moveable " title="自定义文本"
|
||||||
style="position: absolute; width: 18mm; min-height: 5mm; line-height: 1.5; text-indent: 0em; text-decoration: unset; font-style: normal; color: rgb(0, 0, 0); top: 90.56mm; left: 91.83mm; font-size: 12pt;"
|
style="position: absolute; width: 18mm; min-height: 5mm; line-height: 1.5; text-indent: 0em; text-decoration: unset; font-style: normal; color: rgb(0, 0, 0); top: 90.56mm; left: 91.83mm; font-size: 12pt;"
|
||||||
draggable="true">
|
draggable="true">
|
||||||
|
@ -154,30 +158,35 @@
|
||||||
draggable="true">
|
draggable="true">
|
||||||
<div class="editable" style="background-color: transparent; word-break: break-all;">至</div>
|
<div class="editable" style="background-color: transparent; word-break: break-all;">至</div>
|
||||||
</div><span id="MAAR3FWxqXrieXZQTwJ9PJ" class="cell moveable " title="有效截止日期" dtype="1" draggable="true"
|
</div><span id="MAAR3FWxqXrieXZQTwJ9PJ" class="cell moveable " title="有效截止日期" dtype="1" draggable="true"
|
||||||
style="position: absolute; width: 34mm; text-decoration: unset; font-style: normal; color: rgb(0, 0, 0); top: 90.56mm; left: 146.09mm; font-size: 12pt;"><span
|
style="position: absolute; width: 34mm; text-decoration: unset; font-style: normal; color: rgb(0, 0, 0); top: 91mm; left: 146.09mm; font-size: 12pt;"><span
|
||||||
data-tag="enddate">2026年01月27日</span></span><span id="N9LxjQaAG4TXvjiHd9nwm7"
|
data-tag="enddate">{{candidate.end_date}}</span></span><span id="N9LxjQaAG4TXvjiHd9nwm7"
|
||||||
class="cell moveable " title="发证日期" dtype="1" draggable="true"
|
class="cell moveable " title="发证日期" dtype="1" draggable="true"
|
||||||
style="position: absolute; width: 32mm; text-decoration: unset; font-style: normal; color: rgb(0, 0, 0); top: 90.56mm; left: 107.7mm; font-size: 12pt;"><span
|
style="position: absolute; width: 32mm; text-decoration: unset; font-style: normal; color: rgb(0, 0, 0); top: 91mm; left: 107.7mm; font-size: 12pt;"><span
|
||||||
data-tag="certdate">2021年01月27日</span></span>
|
data-tag="certdate">{{candidate.start_date}}</span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js" integrity="sha512-CNgIRecGo7nphbeZ04Sc13ka07paqdeTu0WR1IM4kNcpmBAUSHSQX0FslNhTDadL4O5SAGapGt4FodqL8My0mA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// $(document).ready(function() {
|
// $(document).ready(function() {
|
||||||
|
|
||||||
|
|
||||||
// });
|
// });
|
||||||
|
console.log(window.location.href)
|
||||||
|
new QRCode(document.getElementById("qrcode"), {
|
||||||
|
text: window.location.href,
|
||||||
|
width: 100,
|
||||||
|
height: 100});
|
||||||
function init() {
|
function init() {
|
||||||
// $('select').change(function() {
|
// $('select').change(function() {
|
||||||
// $('form').submit();
|
// $('form').submit();
|
||||||
// });
|
// });
|
||||||
|
|
||||||
if (navigator.userAgent.match(/mobile/i)) {
|
if (navigator.userAgent.match(/mobile/i)) {
|
||||||
$('#print_area').hide();
|
// $('#print_area').hide();
|
||||||
document.querySelector('#print_area').style.display = 'none';
|
document.querySelector('#print_area').style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path,include
|
from django.urls import path,include
|
||||||
from .views import CompanyViewSet, \
|
from .views import CompanyViewSet, \
|
||||||
ConsumerViewSet, ConsumerMPLoginView, ConsumerRegister, change_remain_count, ConsumerPermViewSet, ConsumerRoleViewSet, candidate
|
ConsumerViewSet, ConsumerMPLoginView, ConsumerRegister, change_remain_count, ConsumerPermViewSet, ConsumerRoleViewSet, candidate, CandidateViewSet
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,11 +9,11 @@ router.register('consumer', ConsumerViewSet, basename="consumer")
|
||||||
router.register('company', CompanyViewSet, basename="company")
|
router.register('company', CompanyViewSet, basename="company")
|
||||||
router.register('consumerrole', ConsumerRoleViewSet, basename="consumerrole")
|
router.register('consumerrole', ConsumerRoleViewSet, basename="consumerrole")
|
||||||
router.register('consumerperm', ConsumerPermViewSet, basename="consumerperm")
|
router.register('consumerperm', ConsumerPermViewSet, basename="consumerperm")
|
||||||
|
router.register('candidate', CandidateViewSet, basename="candidate")
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('consumer/mplogin/', ConsumerMPLoginView.as_view()),
|
path('consumer/mplogin/', ConsumerMPLoginView.as_view()),
|
||||||
path('consumer/register/', ConsumerRegister.as_view()),
|
path('consumer/register/', ConsumerRegister.as_view()),
|
||||||
path('change_remain_count/', change_remain_count.as_view()),
|
path('change_remain_count/', change_remain_count.as_view()),
|
||||||
path('candidate/<str:number>/',candidate),
|
path('candidate/img/<str:number>/',candidate),
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,10 +11,11 @@ from openpyxl import Workbook, load_workbook
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.decorators import action, authentication_classes, permission_classes
|
from rest_framework.decorators import action, authentication_classes, permission_classes
|
||||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
|
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
||||||
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
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
|
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
|
||||||
from rest_framework_jwt.serializers import jwt_encode_handler
|
from rest_framework_jwt.serializers import jwt_encode_handler
|
||||||
from rest_framework_jwt.settings import api_settings
|
from rest_framework_jwt.settings import api_settings
|
||||||
|
@ -27,8 +28,8 @@ from server import settings
|
||||||
from utils.custom import CommonPagination
|
from utils.custom import CommonPagination
|
||||||
from .filters import ConsumerFilter
|
from .filters import ConsumerFilter
|
||||||
from .exports import export_consumer
|
from .exports import export_consumer
|
||||||
from .models import Company, Consumer, PaySubject, SendCode, ConsumerPerm, ConsumerRole
|
from .models import Candidate, Company, Consumer, PaySubject, SendCode, ConsumerPerm, ConsumerRole
|
||||||
from .serializers import CompanySerializer, ConsumerSerializer, ConsumerPermSerializer, ConsumerRoleSerializer, ConsumerDetailSerializer
|
from .serializers import CandidateSerializer, CompanySerializer, ConsumerSerializer, ConsumerPermSerializer, ConsumerRoleSerializer, ConsumerDetailSerializer
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from rbac.models import UserProfile
|
from rbac.models import UserProfile
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
|
@ -647,4 +648,52 @@ class change_remain_count(APIView):
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
def candidate(request, number):
|
def candidate(request, number):
|
||||||
return render(request, 'index.html')
|
candidate = Candidate.objects.get(number=number)
|
||||||
|
return render(request, 'index.html', {"candidate":candidate})
|
||||||
|
|
||||||
|
class CandidateViewSet(RetrieveModelMixin, ListModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
出征记录:列表
|
||||||
|
"""
|
||||||
|
perms_map = [
|
||||||
|
{'get': '*'}, {'post': 'candidate_issue'},
|
||||||
|
{'put': 'candidate_update'}, {'delete': 'candidate_delete'}]
|
||||||
|
queryset = Candidate.objects.filter(number__isnull=False)
|
||||||
|
serializer_class = CandidateSerializer
|
||||||
|
pagination_class = CommonPagination
|
||||||
|
filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter]
|
||||||
|
search_fields = ('number', 'consumer_name', 'workscope_name', 'company_name')
|
||||||
|
ordering_fields = ('-id', 'update_time')
|
||||||
|
ordering = ['-update_time']
|
||||||
|
|
||||||
|
def get_authenticators(self, request):
|
||||||
|
if self.request.action == 'retrieve':
|
||||||
|
return []
|
||||||
|
return super().get_authenticators()
|
||||||
|
|
||||||
|
def get_permissions(self):
|
||||||
|
if self.action == 'retrieve':
|
||||||
|
return []
|
||||||
|
return super().get_permissions()
|
||||||
|
|
||||||
|
def retrieve(self, request, *args, **kwargs):
|
||||||
|
instance = self.queryset.get(*args, **kwargs)
|
||||||
|
serializer = self.get_serializer(instance)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = self.queryset
|
||||||
|
if self.request.user.is_superuser:
|
||||||
|
return queryset
|
||||||
|
roles = self.request.user.roles.values_list('name', flat=True)
|
||||||
|
if '普通管理' in roles:
|
||||||
|
queryset = queryset.filter(create_admin = self.request.user)
|
||||||
|
elif '省管理' in roles:
|
||||||
|
if self.request.user.pname:
|
||||||
|
queryset = queryset.filter(consumer__company__geo__pname = self.request.user.pname)
|
||||||
|
else:
|
||||||
|
return Candidate.objects.none()
|
||||||
|
else:
|
||||||
|
return queryset.none()
|
||||||
|
print(queryset)
|
||||||
|
return queryset
|
|
@ -318,10 +318,11 @@ class WorkScopeViewSet(ModelViewSet):
|
||||||
"""
|
"""
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
if obj.can_exam:
|
if obj.can_exam:
|
||||||
try:
|
candidates = Candidate.objects.filter(consumer=request.user, workscope=request.user.workscope)
|
||||||
Candidate.objects.get_or_create(consumer=request.user, workscope=request.user.workscope, defaults={'consumer':request.user, 'workscope':request.user.workscope})
|
if candidates.exists():
|
||||||
except:
|
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
Candidate.objects.create(consumer=request.user, workscope=request.user.workscope)
|
||||||
request.user.workscope = obj
|
request.user.workscope = obj
|
||||||
request.user.save()
|
request.user.save()
|
||||||
return Response({'workscope':obj.pk, 'workscope_name':obj.name})
|
return Response({'workscope':obj.pk, 'workscope_name':obj.name})
|
||||||
|
@ -385,7 +386,7 @@ class ExamTestViewSet(PageOrNot, ModelViewSet):
|
||||||
queryset = ExamTest.objects.filter(is_delete=0).all()
|
queryset = ExamTest.objects.filter(is_delete=0).all()
|
||||||
serializer_class = ExamTestExamListSerializer
|
serializer_class = ExamTestExamListSerializer
|
||||||
ordering_fields = ('id','create_time','took','score')
|
ordering_fields = ('id','create_time','took','score')
|
||||||
ordering = ['-create_time']
|
ordering = ['-create_time', 'is_pass', '-score']
|
||||||
search_fields = ('consumer__name', 'consumer__company__name')
|
search_fields = ('consumer__name', 'consumer__company__name')
|
||||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
filterset_fields = ['type','is_pass', 'exam']
|
filterset_fields = ['type','is_pass', 'exam']
|
||||||
|
@ -505,8 +506,8 @@ class ExamTestViewSet(PageOrNot, ModelViewSet):
|
||||||
'''
|
'''
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
candidate = obj.candidate if hasattr(obj, 'candidate') else None
|
candidate = obj.candidate if hasattr(obj, 'candidate') else None
|
||||||
# if not obj.is_pass:
|
if not obj.is_pass:
|
||||||
# return Response({'error':'考试未通过'})
|
return Response({'error':'考试未通过'})
|
||||||
if candidate:
|
if candidate:
|
||||||
return Response({'error':'证书已存在'})
|
return Response({'error':'证书已存在'})
|
||||||
candidates = Candidate.objects.filter(consumer=obj.consumer, workscope=obj.workscope, number__isnull=True)
|
candidates = Candidate.objects.filter(consumer=obj.consumer, workscope=obj.workscope, number__isnull=True)
|
||||||
|
@ -514,18 +515,19 @@ class ExamTestViewSet(PageOrNot, ModelViewSet):
|
||||||
candidate = candidates[0]
|
candidate = candidates[0]
|
||||||
else:
|
else:
|
||||||
candidate = Candidate.objects.create(consumer=obj.consumer, workscope=obj.workscope)
|
candidate = Candidate.objects.create(consumer=obj.consumer, workscope=obj.workscope)
|
||||||
count = Candidate.objects.exclude(number__isnull=True).count()
|
|
||||||
candidate.examtest = obj
|
candidate.examtest = obj
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
candidate.issue_date = now
|
candidate.issue_date = now
|
||||||
candidate.start_date = now
|
candidate.start_date = now
|
||||||
candidate.end_date = now + timedelta(days=3*365)
|
candidate.end_date = now + timedelta(days=5*365) # 5年有效期
|
||||||
candidate.workscope_name = obj.workscope.name
|
candidate.workscope_name = obj.workscope.name
|
||||||
candidate.consumer_name = obj.consumer_detail['name']
|
candidate.consumer_name = obj.consumer_detail['name']
|
||||||
candidate.ID_number = obj.consumer_detail['ID_number']
|
candidate.ID_number = obj.consumer_detail['ID_number']
|
||||||
candidate.company_name = obj.consumer_detail['company_name']
|
candidate.company_name = obj.consumer_detail['company_name']
|
||||||
candidate.deptname = obj.consumer_detail['deptname']
|
candidate.deptname = obj.consumer_detail['deptname']
|
||||||
candidate.number='SL'+ str(now.year)[-2:] + str(count+1).zfill(6)
|
candidate.save()
|
||||||
|
candidate.number='SL'+ str(now.year)[-2:] + str(candidate.pk).zfill(6)
|
||||||
|
candidate.create_admin = request.user
|
||||||
candidate.save()
|
candidate.save()
|
||||||
return Response({"id":candidate.pk, "number":candidate.number})
|
return Response({"id":candidate.pk, "number":candidate.number})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue