Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shilixia 2022-02-17 14:34:04 +08:00
commit 3008f1e2ce
15 changed files with 155 additions and 138 deletions

View File

@ -66,4 +66,7 @@ export default {
#warningTabs .el-tabs__item{ #warningTabs .el-tabs__item{
padding: 0 10px!important; padding: 0 10px!important;
} }
#loginFaceWrap .el-dialog{
width: 780px!important;height: 720px!important;
}
</style> </style>

View File

@ -1,11 +1,11 @@
<template> <template>
<div style="width: 100%;height: 100%;"> <div style="width: 100%;height: 620px;">
<div> <div>
<div class="video-box"> <div class="video-box">
<video id="video" width="749" height="640" preload autoplay loop muted></video> <video id="video" width="749" height="620" preload autoplay loop muted></video>
<canvas id="canvas" width="749" height="640"></canvas> <canvas id="canvas" width="749" height="620"></canvas>
</div> </div>
<canvas id="screenshotCanvas" width="749" height="640"></canvas> <canvas id="screenshotCanvas" width="749" height="620"></canvas>
</div> </div>
</div> </div>
</template> </template>

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1644973249496" class="icon" viewBox="0 0 1061 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3412" xmlns:xlink="http://www.w3.org/1999/xlink" width="33.15625" height="32"><defs><style type="text/css"></style></defs><path d="M939.425185 796.444444H122.500741C57.230222 796.444444 0 745.775407 0 687.824593V108.619852C0 50.669037 57.192296 0 122.500741 0h816.924444C1004.695704 0 1061.925926 50.669037 1061.925926 108.619852v579.204741C1061.925926 745.775407 1004.73363 796.444444 939.425185 796.444444z m-519.888592-137.102222c16.308148 0 40.808296-16.346074 40.808296-40.846222V373.418667c0-24.500148-16.308148-40.846222-40.808296-40.846223-24.538074 0-40.846222 16.346074-40.846223 40.846223v245.077333c0 24.500148 16.308148 40.846222 40.846223 40.846222z m179.693037 0c24.500148 0 40.846222-16.346074 40.846222-40.846222v-122.538667c0-24.500148-16.308148-40.846222-40.846222-40.846222-24.500148 0-40.846222 16.308148-40.846223 40.846222v122.500741c0 24.538074 16.308148 40.884148 40.846223 40.884148z m179.693037 0c24.538074 0 40.846222-16.346074 40.846222-40.846222V577.611852c0-24.500148-16.308148-40.846222-40.846222-40.846222-24.500148 0-40.808296 16.308148-40.808297 40.846222v40.846222c0 24.500148 16.308148 40.846222 40.808297 40.846222z m-539.117037 0c16.308148 0 40.846222-16.346074 40.846222-40.846222V250.88c0-24.500148-16.308148-40.846222-40.846222-40.846222-24.500148 0-40.846222 16.346074-40.846223 40.846222v367.616c0 24.500148 16.308148 40.846222 40.846223 40.846222zM265.481481 872.296296h530.962963a75.851852 75.851852 0 1 1 0 151.703704H265.481481a75.851852 75.851852 0 1 1 0-151.703704z" p-id="3413" fill="#ffffff"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -55,7 +55,7 @@ export const constantRoutes = [
{ {
path: '/index', path: '/index',
component: () => import('@/views/bigScreen/index'), component: () => import('@/views/bigScreen/index'),
meta: { title: '大屏', icon: 'home', affix: true,keepAlive: false } meta: { title: '大屏', icon: 'bigScreen', affix: true,keepAlive: false }
}, },
{ {
path: '/changepassword', path: '/changepassword',

View File

@ -7,11 +7,8 @@
<div style="padding: 20px;overflow: hidden;"> <div style="padding: 20px;overflow: hidden;">
<div class="cardsWrap" @click="toDetail('1')"> <div class="cardsWrap" @click="toDetail('1')">
<div class="svgIconWrap"> <div class="svgIconWrap">
<svg-icon <el-icon class="el-icon-s-order svgIcon"></el-icon>
class="svgIcon" <!--<svg-icon class="svgIcon" icon-class="contract" :className="'svgIcon'"/>-->
icon-class="contract"
:className="'svgIcon'"
/>
</div> </div>
<div class="totalCountWrap"> <div class="totalCountWrap">
<span class="totalCountText">本月合同数</span> <span class="totalCountText">本月合同数</span>
@ -23,6 +20,7 @@
</div> </div>
<div class="cardsWrap" @click="toDetail('2')"> <div class="cardsWrap" @click="toDetail('2')">
<div class="svgIconWrap"> <div class="svgIconWrap">
<el-icon class="el-icon-menu svgIcon"></el-icon>
<svg-icon <svg-icon
class="svgIcon" class="svgIcon"
icon-class="order" icon-class="order"
@ -39,11 +37,8 @@
</div> </div>
<div class="cardsWrap" @click="toDetail('3')"> <div class="cardsWrap" @click="toDetail('3')">
<div class="svgIconWrap"> <div class="svgIconWrap">
<svg-icon <el-icon class="el-icon-s-operation svgIcon"></el-icon>
class="svgIcon" <!--<svg-icon class="svgIcon" icon-class="productionTask" :className="'svgIcon'"/>-->
icon-class="productionTask"
:className="'svgIcon'"
/>
</div> </div>
<div class="totalCountWrap"> <div class="totalCountWrap">
<span class="totalCountText">本月在制任务</span> <span class="totalCountText">本月在制任务</span>
@ -55,11 +50,8 @@
</div> </div>
<div class="cardsWrap" @click="toDetail('4')"> <div class="cardsWrap" @click="toDetail('4')">
<div class="svgIconWrap"> <div class="svgIconWrap">
<svg-icon <el-icon class="el-icon-s-claim svgIcon"></el-icon>
icon-class="product" <!--<svg-icon icon-class="product" class="svgIcon" :className="'svgIcon'"/>-->
class="svgIcon"
:className="'svgIcon'"
/>
</div> </div>
<div class="totalCountWrap"> <div class="totalCountWrap">
<span class="totalCountText">本月交付产品</span> <span class="totalCountText">本月交付产品</span>
@ -71,11 +63,8 @@
</div> </div>
<div class="cardsWrap" @click="toDetail('5')"> <div class="cardsWrap" @click="toDetail('5')">
<div class="svgIconWrap"> <div class="svgIconWrap">
<svg-icon <el-icon class="el-icon-error svgIcon"></el-icon>
icon-class="unqualified" <!--<svg-icon icon-class="unqualified" class="svgIcon" :className="'svgIcon'"/>-->
class="svgIcon"
:className="'svgIcon'"
/>
</div> </div>
<div class="totalCountWrap"> <div class="totalCountWrap">
<span class="totalCountText">本月不合格产品</span> <span class="totalCountText">本月不合格产品</span>
@ -695,7 +684,8 @@
show: false//Y轴刻度线 show: false//Y轴刻度线
}, },
axisLabel: { axisLabel: {
color: '#333333'//Y轴文本颜色 color: '#333333',//Y轴文本颜色
fontSize: 10,//字体大小
}, },
splitLine: { splitLine: {
show: true, //Y轴分割线 show: true, //Y轴分割线

View File

@ -64,8 +64,8 @@
</el-tabs> </el-tabs>
</div> </div>
</div> </div>
<el-dialog :visible.sync="limitedPhoto" @close="closeCamera"> <el-dialog :visible.sync="limitedPhoto" @close="closeCamera" id="loginFaceWrap">
<div style="font-size: 28px;color: #333333;text-align: center;font-weight: bold;margin-bottom: 15px;">打卡</div> <div style="font-size: 28px;color: #333333;text-align: center;font-weight: bold;">打卡</div>
<div class="testTracking"> <div class="testTracking">
<faceLogin ref="faceTracking" name="faceLogin" @func="getMsgFormSon"></faceLogin> <faceLogin ref="faceTracking" name="faceLogin" @func="getMsgFormSon"></faceLogin>
</div> </div>
@ -309,6 +309,6 @@
} }
.testTracking{ .testTracking{
width:100%; width:100%;
height: 700px; height: 620px;
} }
</style> </style>

