ziliangguanli

This commit is contained in:
shilixia 2021-12-31 09:05:00 +08:00
commit d031f16be7
12 changed files with 298 additions and 42 deletions

View File

@ -2,8 +2,8 @@
ENV = 'development'
# base api
VUE_APP_BASE_API = 'http://127.0.0.1:8000/api'
#VUE_APP_BASE_API = 'http://47.95.0.242:2222/api'
#VUE_APP_BASE_API = 'http://127.0.0.1:8000/api'
VUE_APP_BASE_API = 'http://47.95.0.242:2222/api'
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,

View File

@ -23,6 +23,7 @@
"d3": "^5.14.2",
"dagre-d3": "^0.6.4",
"dhtmlx-gantt": "^6.2.1",
"echarts": "^4.2.0-rc.2",
"element-ui": "^2.15.5",
"file-saver": "^2.0.2",
"fuse.js": "^6.4.6",

View File

@ -282,8 +282,8 @@
that.formData.push(obj)
});
that.formData=[...that.formData];
debugger;
console.log(that.formData)
// debugger;
console.log(that.formData);
//当前表的数据存储
for(let i=0;i<this.results.length;i++){
let key = this.results[i].field_key;
@ -307,18 +307,18 @@
that.$set(that.originForm,key,this.origins[i].field_value)
}*/
//图片地址
// let imag= this.formData.filter(item => {
// return item.field_type === 'draw';
// });
let imag= this.formData.filter(item => {
return item.field_type === 'draw';
});
// that.img = 'http://47.95.0.242:2222'+imag[0].draw_template;
/*let originImag= this.origins.filter(item => {
return item.field_type === 'draw';
});*/
// that.originImg = new Image();
// that.originImg.crossOrigin = '';
// that.originImg = imag[0].origin_value;
/*that.originImg = new Image();
that.originImg.crossOrigin = '';
that.originImg = imag[0].origin_value;
*/
listJudge.forEach(item => {
let obj = new Object();
obj = item;
@ -786,14 +786,16 @@
fieldData(isSubmit){
let that = this;
that.field = []; //检查项目
debugger;
// debugger;
let submit = isSubmit=='1'?false:true;
that.formData.forEach((item) => {
let field_value = 0;
let field_value = null;
if(item.field_type==='int'){
field_value = parseInt(that.checkForm[item.field_key])
}else if(item.field_type==='float'){
field_value = parseFloat(that.checkForm[item.field_key])
}else{
field_value = that.checkForm[item.field_key];
}
that.field.push({
id: item.id,
@ -805,7 +807,7 @@
that.testrecord.record_data = that.field;//检查项列表
that.testrecord.is_testok = that.is_testok;//检查表检查结果
that.testrecord.id = that.recordId;
debugger;
// debugger;
if(submit){//提交
this.$emit('recordSubmit',that.testrecord);
}else {//保存

View File

@ -1,6 +1,6 @@
<template>
<div class="dashboard-container">
<el-card>
<el-card style="margin-bottom: 5px">
<div class="cards">
<div class="cardFirstText">本月2</div>
<div class="cardSecondText">20</div>
@ -27,22 +27,158 @@
<div>累计不合格产品数</div>
</div>
</el-card>
<el-card>
<el-badge :value="count.total_count" class="item" @click.native="gotoTicketPage">
<el-icon class="el-icon-s-management" style="font-size: 70px;color: #d29898"></el-icon>
</el-badge>
<div></div>
<div class="dashboard-text">name: {{ name }}</div>
<div class="dashboard-text">perms: <span v-for="perm in perms" :key="perm">{{ perm }}</span></div>
</el-card>
<el-row :gutter="5" style="margin-bottom: 5px">
<el-col :span="12">
<el-card>
<div style="display: flex">
<div style="height: 35px; line-height:35px;font-size: 24px;font-weight: bold;vertical-align: middle">任务排期</div>
<el-date-picker
v-model="date"
type="month"
placeholder="查询日期"
range-separator=""
format="yyyy 年 MM 月"
value-format="yyyy-MM"
>
</el-date-picker>
<div style="display: flex;border: 1px solid #aaaaaa;border-radius: 6px;height: 35px; line-height:35px;">
<div style=" cursor: pointer;width: 60px;text-align:center;border-right: 1px solid #aaaaaa;"></div>
<div style="width: 60px;text-align:center;border-right: 1px solid #aaaaaa;"></div>
<div style="width: 60px;text-align:center;">三个月</div>
</div>
</div>
<el-table
v-loading="listLoading"
:data="list"
border fit stripe
height="300"
>
<el-table-column type="index" width="50" />
<el-table-column label="任务编号">
<template slot-scope="scope">{{ scope.row.id }}</template>
</el-table-column>
<el-table-column label="产品名称">
<template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
<el-table-column label="产品型号">
<template slot-scope="scope">{{ scope.row.card }}</template>
</el-table-column>
<el-table-column label="生产数量">
<template slot-scope="scope">{{ scope.row.sco }}</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<div style="display: flex">
<div style="height: 35px; line-height:35px;font-size: 24px;font-weight: bold;vertical-align: middle">成品率</div>
<el-date-picker
v-model="date"
type="month"
placeholder="查询日期"
range-separator=""
format="yyyy 年 MM 月"
value-format="yyyy-MM"
>
</el-date-picker>
<div style="display: flex;border: 1px solid #aaaaaa;border-radius: 6px;height: 35px; line-height:35px;">
<div style=" cursor: pointer;width: 60px;text-align:center;border-right: 1px solid #aaaaaa;"></div>
<div style="width: 60px;text-align:center;border-right: 1px solid #aaaaaa;"></div>
<div style="width: 60px;text-align:center;">三个月</div>
</div>
</div>
<div id="chartColumn" style="width:100%; height:300px;"></div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="5" style="margin-bottom: 5px">
<el-col :span="12">
<el-card>
<div style="display: flex">
<div style="height: 35px; line-height:35px;font-size: 24px;font-weight: bold;vertical-align: middle">库存列表</div>
<div class="block">
<el-pagination
:current-page.sync="currentPage"
:page-size="100"
layout="prev, pager, next, jumper"
:total="1000">
</el-pagination>
</div>
</div>
<el-table
v-loading="listLoading"
:data="list"
border fit stripe
height="300"
>
<el-table-column label="物料编号">
<template slot-scope="scope">{{ scope.row.id }}</template>
</el-table-column>
<el-table-column label="物料名称">
<template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
<el-table-column label="规格型号">
<template slot-scope="scope">{{ scope.row.card }}</template>
</el-table-column>
<el-table-column label="物料类型">
<template slot-scope="scope">{{ scope.row.sco }}</template>
</el-table-column>
<el-table-column label="单位">
<template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
<el-table-column label="库存">
<template slot-scope="scope">{{ scope.row.card }}</template>
</el-table-column>
<el-table-column label="仓库">
<template slot-scope="scope">{{ scope.row.sco }}</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
<el-col :span="12">
<el-card style="height: 350px">
<div style="display: flex">
<div style="height: 35px; line-height:35px;font-size: 24px;font-weight: bold;vertical-align: middle">提醒</div>
<div class="block">
<el-pagination
:current-page.sync="currentPage"
:page-size="100"
layout="prev, pager, next, jumper"
:total="1000">
</el-pagination>
</div>
</div>
<el-badge :value="count.total_count" class="item" @click.native="gotoTicketPage">
<el-icon class="el-icon-s-management" style="font-size: 70px;color: #d29898"></el-icon>
</el-badge>
<div></div>
<div class="dashboard-text">name: {{ name }}</div>
<div class="dashboard-text">perms: <span v-for="perm in perms" :key="perm">{{ perm }}</span></div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import echarts from 'echarts'
import { mapGetters } from 'vuex';
export default {
name: 'Dashboard',
data() {
return {
chartColumn: null,
currentPage:1,
total_count:1,
date:'2021-12',
list:[
{id:1,name:'HIehd9',card:'3337',sco:'REF-32'},
{id:1,name:'HIehd9',card:'3337',sco:'REF-32'},
{id:1,name:'HIehd9',card:'3337',sco:'REF-32'}
],
}
},
computed: {
...mapGetters([
'name',
@ -59,6 +195,80 @@ export default {
this.$router.push({name:'ticket',params:{}})
}
},
drawChart() {
this.chartColumn = echarts.init(document.getElementById('chartColumn'));
this.chartColumn.setOption({
// title: { text: '成品率' },
/*tooltip: {
trigger:'axis',
aXisPointer:{
type:'cross'
},
formatter(params){
for(let x in params){
return params[x].name +":"+params[x].data+"%";
}
},
},*/
grid: {
top: '3%',
left: '3%',
right: '4%',
bottom: '1%',
containLabel: true
},
tooltip: {
trigger: 'item',
formatter: function (params) {
var color = params.color;//图例颜色
// var color = "red";//图例颜色
var htmlStr ='<div>';
htmlStr += params.name + '<br/>';
htmlStr += '<span style="height:10px;width:10px;font-size:12px;border-radius:5px;margin-right:5px;font-family:Consolas;display:inline-block;background:'+color+';"></span>';
htmlStr += params.seriesName + ''+params.value + '%';
htmlStr += '</div>';
return htmlStr;
}
},
xAxis: {
data: ["冷加工", "热弯", "钢化", "镀膜", "夹层", "包边", "装框", "成品"]
},
yAxis: {},
series: [{
name: '成品率',
type: 'bar',
barWidth: 40,
data: [80,60,60, 70, 76, 80, 90, 70],
label: {
show: true, //开启显示
position: 'top', //在上方显示
formatter: '{c}%',//显示百分号
textStyle: { //数值样式
color: 'black',//字体颜色
fontSize: 10//字体大小
}
},
itemStyle: {
normal: {
color: function(params) {
var colorList = [
'#5e7e54','#e44f2f','#81b6b2','#eba422',
'#1bcde4','#b61b08','#84eb84','#d8d417'
];
return colorList[params.dataIndex]
},
}
},
}]
});
},
},
mounted () {
this.drawChart()
},
updated () {
this.drawChart()
}
}
</script>

View File

@ -979,6 +979,7 @@
//点击记录里的检验
handleInspectionRecord(scope){
let that =this;
that.fieldList = [];
that.recordVisible = false;
that.recordId = scope.row.id;
that.recordform = scope.row.form;
@ -1033,7 +1034,6 @@
obj.is_testok = null;
for (let j = 0; j < originList.length; j++) {
if (fieldList[i].field_key === originList[j].field_key) {
obj.id = originList[j].id;
obj.is_testok = originList[j].is_testok;
obj.field_value = originList[j].field_value;
obj.origin_value = originList[j].field_value;
@ -1056,6 +1056,7 @@
//点击记录里的查看
handleRecordDetail(scope){
let that = this;
that.fieldList = [];
that.recordVisible = false;
that.recordId = scope.row.id;
that.recordform = scope.row.form;
@ -1098,6 +1099,7 @@
//半产品复检
handleReview() {
let that = this;
that.fieldList = [];
testInit({ wproduct: this.wproduct,form: that.recordform}).then((response) => {
if (response.data) {
that.hasPicture = false;
@ -1111,7 +1113,6 @@
obj.is_testok = null;
for (let j = 0; j < originList.length; j++) {
if (fieldList[i].field_key === originList[j].field_key) {
obj.id = originList[j].id;
obj.is_testok = originList[j].is_testok;
obj.field_value = originList[j].field_value;
obj.origin_value = originList[j].field_value;
@ -1136,6 +1137,7 @@
submitrecordform(index) {
let that = this;
this.outerVisible = false;
that.fieldList = [];
if (that.recordform != "") {
if(index==='1'){//非复检
testInit({ wproduct: that.wproduct,form: that.recordform}).then((response) => {

View File

@ -130,6 +130,7 @@ class WfService(object):
import datetime, time # 用于支持条件表达式中对时间的操作
if eval(expression, {'__builtins__':None}, {'datetime':datetime, 'time':time}):
destination_state = State.objects.get(pk=i['target_state'])
return destination_state
return destination_state
@classmethod
@ -321,7 +322,8 @@ class WfService(object):
if not created:
for key, value in source_state.state_fields.items():
if value in (State.STATE_FIELD_REQUIRED, State.STATE_FIELD_OPTIONAL):
source_ticket_data[key] = new_ticket_data[key]
if key in new_ticket_data:
source_ticket_data[key] = new_ticket_data[key]
ticket.ticket_data = source_ticket_data
ticket.save()

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.9 on 2021-12-30 08:31
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mtm', '0042_alter_recordformfield_field_type'),
('wpm', '0041_wproductflow_change_str'),
]
operations = [
migrations.AddField(
model_name='wprouctticket',
name='resp_process',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.process', verbose_name='责任工序'),
),
]

View File

@ -120,6 +120,7 @@ class WprouctTicket(CommonAModel):
step = models.ForeignKey(Step, verbose_name='所在步骤/发现步骤', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='所在子生产计划', on_delete=models.CASCADE)
resp_process = models.ForeignKey(Process, verbose_name='责任工序', on_delete=models.CASCADE, null=True, blank=True)
ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.CASCADE, related_name='wt_ticket')
decision = models.PositiveSmallIntegerField('最终决定', choices=WProduct.ng_choices, null=True, blank=True)

View File

@ -5,7 +5,7 @@ from apps.em.serializers import EquipmentSimpleSerializer
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse
from apps.inm.signals import update_inm
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial
from apps.mtm.serializers import MaterialSimpleSerializer, RecordFormSimpleSerializer, StepSimpleSerializer
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, RecordFormSimpleSerializer, StepSimpleSerializer
from apps.pm.models import SubProductionPlan, SubProductionProgress
from django.utils import timezone
@ -13,7 +13,7 @@ from django.utils.translation import gettext_lazy as _
from apps.pm.serializers import SubproductionPlanSimpleSerializer
from apps.qm.models import TestRecord, TestRecordItem
from apps.system.serializers import UserSimpleSerializer
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket
from django.db import transaction
class PickHalfSerializer(serializers.Serializer):
@ -429,4 +429,15 @@ class OperationRecordDetailSerializer(serializers.ModelSerializer):
class ScrapSerializer(serializers.Serializer):
scrap_reason = serializers.ChoiceField(choices=WProduct.scrap_reason_choices, required=False)
# wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()), label='半成品ID列表')
# wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()), label='半成品ID列表')
class WproductTicketListSerializer(serializers.ModelSerializer):
material_ = MaterialSimpleSerializer(source='material', read_only=True)
step_ = StepSimpleSerializer(source='step', read_only=True)
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
resp_process_ = ProcessSimpleSerializer(source='resp_process', read_only=True)
class Meta:
model = WprouctTicket
fields = '__all__'

View File

@ -28,7 +28,7 @@ def handleTicket(sender, instance, created, **kwargs):
obj.subproduction_plan = wproduct.subproduction_plan
obj.ticket = instance
test_record = TestRecord.objects.filter(wproduct=wproduct, is_deleted=False, is_testok=False).order_by('-id').first()
# test_record = TestRecord.objects.filter(wproduct=wproduct, is_deleted=False, is_testok=False).order_by('-id').first()
obj.save()
# 工单绑定半成品
@ -36,11 +36,6 @@ def handleTicket(sender, instance, created, **kwargs):
wproduct.save()
WpmServies.add_wproduct_flow_log(wproduct, 'ticket_create')
# 检验员
if not ticket_data.get('tester', None):
ticket_data['tester'] = test_record.create_by.id
instance.ticket_data = ticket_data
instance.save()
elif instance.act_state == Ticket.TICKET_ACT_STATE_FINISH:
"""
@ -58,6 +53,7 @@ def handleTicket(sender, instance, created, **kwargs):
wp.ng_sign = decision
wt.decision = decision
if decision in [WProduct.NG_BACK_WORK, WProduct.NG_BACK_FIX]:
step = Step.objects.get(id=ticket_data['back_step'])
wp.step = step

View File

@ -3,11 +3,12 @@ from rest_framework import urlpatterns
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet
router = DefaultRouter()
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
router.register('wproduct', WProductViewSet, basename='wproduct')
router.register('wproduct_ticket', WproductTicketViewSet, basename='wproduct_ticket')
router.register('operation', OperationViewSet, basename='operation')
router.register('operation_wproduct', OperationWproductViewSet, basename='operation_wproduct')
router.register('operation_equip', OperationEquipViewSet, basename='operation_equip')

View File

@ -20,9 +20,9 @@ from rest_framework.decorators import action
from apps.wf.models import Workflow
from apps.wf.serializers import WorkflowSimpleSerializer
from apps.wpm.filters import WMaterialFilterSet, WProductFilterSet
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket
from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer
from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer
from rest_framework.response import Response
from django.db import transaction
from rest_framework import exceptions, serializers
@ -406,6 +406,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
raise exceptions.APIException('该产品不可发起不合格审理')
workflow = Workflow.objects.filter(name='不合格品审理单', is_deleted=False).first()
if workflow:
test_record = TestRecord.objects.filter(wproduct=obj, is_deleted=False, is_testok=False).order_by('-id').first()
exist_data = {
'wproduct':obj.id,
'wproduct_number':obj.number,
@ -413,6 +414,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
'wproduct_specification':obj.material.specification,
'finder':request.user.id,
'find_process':obj.step.process.id,
'tester':test_record.create_by.id
}
ret = {'workflow':workflow.id}
ret['exist_data'] = exist_data
@ -422,8 +424,16 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
class WproductTicketViewSet(ListModelMixin, GenericViewSet):
"""
玻璃审批工单
"""
perms_map={'*':'*'}
queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan', 'resp_process')
serializer_class = WproductTicketListSerializer
filterset_fields = ['step', 'material', 'subproduction_plan', 'resp_process']
ordering_fields = ['id']
ordering = ['-id']
class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):