View File

@ -3,7 +3,7 @@
<el-card> <el-card>
<el-row :gutter="2"> <el-row :gutter="2">
<!--表格--> <!--表格-->
<el-col :span="6"> <el-col :span="10">
<el-card> <el-card>
<div <div
slot="header" slot="header"
@ -30,8 +30,12 @@
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
> >
<el-table-column type="index" width="50"/> <el-table-column type="index" width="50"/>
<el-table-column label="表名称"> <el-table-column label="表名称" prop="name">
<template slot-scope="scope">{{ scope.row.name }}</template> </el-table-column>
<el-table-column label="表类型">
<template slot-scope="scope">
{{typeOptions_[scope.row.type]}}
</template>
</el-table-column> </el-table-column>
<el-table-column label="是否启用"> <el-table-column label="是否启用">
<template slot-scope="scope"> <template slot-scope="scope">
@ -75,6 +79,36 @@
<el-form-item label="表格名称" prop="name"> <el-form-item label="表格名称" prop="name">
<el-input v-model="recordform.name" placeholder="表格名称"/> <el-input v-model="recordform.name" placeholder="表格名称"/>
</el-form-item> </el-form-item>
<!--<el-form-item label="引用表单" prop="field_type">
<el-select
style="width: 100%"
v-model="recordform.number"
placeholder="请选择"
>
<el-option
v-for="item in fieldtypeoptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>-->
<el-form-item label="表格类型" prop="formUsed">
<el-select
style="width: 100%"
v-model="recordform.type"
placeholder="请选择"
>
<el-option
v-for="item in typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="是否启用" prop="name"> <el-form-item label="是否启用" prop="name">
<el-switch v-model="recordform.enabled"></el-switch> <el-switch v-model="recordform.enabled"></el-switch>
</el-form-item> </el-form-item>
@ -239,7 +273,7 @@
</el-card> </el-card>
</el-col> </el-col>
<!--表格字段--> <!--表格字段-->
<el-col :span="18"> <el-col :span="14">
<el-card> <el-card>
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span style="font-size: 16px; font-weight: 300">记录字段</span> <span style="font-size: 16px; font-weight: 300">记录字段</span>
@ -406,69 +440,6 @@
<el-form-item label="是否需要判定" prop="need_judge"> <el-form-item label="是否需要判定" prop="need_judge">
<el-switch v-model="field.need_judge"></el-switch> <el-switch v-model="field.need_judge"></el-switch>
</el-form-item> </el-form-item>
<!--
<el-form-item
label="上限值"
v-if="field.need_judge == true"
prop="high_limit"
>
<el-input-number
v-model="field.high_limit"
:precision="2"
:min="0"
></el-input-number>
</el-form-item>
<el-form-item
label="上限规则"
v-if="field.need_judge == true"
prop="high_rule"
>
<el-select
style="width: 100%"
v-model="field.high_rule"
placeholder="请选择"
>
<el-option
v-for="item in highoptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
label="下限值"
v-if="field.need_judge == true"
prop="low_limit"
>
<el-input-number
v-model="field.low_limit"
:precision="2"
:min="0"
></el-input-number>
</el-form-item>
<el-form-item
label="下限规则"
v-if="field.need_judge == true"
prop="low_rule"
>
<el-select
style="width: 100%"
v-model="field.low_rule"
placeholder="请选择"
>
<el-option
v-for="item in lowoptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
!-->
<el-form-item label="判定式" v-if="field.need_judge === true"> <el-form-item label="判定式" v-if="field.need_judge === true">
<el-input v-model="field.rule_expression" type="textarea"/> <el-input v-model="field.rule_expression" type="textarea"/>
</el-form-item> </el-form-item>
@ -556,7 +527,7 @@
const defaultfield = {}; const defaultfield = {};
let preDrawAry = []; let preDrawAry = [];
export default { export default {
components: {Pagination, vueJsonEditor, Treeselect, customForm,faceLogin}, components: {Pagination, vueJsonEditor, Treeselect, customForm, faceLogin},
data() { data() {
return { return {
step: defaultstep, step: defaultstep,
@ -677,12 +648,31 @@
label: "绘图模板", label: "绘图模板",
}, },
], ],
typeoptions: [ typeOptions: [
{ {
value: 1, value: 10,
label: "生产记录", label: "生产记录表",
}, {
value: 20,
label: "工序检查表",
}, {
value: 30,
label: "入场检验表",
}, {
value: 40,
label: "成品检验表",
}, {
value: 50,
label: "首件检查表",
}, },
], ],
typeOptions_:{
10 : "生产记录表",
20 : "工序检查表",
30 : "入场检验表",
40 : "成品检验表",
50 : "首件检查表",
},
canvas: null, canvas: null,
ctx: null, ctx: null,
myCanvas_rect: null, myCanvas_rect: null,
@ -696,8 +686,8 @@
imgData: '', imgData: '',
canvasImg: '', canvasImg: '',
judgeList: [], judgeList: [],
limitedPhoto:false, limitedPhoto: false,
isDisabled:true, isDisabled: true,
}; };
}, },
computed: {}, computed: {},
@ -850,7 +840,7 @@
}, },
recordformLists() { recordformLists() {
this.listQueryrecordform.material = this.material; this.listQueryrecordform.material = this.material;
this.listQueryrecordform.type = 2; // this.listQueryrecordform.type = 2;
getrecordformList(this.listQueryrecordform).then((response) => { getrecordformList(this.listQueryrecordform).then((response) => {
if (response.data) { if (response.data) {
this.recordformList = response.data; this.recordformList = response.data;
@ -895,21 +885,20 @@
//新增字段 //新增字段
handlefieldCreate() { handlefieldCreate() {
this.field_choice = [""]; this.field_choice = [""];
// this.field = Object.assign({}, defaultfield);
this.dialogType1 = "new"; this.dialogType1 = "new";
this.dialogVisible1 = true; this.dialogVisible1 = true;
// this.$refs["Form"].resetFields(); // this.$refs["Form"].resetFields();
this.$nextTick(() => { this.$nextTick(() => {
this.field.field_type= null; this.field.field_type = null;
this.field.field_key= null; this.field.field_key = null;
this.field.field_name= null; this.field.field_name = null;
this.field.sort= null; this.field.sort = null;
this.field.parent= null; this.field.parent = null;
this.field.help_text= null; this.field.help_text = null;
this.field.draw_template= null; this.field.draw_template = null;
this.field.field_choice= null; this.field.field_choice = null;
this.field.rule_expression= null; this.field.rule_expression = null;
this.field.display_expression= null; this.field.display_expression = null;
this.$refs["Form"].clearValidate(); this.$refs["Form"].clearValidate();
}); });
}, },
@ -965,10 +954,12 @@
this.$refs[form].validate((valid) => { this.$refs[form].validate((valid) => {
if (valid) { if (valid) {
const isEdit = this.dialogType === "edit"; const isEdit = this.dialogType === "edit";
let obj = new Object();
obj.name=this.recordform.name;
obj.type=this.recordform.type;
obj.enabled=this.recordform.enabled;
if (isEdit) { if (isEdit) {
this.recordform.material = this.material; updaterecordform(this.recordform.id, obj).then(
this.recordform.type = 2;
updaterecordform(this.recordform.id, this.recordform).then(
(res) => { (res) => {
if (res.code >= 200) { if (res.code >= 200) {
this.recordformLists(); this.recordformLists();
@ -978,9 +969,8 @@
} }
); );
} else { } else {
this.recordform.material = this.material; obj.material=parseInt(this.material);
this.recordform.type = 2; createrecordform(obj).then((res) => {
createrecordform(this.recordform).then((res) => {
if (res.code >= 200) { if (res.code >= 200) {
this.recordformLists(); this.recordformLists();
this.dialogVisible = false; this.dialogVisible = false;
@ -1011,8 +1001,6 @@
} else { } else {
this.field.form = this.formID; this.field.form = this.formID;
this.field.field_choice = this.field_choice; this.field.field_choice = this.field_choice;
debugger;
console.log(this.field);
createrffield(this.field).then((res) => { createrffield(this.field).then((res) => {
if (res.code >= 200) { if (res.code >= 200) {
this.fieldLists(); this.fieldLists();
@ -1027,12 +1015,12 @@
} }
}); });
}, },
recordformcon(){ recordformcon() {
this.recordform.material = this.material; this.recordform.material = this.material;
this.recordform.type = 2; this.recordform.type = 2;
this.limitedPhoto = true; this.limitedPhoto = true;
}, },
getMsgFormSon(data){ getMsgFormSon(data) {
this.limitedPhoto = data; this.limitedPhoto = data;
this.recordformLists(); this.recordformLists();
this.dialogVisible = false; this.dialogVisible = false;

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-02-16 07:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mtm', '0045_usedstep_need_test'),
]
operations = [
migrations.AlterField(
model_name='recordform',
name='type',
field=models.IntegerField(choices=[(10, '生产记录表'), (20, '工序检查表'), (30, '入厂检查表'), (40, '成品检查表'), (50, '首件检查表')], default=1, verbose_name='表格类型'),
),
]

View File

@ -107,11 +107,17 @@ class RecordForm(CommonAModel):
""" """
记录表格 记录表格
""" """
RF_TYPE_DO = 1 RF_TYPE_DO = 10
RF_TYPE_TEST = 2 RF_TYPE_TEST = 20
RF_TYPE_TEST_IN = 30
RF_TYPE_TEST_GOOD = 40
RF_TYPE_TEST_FIRST = 50
type_choices=( type_choices=(
(RF_TYPE_DO, '生产记录模板'), (RF_TYPE_DO, '生产记录表'),
(RF_TYPE_TEST, '检验记录模板') (RF_TYPE_TEST, '工序检查表'),
(RF_TYPE_TEST_IN, '入厂检查表'),
(RF_TYPE_TEST_GOOD, '成品检查表'),
(RF_TYPE_TEST_FIRST, '首件检查表'),
) )
name = models.CharField('表格名称', max_length=100) name = models.CharField('表格名称', max_length=100)
type = models.IntegerField('表格类型', choices=type_choices, default=1) type = models.IntegerField('表格类型', choices=type_choices, default=1)

View File

@ -190,6 +190,7 @@ class RecordFormCreateSerializer(serializers.ModelSerializer):
model = RecordForm model = RecordForm
fields = ['name', 'type', 'step', 'material', 'number', 'enabled'] fields = ['name', 'type', 'step', 'material', 'number', 'enabled']
class RecordFormUpdateSerializer(serializers.ModelSerializer): class RecordFormUpdateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = RecordForm model = RecordForm

View File

@ -7,7 +7,7 @@ import django.utils.timezone as timezone
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from utils.model import SoftModel, BaseModel from utils.model import SoftModel, BaseModel
from apps.mtm.models import Material, Process, SubProduction, SubprodctionMaterial from apps.mtm.models import Material, Process, RecordFormField, SubProduction, SubprodctionMaterial
from apps.sam.models import Order from apps.sam.models import Order
class ProductionPlan(CommonAModel): class ProductionPlan(CommonAModel):
@ -91,6 +91,16 @@ class SubProductionPlan(CommonAModel):
verbose_name = '子生产计划' verbose_name = '子生产计划'
verbose_name_plural = verbose_name verbose_name_plural = verbose_name
class FirstItem(BaseModel):
"""
首件确认表记录条目
"""
form_field = models.ForeignKey(RecordFormField, verbose_name='关联自定义表格字段', on_delete=models.CASCADE)
field_value = models.JSONField('录入值', null=True, blank=True)
is_hidden = models.BooleanField('是否隐藏', default=False)
is_testok = models.BooleanField('是否合格', null=True, blank=True)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, related_name='item_test_record')
class SubProductionProgress(BaseModel): class SubProductionProgress(BaseModel):
""" """
子计划生产进度统计表/物料消耗 子计划生产进度统计表/物料消耗
@ -104,3 +114,4 @@ class SubProductionProgress(BaseModel):
count_real = models.PositiveIntegerField('实际消耗/产出数', default=0) count_real = models.PositiveIntegerField('实际消耗/产出数', default=0)
count_ok = models.PositiveIntegerField('合格数量', default=0) count_ok = models.PositiveIntegerField('合格数量', default=0)
count_notok = models.PositiveIntegerField('不合格数量', default=0) count_notok = models.PositiveIntegerField('不合格数量', default=0)

View File

@ -9,15 +9,11 @@ class CustomBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs): def authenticate(self, request, username=None, password=None, **kwargs):
if username is None: if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD) username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
try: try:
user = UserModel._default_manager.get( user = UserModel._default_manager.get(
Q(username=username) | Q(phone=username) | Q(email=username)) Q(username=username) | Q(phone=username) | Q(email=username))
except UserModel.DoesNotExist: except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing return None
# difference between an existing and a nonexistent user (#20760).
UserModel().set_password(password)
else: else:
if user.check_password(password) and self.user_can_authenticate(user): if user.check_password(password) and self.user_can_authenticate(user):
return user return user

View File

@ -35,7 +35,10 @@ class RbacPermission(BasePermission):
:return: :return:
""" """
if not request.user: if not request.user:
perms = ['visitor'] # 如果没有经过认证,视为游客 if request.META.get('HTTP_AUTHORIZATION', None) == 'big_screen':
perms = ['visitor']
else:
return False
else: else:
perms = cache.get(request.user.username + '__perms') perms = cache.get(request.user.username + '__perms')
if not perms: if not perms:

View File

@ -158,7 +158,7 @@ REST_FRAMEWORK = {
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
], ],
'DEFAULT_PERMISSION_CLASSES': [ 'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', # 'rest_framework.permissions.IsAuthenticated',
'apps.system.permission.RbacPermission' 'apps.system.permission.RbacPermission'
], ],
'DEFAULT_RENDERER_CLASSES': [ 'DEFAULT_RENDERER_CLASSES': [

View File

@ -48,9 +48,9 @@ class FitJSONRenderer(JSONRenderer):
response_body = BaseResponse() response_body = BaseResponse()
response = renderer_context.get("response") response = renderer_context.get("response")
status_code = response.status_code # Http状态异常码 status_code = response.status_code # Http状态异常码
print(status_code)
if status_code >= 400: # 如果http响应异常 if status_code >= 400: # 如果http响应异常
if isinstance(data, dict) and 'code' in data: # 如果自定义了异常码 if isinstance(data, dict) \
and 'code' in data and 'msg' in data: # 如果自定义了异常码
response_body = data response_body = data
else: else:
response_body.data = data # data里是详细异常信息 response_body.data = data # data里是详细异常信息