ceshi
This commit is contained in:
commit
60f726cda6
|
@ -28,6 +28,7 @@
|
||||||
"file-saver": "^2.0.2",
|
"file-saver": "^2.0.2",
|
||||||
"fuse.js": "^6.4.6",
|
"fuse.js": "^6.4.6",
|
||||||
"js-cookie": "^3.0.0",
|
"js-cookie": "^3.0.0",
|
||||||
|
"mammoth": "^1.4.19",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
|
@ -37,7 +38,7 @@
|
||||||
"vue-quill-editor": "^3.0.6",
|
"vue-quill-editor": "^3.0.6",
|
||||||
"vue-router": "^3.5.2",
|
"vue-router": "^3.5.2",
|
||||||
"vuex": "^3.6.2",
|
"vuex": "^3.6.2",
|
||||||
"webpack-dev-server": "^4.2.0",
|
"webpack-dev-server": "^4.7.3",
|
||||||
"xlsx": "^0.17.1"
|
"xlsx": "^0.17.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
export function faceLogin(data) {
|
||||||
|
return request({
|
||||||
|
url: '/hrm/facelogin/',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function clockRecord(data) {
|
||||||
|
return request({
|
||||||
|
url: '/hrm/clock_record/',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import request from '@/utils/request'
|
||||||
|
|
||||||
export function login(data) {
|
export function login(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/token/',
|
url: '/auth/token/',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,7 @@ export function login(data) {
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return request({
|
return request({
|
||||||
url: '/token/black/',
|
url: '/auth/token/black/',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,6 +299,18 @@
|
||||||
}
|
}
|
||||||
} ,
|
} ,
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'$route.path': function (newVal) {
|
||||||
|
if(newVal==='/dashboard'){
|
||||||
|
this.$refs.leftMenu.handlerSelect(this.list[0]);
|
||||||
|
this.$refs.chart.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
left: this.list[0].left - 30,
|
||||||
|
behavior: "smooth"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
windowWidth:0,
|
windowWidth:0,
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import {faceLogin} from "@/api/testModel";
|
import { clockRecord } from '@/api/hrm'
|
||||||
import { getTickets } from "@/api/workflow";
|
|
||||||
import tracking from '@/assets/tracking/build/tracking-min.js';
|
import tracking from '@/assets/tracking/build/tracking-min.js';
|
||||||
import '@/assets/tracking/build/data/face-min.js';
|
import '@/assets/tracking/build/data/face-min.js';
|
||||||
|
|
||||||
|
@ -62,7 +61,7 @@
|
||||||
// 避免在新的浏览器中使用它,因为它正在被弃用。
|
// 避免在新的浏览器中使用它,因为它正在被弃用。
|
||||||
_this.video.src = window.URL.createObjectURL(stream)
|
_this.video.src = window.URL.createObjectURL(stream)
|
||||||
}
|
}
|
||||||
_this.video.onloadedmetadata = function (e) {
|
_this.video.onloadedmetadata = function () {
|
||||||
_this.video.play();
|
_this.video.play();
|
||||||
};
|
};
|
||||||
_this.init();
|
_this.init();
|
||||||
|
@ -117,33 +116,12 @@
|
||||||
let base64Img = canvas.toDataURL('image/jpeg');
|
let base64Img = canvas.toDataURL('image/jpeg');
|
||||||
let img = base64Img.split(',')[1];
|
let img = base64Img.split(',')[1];
|
||||||
let imgData = {base64:img};
|
let imgData = {base64:img};
|
||||||
faceLogin(imgData).then((res) => {
|
clockRecord(imgData).then((res) => {
|
||||||
if (res.code >= 200) {
|
if (res.code === 200&&res.data.id) {
|
||||||
/* debugger;
|
this.$message.success(res.data.name+'签到成功!');
|
||||||
console.log(res.data);
|
setTimeout(()=>{
|
||||||
getTickets( {token:res.data.access,page:1,page_size:10}).then((resp)=>{
|
|
||||||
if(resp.code>=200){
|
|
||||||
debugger;
|
|
||||||
console.log(resp.data);
|
|
||||||
}
|
|
||||||
})*/
|
|
||||||
that.uploadLock = false;
|
that.uploadLock = false;
|
||||||
this.$message.success(res.data.username+'签到成功!');
|
},3000)
|
||||||
/*that.$confirm("是否提交?", "提示", {
|
|
||||||
confirmButtonText: "确认",
|
|
||||||
cancelButtonText: "取消",
|
|
||||||
type: "warning",
|
|
||||||
}).then(async () => {
|
|
||||||
// that.$emit('func',false);
|
|
||||||
// 请求接口成功以后打开锁
|
|
||||||
that.uploadLock = false;
|
|
||||||
}).catch((err) => {
|
|
||||||
that.$message.success(err);
|
|
||||||
// that.$emit('func',false);
|
|
||||||
// 请求接口成功以后打开锁
|
|
||||||
that.uploadLock = false;
|
|
||||||
});*/
|
|
||||||
// this.$message.success("成功");
|
|
||||||
}else{
|
}else{
|
||||||
// 打开锁
|
// 打开锁
|
||||||
that.uploadLock = false;
|
that.uploadLock = false;
|
||||||
|
|
|
@ -50,7 +50,7 @@ export const constantRoutes = [
|
||||||
path: 'dashboard',
|
path: 'dashboard',
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
component: () => import('@/views/dashboard/index'),
|
component: () => import('@/views/dashboard/index'),
|
||||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
meta: { title: '首页', icon: 'dashboard', affix: true,keepAlive: false }
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
<span class="totalCount">{{contractTotalCurrent}}</span>
|
<span class="totalCount">{{contractTotalCurrent}}</span>
|
||||||
<span>个</span>
|
<span>个</span>
|
||||||
</div>
|
</div>
|
||||||
|
<!--<div style="height: 35px;line-height: 35px;font-size: 16px;color: #333333">
|
||||||
|
<span>本年合同总数:</span>
|
||||||
|
</div>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cardsWrap" @click="toDetail('2')">
|
<div class="cardsWrap" @click="toDetail('2')">
|
||||||
|
@ -141,59 +144,134 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<el-row :gutter="5">
|
<el-row :gutter="5">
|
||||||
<el-col :span="12">
|
<el-col :span="8">
|
||||||
<div class="dashboardBottomRow">
|
<div class="dashboardBottomRow">
|
||||||
<div class="dashboardCardHand">
|
<div class="dashboardCardHand">
|
||||||
<div class="CardTitleWrap">
|
<div class="CardTitleWrap">
|
||||||
<span class="verticalLine"></span><span class="dashboardCardTitle">库存列表</span>
|
<span class="verticalLine"></span><span class="dashboardCardTitle">生产设备</span>
|
||||||
<span class="stockMore" @click="stockMore">更多>></span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
:current-page.sync="stockPage"
|
small
|
||||||
:page-size="stockPageSize"
|
:pager-count="pageCounts"
|
||||||
|
:current-page.sync="equipmentPage"
|
||||||
|
:page-size="equipmentPageSize"
|
||||||
layout="prev, pager, next, jumper"
|
layout="prev, pager, next, jumper"
|
||||||
:total="stockTotal"
|
:total="equipmentTotal"
|
||||||
@size-change="handleStockSizeChange"
|
@current-change="handleEquipmentCurrentChange"
|
||||||
@current-change="handleStockCurrentChange"
|
|
||||||
>
|
>
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dashboardCardPadding">
|
<div class="dashboardCardPadding">
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="listLoadingStock"
|
small
|
||||||
:data="stockList"
|
v-loading="listLoadingEm"
|
||||||
|
:data="equipmentList"
|
||||||
fit stripe
|
fit stripe
|
||||||
size="mini"
|
size="mini"
|
||||||
:height="cardTabelHeight"
|
:height="cardTabelHeight"
|
||||||
|
pager-count="3"
|
||||||
style="border-top: 1px solid #f5f5f5;"
|
style="border-top: 1px solid #f5f5f5;"
|
||||||
>
|
>
|
||||||
<el-table-column label="物料编号" prop="material_">
|
<el-table-column label="序号" type="index" width="50">
|
||||||
<template slot-scope="scope">{{ scope.row.material_.number }}</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="物料名称" prop="material_" show-overflow-tooltip>
|
<el-table-column label="设备编号" prop="number">
|
||||||
<template slot-scope="scope">{{ scope.row.material_.name }}</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="规格型号" prop="material_" show-overflow-tooltip>
|
<el-table-column label="设备名称" prop="name" show-overflow-tooltip>
|
||||||
<template slot-scope="scope">{{ scope.row.material_.specification }}</template>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="物料类型" prop="material_">
|
<el-table-column label="设备状态" prop="material_">
|
||||||
<template slot-scope="scope">{{options[scope.row.material_.type]}}</template>
|
<!--type=1生产设备-->
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div v-if="scope.row.type===1">
|
||||||
|
<el-tag v-if="scope.row.state===40" type="danger">
|
||||||
|
禁用
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="success">
|
||||||
|
合格
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<el-tag v-if="scope.row.state===10" type="success">
|
||||||
|
{{ state_[scope.row.state] }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.state===20">
|
||||||
|
{{ state_[scope.row.state] }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.state===30" type="warning">
|
||||||
|
{{ state_[scope.row.state] }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="danger">
|
||||||
|
{{ state_[scope.row.state] }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="单位" prop="material_">
|
<el-table-column label="下次校准日期" prop="model">
|
||||||
<template slot-scope="scope">{{scope.row.material_.unit}}</template>
|
<template slot-scope="scope">
|
||||||
</el-table-column>
|
<el-tag v-if="scope.row.next_check_date" :type="setClass(scope.row.next_check_date)">
|
||||||
<el-table-column label="库存" prop="count">
|
{{scope.row.next_check_date}}
|
||||||
</el-table-column>
|
</el-tag>
|
||||||
<el-table-column label="仓库" prop="warehouse_">
|
<div v-else></div>
|
||||||
<template slot-scope="scope">{{ scope.row.warehouse_.name }}</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="8">
|
||||||
|
<div class="dashboardBottomRow">
|
||||||
|
<div class="dashboardCardHand">
|
||||||
|
<div class="CardTitleWrap">
|
||||||
|
<span class="verticalLine"></span><span class="dashboardCardTitle">人员到岗</span>
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
<el-pagination
|
||||||
|
small
|
||||||
|
:pager-count="pageCounts"
|
||||||
|
:current-page.sync="userPage"
|
||||||
|
:page-size="userPageSize"
|
||||||
|
layout="prev, pager, next, jumper"
|
||||||
|
:total="userTotal"
|
||||||
|
@current-change="handleUserCurrentChange"
|
||||||
|
>
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="dashboardCardPadding"
|
||||||
|
@mouseenter="stopScroll()"
|
||||||
|
@mouseleave="toScroll()"
|
||||||
|
>
|
||||||
|
<el-table
|
||||||
|
v-loading="listLoadingUser"
|
||||||
|
:data="userList"
|
||||||
|
fit stripe
|
||||||
|
size="mini"
|
||||||
|
:height="cardTabelHeight"
|
||||||
|
style="border-top: 1px solid #f5f5f5;"
|
||||||
|
>
|
||||||
|
<el-table-column label="id" prop="id" width="50">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="人员名称" prop="name" show-overflow-tooltip>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="到岗情况" prop="dept_name">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.is_atwork" type="success">
|
||||||
|
到岗
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="danger">
|
||||||
|
未到
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="部门" prop="dept_name">
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
<div class="dashboardBottomRow">
|
<div class="dashboardBottomRow">
|
||||||
<div class="dashboardCardHand">
|
<div class="dashboardCardHand">
|
||||||
<div class="CardTitleWrap">
|
<div class="CardTitleWrap">
|
||||||
|
@ -201,12 +279,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
:current-page.sync="remindPage"
|
small
|
||||||
:page-size="remindPageSize"
|
:pager-count="pageCounts"
|
||||||
|
:current-page.sync="warningPage"
|
||||||
|
:page-size="warningPageSize"
|
||||||
layout="prev, pager, next, jumper"
|
layout="prev, pager, next, jumper"
|
||||||
:total="remindTotal"
|
:total="warningTotal"
|
||||||
@size-change="handleRemindSizeChange"
|
@size-change="handleWarningSizeChange"
|
||||||
@current-change="handleRemindCurrentChange"
|
@current-change="handleWarningCurrentChange"
|
||||||
>
|
>
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
</div>
|
</div>
|
||||||
|
@ -215,38 +295,31 @@
|
||||||
<el-tabs type="card" :style="{height:cardTabelHeight+'px'}" v-model="activeName"
|
<el-tabs type="card" :style="{height:cardTabelHeight+'px'}" v-model="activeName"
|
||||||
@tab-click="activeNameClick">
|
@tab-click="activeNameClick">
|
||||||
<el-tab-pane label="库存警告" name="库存警告">
|
<el-tab-pane label="库存警告" name="库存警告">
|
||||||
<ul :style="{height:cardTabelHeight-47+'px'}" class="lists" :class="{anim:animate}" @mouseenter="Stop()" @mouseleave="Up()">
|
<ul :style="{height:cardTabelHeight-47+'px'}" class="lists" :class="{anim:animate}" @mouseenter="Stop()"
|
||||||
<li v-for="item in list" :key="item.id" class="listItem">
|
@mouseleave="Up()">
|
||||||
|
<li class="listItem" v-for="item in warningList" :key="item.id">
|
||||||
<div class="itemText">
|
<div class="itemText">
|
||||||
<span>{{item.name}}</span><span style="float: right">2021-12-30</span>
|
<span>{{item.name}}({{item.unit}})</span><span>剩余{{item.count}},低于安全库存{{item.count_safe}}</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="临近交货" name="临近交货">
|
<el-tab-pane label="临近交货" name="临近交货">
|
||||||
<ul class="lists">
|
<ul :style="{height:cardTabelHeight-47+'px'}" class="lists" :class="{anim:animate}" @mouseenter="Stop()"
|
||||||
<li class="listItem">
|
@mouseleave="Up()">
|
||||||
<div class="itemText">
|
|
||||||
<span>某某批货临近交货日期</span><span>2021-12-20</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li class="listItem" v-for="item in warningList" :key="item.id">
|
<li class="listItem" v-for="item in warningList" :key="item.id">
|
||||||
<div class="itemText">
|
<div class="itemText">
|
||||||
<span>{{item}}</span><span>2021-12-20</span>
|
<span>{{item.name}}({{item.number}})</span><span>{{item.delivery_date}}到交货日期</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="过期提醒" name="过期提醒">
|
<el-tab-pane label="过期提醒" name="过期提醒">
|
||||||
<ul class="lists">
|
<ul :style="{height:cardTabelHeight-47+'px'}" class="lists" :class="{anim:animate}" @mouseenter="Stop()"
|
||||||
<li class="listItem">
|
@mouseleave="Up()">
|
||||||
<div class="itemText">
|
|
||||||
<span>某某批货临近过期</span><span>2021-11-20</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li class="listItem" v-for="item in warningList" :key="item.id">
|
<li class="listItem" v-for="item in warningList" :key="item.id">
|
||||||
<div class="itemText">
|
<div class="itemText">
|
||||||
<span>{{item}}</span><span>2021-12-20</span>
|
<span>{{item.name}}({{item.number}})</span><span>{{item.delivery_date}}到期</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -262,15 +335,14 @@
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import echarts from 'echarts'
|
||||||
import {mapGetters} from 'vuex';
|
import {mapGetters} from 'vuex';
|
||||||
import {getPlanGantt} from "@/api/srm";
|
import {getUserList} from "@/api/user";
|
||||||
import {getProcessYield} from "@/api/srm";
|
|
||||||
import {getMaterialList} from "@/api/mtm";
|
import {getMaterialList} from "@/api/mtm";
|
||||||
import {getInventoryList} from "@/api/inm";
|
|
||||||
import {getProductionplanList} from "@/api/pm";
|
import {getProductionplanList} from "@/api/pm";
|
||||||
import {getmaterialbatchList} from "@/api/inm";
|
import {getmaterialbatchList} from "@/api/inm";
|
||||||
import gantt from "@/components/Gantt/dashGantt";
|
import gantt from "@/components/Gantt/dashGantt";
|
||||||
import {getContractList, getOrderList} from "@/api/sam";
|
import {getpEquipmentList} from "@/api/equipment";
|
||||||
|
import {getProcessYield ,getPlanGantt} from "@/api/srm";
|
||||||
|
import {getContractList , getOrderList} from "@/api/sam";
|
||||||
export default {
|
export default {
|
||||||
components: {gantt},
|
components: {gantt},
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
|
@ -278,27 +350,32 @@
|
||||||
return {
|
return {
|
||||||
animate: false,
|
animate: false,
|
||||||
intNum: null,
|
intNum: null,
|
||||||
|
intNumUser: null,
|
||||||
|
animateUser: false,
|
||||||
chartColumn: null,
|
chartColumn: null,
|
||||||
week: null,
|
week: null,
|
||||||
currentTime: null,
|
currentTime: null,
|
||||||
currentYear: null,
|
currentYear: null,
|
||||||
currentMonth: null,
|
currentMonth: null,
|
||||||
currentDay: null,
|
currentDay: null,
|
||||||
stockPage: 1,
|
pageCounts: 5,
|
||||||
stockPageSize: 10,
|
userPage: 1,
|
||||||
stockTotal: 100,
|
userPageSize: 10,
|
||||||
remindPage: 1,
|
userTotal: 0,
|
||||||
remindPageSize: 20,
|
equipmentPage: 1,
|
||||||
remindTotal: 100,
|
equipmentPageSize: 10,
|
||||||
|
equipmentTotal: 0,
|
||||||
|
warningPage: 1,
|
||||||
|
warningPageSize: 10,
|
||||||
|
warningTotal: 0,
|
||||||
tableIndex: null,
|
tableIndex: null,
|
||||||
chartIndex: null,
|
chartIndex: null,
|
||||||
tableDate: '2021-12',
|
tableDate: '2021-12',
|
||||||
chartDate: [],
|
chartDate: [],
|
||||||
proList: [],
|
proList: [],
|
||||||
planList: [],
|
userList: [],
|
||||||
stockList: [],
|
|
||||||
remindList: [],
|
|
||||||
warningList: [],
|
warningList: [],
|
||||||
|
equipmentList: [],
|
||||||
list: [
|
list: [
|
||||||
{id: 1, name: 'HIehd91', card: '3337', sco: 'REF-32'},
|
{id: 1, name: 'HIehd91', card: '3337', sco: 'REF-32'},
|
||||||
{id: 2, name: 'HIehd92', card: '3337', sco: 'REF-32'},
|
{id: 2, name: 'HIehd92', card: '3337', sco: 'REF-32'},
|
||||||
|
@ -308,6 +385,12 @@
|
||||||
{id: 6, name: 'HIehd96', card: '3337', sco: 'REF-32'},
|
{id: 6, name: 'HIehd96', card: '3337', sco: 'REF-32'},
|
||||||
{id: 7, name: 'HIehd97', card: '3337', sco: 'REF-32'},
|
{id: 7, name: 'HIehd97', card: '3337', sco: 'REF-32'},
|
||||||
],
|
],
|
||||||
|
state_: {
|
||||||
|
10: '完好',
|
||||||
|
20: '限用',
|
||||||
|
30: '在修',
|
||||||
|
40: '禁用',
|
||||||
|
},
|
||||||
options: {
|
options: {
|
||||||
"1": '成品',
|
"1": '成品',
|
||||||
"2": '半成品',
|
"2": '半成品',
|
||||||
|
@ -330,7 +413,8 @@
|
||||||
rderTotalCount: null,//累计交付产品总数
|
rderTotalCount: null,//累计交付产品总数
|
||||||
derTotalCount: null,//累计不合格产品总数
|
derTotalCount: null,//累计不合格产品总数
|
||||||
listLoadingPlan: false,
|
listLoadingPlan: false,
|
||||||
listLoadingStock: false,
|
listLoadingEm: false,
|
||||||
|
listLoadingUser: false,
|
||||||
cardTabelHeight: null,
|
cardTabelHeight: null,
|
||||||
ganttHeight: 0,
|
ganttHeight: 0,
|
||||||
}
|
}
|
||||||
|
@ -342,19 +426,48 @@
|
||||||
'count'
|
'count'
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'$route.path': function (newVal) {
|
||||||
|
if(newVal==='/dashboard') {
|
||||||
|
this.getUserList();//用户列表
|
||||||
|
this.getEquipmentList();//设备列表
|
||||||
|
this.getGanttData();//甘特图数据
|
||||||
|
this.getStatisticsData();//统计数据
|
||||||
|
this.getNoticeData();//提醒列表
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setClass:function(check_date) {
|
||||||
|
let obj = {};
|
||||||
|
if(check_date!=null){
|
||||||
|
let dat = new Date();
|
||||||
|
let time = dat.getTime();
|
||||||
|
let check = new Date(check_date).getTime();
|
||||||
|
let timeDiffer = (check-time)/1000/60/60/24;
|
||||||
|
if (4>timeDiffer&&timeDiffer>0) {
|
||||||
|
obj = 'warning';
|
||||||
|
}else if (timeDiffer<0) {
|
||||||
|
obj = "danger";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
getNoticeData() {
|
getNoticeData() {
|
||||||
this.ScrollUp();
|
this.ScrollUp();
|
||||||
},
|
},
|
||||||
ScrollUp() {
|
ScrollUp() {
|
||||||
this.intNum = setInterval(() => {
|
let that = this;
|
||||||
this.animate = true;
|
that.intNum = setInterval(() => {
|
||||||
|
if(that.warningList.length>3){
|
||||||
|
that.animate = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.list.push(this.list[0]);
|
that.warningList.push(that.warningList[0]);
|
||||||
this.list.shift();
|
that.warningList.shift();
|
||||||
this.animate = false;
|
that.animate = false;
|
||||||
}, 500)
|
}, 3000)
|
||||||
}, 1000);
|
}
|
||||||
|
}, 3000);
|
||||||
},
|
},
|
||||||
//鼠标移上去停止
|
//鼠标移上去停止
|
||||||
Stop() {
|
Stop() {
|
||||||
|
@ -433,12 +546,85 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
//获取库存警告
|
//获取库存警告
|
||||||
getMaterialList({tag: 'low_inm'}).then((response) => {
|
getMaterialList({page: 1, page_size:that.warningPageSize,tag: 'low_inm'}).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
|
debugger;
|
||||||
that.warningList = response.data.results;
|
that.warningList = response.data.results;
|
||||||
|
that.warningTotal = response.data.count;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
//设备列表
|
||||||
|
getEquipmentList() {
|
||||||
|
let that = this;
|
||||||
|
this.listLoadingEm = true;
|
||||||
|
getpEquipmentList({page: that.equipmentPage, page_size: that.equipmentPageSize}).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
that.equipmentList = response.data.results;
|
||||||
|
that.equipmentTotal = response.data.count;
|
||||||
|
}
|
||||||
|
that.listLoadingEm = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//设备分页跳转
|
||||||
|
handleEquipmentCurrentChange(val) {
|
||||||
|
let that = this;
|
||||||
|
that.listLoadingEm = true;
|
||||||
|
that.equipmentPage = val;
|
||||||
|
getpEquipmentList({page: val, page_size: that.equipmentPageSize}).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
that.equipmentList = response.data.results;
|
||||||
|
that.equipmentTotal = response.data.count;
|
||||||
|
}
|
||||||
|
that.listLoadingEm = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//用户列表
|
||||||
|
getUserList() {
|
||||||
|
let that = this;
|
||||||
|
that.listLoadingUser = true;
|
||||||
|
getUserList({page: that.userPage, page_size: that.userPageSize, fields: 'id,name,dept_name,is_atwork'}).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
that.userList = response.data.results;
|
||||||
|
that.userTotal = response.data.count;
|
||||||
|
that.userScroll();
|
||||||
|
}
|
||||||
|
that.listLoadingUser = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//用户分页跳转
|
||||||
|
handleUserCurrentChange(val) {
|
||||||
|
let that = this;
|
||||||
|
that.listLoadingUser = true;
|
||||||
|
that.userPage = val;
|
||||||
|
getUserList({page: val, page_size: that.userPageSize, fields: 'id,name,dept_name,is_atwork'}).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
that.userList = response.data.results;
|
||||||
|
that.userTotal = response.data.count;
|
||||||
|
that.userScroll();
|
||||||
|
}
|
||||||
|
that.listLoadingUser = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
userScroll() {
|
||||||
|
let that = this;
|
||||||
|
that.intNumUser = setInterval(() => {
|
||||||
|
that.animateUser = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
that.userList.push(that.userList[0]);
|
||||||
|
that.userList.shift();
|
||||||
|
that.animateUser = false;
|
||||||
|
}, 3000)
|
||||||
|
}, 3000);
|
||||||
|
},
|
||||||
|
//鼠标移上去停止
|
||||||
|
stopScroll() {
|
||||||
|
clearInterval(this.intNumUser);
|
||||||
|
},
|
||||||
|
toScroll() {
|
||||||
|
this.userScroll();
|
||||||
|
},
|
||||||
|
//去往工作流页面
|
||||||
gotoTicketPage() {
|
gotoTicketPage() {
|
||||||
let path = this.$route.path;
|
let path = this.$route.path;
|
||||||
if (path === '/workflow/ticket') {
|
if (path === '/workflow/ticket') {
|
||||||
|
@ -448,7 +634,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//任务排期列表
|
//任务排期列表
|
||||||
getPlanList() {
|
/*getPlanList() {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.listLoadingPlan = true;
|
this.listLoadingPlan = true;
|
||||||
getProductionplanList({page: 0}).then((response) => {
|
getProductionplanList({page: 0}).then((response) => {
|
||||||
|
@ -457,9 +643,9 @@
|
||||||
}
|
}
|
||||||
this.listLoadingPlan = false;
|
this.listLoadingPlan = false;
|
||||||
});
|
});
|
||||||
},
|
},*/
|
||||||
//库存列表
|
//库存列表
|
||||||
getStockList() {
|
/*getStockList() {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.listLoadingStock = true;
|
this.listLoadingStock = true;
|
||||||
getInventoryList({page: this.stockPage, page_size: this.stockPageSize}).then((response) => {
|
getInventoryList({page: this.stockPage, page_size: this.stockPageSize}).then((response) => {
|
||||||
|
@ -470,6 +656,17 @@
|
||||||
this.listLoadingStock = false;
|
this.listLoadingStock = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
//更多库存
|
||||||
|
stockMore() {
|
||||||
|
this.$router.push({name: 'warehouse', params: {}})
|
||||||
|
},
|
||||||
|
//库存pageSize改变
|
||||||
|
// @size-change="handleStockSizeChange"
|
||||||
|
handleEquipmentSizeChange(val) {
|
||||||
|
this.stockPageSize = val;
|
||||||
|
this.stockPage = 1;
|
||||||
|
},
|
||||||
|
*/
|
||||||
//图标渲染
|
//图标渲染
|
||||||
drawChart() {
|
drawChart() {
|
||||||
let that = this;
|
let that = this;
|
||||||
|
@ -583,9 +780,7 @@
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
stockMore() {
|
|
||||||
this.$router.push({name: 'warehouse', params: {}})
|
|
||||||
},
|
|
||||||
toDetail(index) {
|
toDetail(index) {
|
||||||
if (index === '1') {
|
if (index === '1') {
|
||||||
this.$router.push({name: 'contract', params: {page: 1, page_size: 20}})
|
this.$router.push({name: 'contract', params: {page: 1, page_size: 20}})
|
||||||
|
@ -594,9 +789,9 @@
|
||||||
} else if (index === '3') {
|
} else if (index === '3') {
|
||||||
this.$router.push({name: 'management', params: {page: 1, page_size: 20}})
|
this.$router.push({name: 'management', params: {page: 1, page_size: 20}})
|
||||||
} else if (index === '4') {
|
} else if (index === '4') {
|
||||||
this.$router.push({name: 'product', params: {page: 1, page_size: 20, material__type: 1}})
|
this.$router.push({name: 'product'})
|
||||||
} else if (index === '5') {
|
} else if (index === '5') {
|
||||||
this.$router.push({name: 'product', params: {page: 1, page_size: 20, material__type: 1}})
|
this.$router.push({name: 'unproduct'})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//便捷查询按钮
|
//便捷查询按钮
|
||||||
|
@ -650,7 +845,6 @@
|
||||||
this.drawChart();
|
this.drawChart();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
//根据时间和类型获取数据
|
//根据时间和类型获取数据
|
||||||
},
|
},
|
||||||
|
@ -683,55 +877,41 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//库存
|
|
||||||
handleStockSizeChange(val) {
|
|
||||||
this.stockPageSize = val;
|
|
||||||
this.stockPage = 1;
|
|
||||||
},
|
|
||||||
//库存
|
|
||||||
handleStockCurrentChange(val) {
|
|
||||||
let that = this;
|
|
||||||
this.listLoading = true;
|
|
||||||
this.stockPage = val;
|
|
||||||
getInventoryList({page: val, page_size: this.stockPageSize}).then((response) => {
|
|
||||||
if (response.data) {
|
|
||||||
that.stockList = response.data.results;
|
|
||||||
that.stockTotal = response.data.count;
|
|
||||||
}
|
|
||||||
this.listLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
//提示
|
//提示
|
||||||
activeNameClick(tab) {
|
activeNameClick(tab) {
|
||||||
|
debugger;
|
||||||
|
debugger;
|
||||||
let that = this;
|
let that = this;
|
||||||
|
that.warningPage = 1;
|
||||||
|
that.warningList = [];
|
||||||
if (tab.label === '库存警告') {
|
if (tab.label === '库存警告') {
|
||||||
getMaterialList({page: 0, tag: 'low_inm'}).then((response) => {
|
getMaterialList({page: 1, page_size:that.warningPageSize, tag: 'low_inm'}).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
that.warningList = response.data;
|
that.warningList = response.data.results;
|
||||||
that.remindTotal = response.data.length;
|
that.warningTotal = response.data.count;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (tab.label === '临近交货') {
|
} else if (tab.label === '临近交货') {
|
||||||
getmaterialbatchList({page: 0, tag: 'expired'}).then((response) => {
|
getOrderList({page: 1, page_size:that.warningPageSize,tag:'near_delivery'}).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
that.warningList = response.data;
|
that.warningList = response.data.results;
|
||||||
that.remindTotal = response.data.length;
|
that.warningTotal = response.data.count;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (tab.label === '过期提醒') {
|
} else if (tab.label === '过期提醒') {
|
||||||
getmaterialbatchList({page: 0, tag: 'expired'}).then((response) => {
|
getmaterialbatchList({page: 1, page_size:that.warningPageSize, tag: 'expired'}).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
that.warningList = response.data;
|
that.warningList = response.data.results;
|
||||||
that.remindTotal = response.data.length;
|
that.warningTotal = response.data.count;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleRemindSizeChange(val) {
|
handleWarningSizeChange(val) {
|
||||||
this.remindPageSize = val;
|
this.warningPageSize = val;
|
||||||
this.remindPage = 1;
|
this.warningPage = 1;
|
||||||
},
|
},
|
||||||
handleRemindCurrentChange(val) {
|
handleWarningCurrentChange(val) {
|
||||||
console.log(`当前页: ${val}`);
|
console.log(`当前页: ${val}`);
|
||||||
},
|
},
|
||||||
getGanttData() {
|
getGanttData() {
|
||||||
|
@ -807,23 +987,21 @@
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
let hei = document.getElementsByClassName('app-main')[0].clientHeight;
|
let hei = document.getElementsByClassName('app-main')[0].clientHeight;
|
||||||
let heig = document.getElementsByClassName('dashboardTopCard')[0].clientHeight;
|
let heig = document.getElementsByClassName('dashboardTopCard')[0].clientHeight;
|
||||||
this.cardTabelHeight = ((hei - heig - 130) / 2);
|
let domHeight = ((hei - heig - 140) / 2);
|
||||||
this.ganttHeight = this.cardTabelHeight - 50;
|
this.cardTabelHeight = domHeight-35;
|
||||||
document.getElementById('chartColumn').style.height = this.cardTabelHeight - 35 + 'px';
|
this.ganttHeight = domHeight - 10;
|
||||||
this.getPlanList();
|
document.getElementById('chartColumn').style.height = domHeight + 'px';
|
||||||
this.getStockList();
|
this.getUserList();//用户列表
|
||||||
this.getGanttData();
|
this.getEquipmentList();//设备列表
|
||||||
this.getStatisticsData();
|
this.getGanttData();//甘特图数据
|
||||||
this.getNoticeData();
|
this.getStatisticsData();//统计数据
|
||||||
|
this.getNoticeData();//提醒列表
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.el-card.is-always-shadow {
|
.el-card.is-always-shadow {
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
|
@ -867,6 +1045,7 @@
|
||||||
.cardsWrap:nth-child(1) {
|
.cardsWrap:nth-child(1) {
|
||||||
.svgIconWrap {
|
.svgIconWrap {
|
||||||
background: #e9f3ff;
|
background: #e9f3ff;
|
||||||
|
|
||||||
.svgIcon {
|
.svgIcon {
|
||||||
color: #409EFF;
|
color: #409EFF;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "largeScreen"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -91,6 +91,14 @@
|
||||||
<el-table-column label="检查类型">
|
<el-table-column label="检查类型">
|
||||||
<template slot-scope="scope">{{ checkTypes[scope.row.type] }}</template>
|
<template slot-scope="scope">{{ checkTypes[scope.row.type] }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="操作人">
|
||||||
|
<template slot-scope="scope">{{ scope.row.create_by_.name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作时间">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{scope.row.update_time.substring(0,scope.row.update_time.length-3)}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="是否提交">
|
<el-table-column label="是否提交">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span v-if="scope.row.is_submited">已提交</span>
|
<span v-if="scope.row.is_submited">已提交</span>
|
||||||
|
@ -116,27 +124,45 @@
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col v-for="item in fieldList" :key="item.id" :span="12">
|
<el-col :span="12">
|
||||||
<div class="items">
|
<div class="items">
|
||||||
|
<span class="itemLabel">操作人:</span>
|
||||||
|
<span>{{create_by_}}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="items">
|
||||||
|
<span class="itemLabel">操作时间:</span>
|
||||||
|
<span>{{update_time}}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col v-for="item in fieldList" :key="item.id" :span="12">
|
||||||
|
<div class="items" v-if="item.field_type!=='draw'&&item.field_value!==null&&item.field_value!==''">
|
||||||
<span class="itemLabel">{{item.field_name}}:</span>
|
<span class="itemLabel">{{item.field_name}}:</span>
|
||||||
<span>{{item.field_value}}</span>
|
<span>{{item.field_value}}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col v-for="item in fieldList" :key="item.id" :span="24">
|
||||||
|
<div class="items" v-if="item.field_type==='draw'" style="height: 400px">
|
||||||
|
<span class="itemLabel">{{item.field_name}}:</span>
|
||||||
|
<img style="width: 45%;vertical-align: text-top;" :src="'http://47.95.0.242:2222'+item.field_value"/>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getfifodetailList } from "@/api/inm";
|
import {getfifodetailList} from "@/api/inm";
|
||||||
import checkPermission from "@/utils/permission";
|
import checkPermission from "@/utils/permission";
|
||||||
import { mtest,getwproductList } from "@/api/wpm";
|
import {mtest, getwproductList} from "@/api/wpm";
|
||||||
import { getrecordformList, getrffieldList} from "@/api/mtm";
|
import {getrecordformList, getrffieldList} from "@/api/mtm";
|
||||||
import {getTestRecord,getTestRecordItem} from "@/api/qm";
|
import {getTestRecord, getTestRecordItem} from "@/api/qm";
|
||||||
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { Pagination },
|
components: {Pagination},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
wproductList: {
|
wproductList: {
|
||||||
|
@ -171,6 +197,8 @@ export default {
|
||||||
mtestform: {
|
mtestform: {
|
||||||
is_mtestok: false,
|
is_mtestok: false,
|
||||||
},
|
},
|
||||||
|
create_by_: '',
|
||||||
|
update_time: '',
|
||||||
wproduct: null,
|
wproduct: null,
|
||||||
recordList: [],
|
recordList: [],
|
||||||
fieldList: [],
|
fieldList: [],
|
||||||
|
@ -239,6 +267,8 @@ export default {
|
||||||
handleRecordDetail(scope) {
|
handleRecordDetail(scope) {
|
||||||
let that = this;
|
let that = this;
|
||||||
that.fieldList = [];
|
that.fieldList = [];
|
||||||
|
that.create_by_ = scope.row.create_by_.name;
|
||||||
|
that.update_time = scope.row.update_time;
|
||||||
getTestRecordItem(scope.row.id).then((res) => {
|
getTestRecordItem(scope.row.id).then((res) => {
|
||||||
if (res.code >= 200) {
|
if (res.code >= 200) {
|
||||||
debugger;
|
debugger;
|
||||||
|
|
|
@ -29,6 +29,16 @@
|
||||||
{{checkTypes[scope.row.type]}}
|
{{checkTypes[scope.row.type]}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="操作人">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.create_by_.name }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作时间">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{scope.row.update_time.substring(0,scope.row.update_time.length-3)}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="是否提交">
|
<el-table-column label="是否提交">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span v-if="scope.row.is_submited">已提交</span>
|
<span v-if="scope.row.is_submited">已提交</span>
|
||||||
|
@ -48,8 +58,20 @@
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="items">
|
||||||
|
<span class="itemLabel">操作人:</span>
|
||||||
|
<span>{{create_by_}}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="items">
|
||||||
|
<span class="itemLabel">操作时间:</span>
|
||||||
|
<span>{{update_time}}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
<el-col v-for="item in fieldList" :key="item.id" :span="12">
|
<el-col v-for="item in fieldList" :key="item.id" :span="12">
|
||||||
<div class="items" v-if="item.field_type!=='draw'">
|
<div class="items" v-if="item.field_type!=='draw'&&item.field_value!==null&&item.field_value!==''">
|
||||||
<span class="itemLabel">{{item.field_name}}:</span>
|
<span class="itemLabel">{{item.field_name}}:</span>
|
||||||
<span>{{item.field_value}}</span>
|
<span>{{item.field_value}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,6 +111,8 @@
|
||||||
50: '已完成',
|
50: '已完成',
|
||||||
60: '军检完成'
|
60: '军检完成'
|
||||||
},
|
},
|
||||||
|
create_by_:'',
|
||||||
|
update_time:'',
|
||||||
recordVisible: false,
|
recordVisible: false,
|
||||||
customfieldList: [],
|
customfieldList: [],
|
||||||
recordform: null,
|
recordform: null,
|
||||||
|
@ -140,6 +164,8 @@
|
||||||
handleRecordDetail(scope) {
|
handleRecordDetail(scope) {
|
||||||
let that = this;
|
let that = this;
|
||||||
that.fieldList = [];
|
that.fieldList = [];
|
||||||
|
that.create_by_ = scope.row.create_by_.name;
|
||||||
|
that.update_time = scope.row.update_time;
|
||||||
getTestRecordItem(scope.row.id).then((res) => {
|
getTestRecordItem(scope.row.id).then((res) => {
|
||||||
if (res.code >= 200) {
|
if (res.code >= 200) {
|
||||||
debugger;
|
debugger;
|
||||||
|
|
|
@ -474,6 +474,14 @@
|
||||||
<el-table-column label="检查类型">
|
<el-table-column label="检查类型">
|
||||||
<template slot-scope="scope">{{ checkTypes[scope.row.type] }}</template>
|
<template slot-scope="scope">{{ checkTypes[scope.row.type] }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="操作人">
|
||||||
|
<template slot-scope="scope">{{ scope.row.create_by_.name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作时间">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{scope.row.update_time.substring(0,scope.row.update_time.length-3)}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="是否提交">
|
<el-table-column label="是否提交">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span v-if="scope.row.is_submited">已提交</span>
|
<span v-if="scope.row.is_submited">已提交</span>
|
||||||
|
@ -620,8 +628,20 @@
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="items">
|
||||||
|
<span class="itemLabel">操作人:</span>
|
||||||
|
<span>{{create_by_}}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="items">
|
||||||
|
<span class="itemLabel">操作时间:</span>
|
||||||
|
<span>{{update_time}}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
<el-col v-for="item in fieldList" :key="item.id" :span="12">
|
<el-col v-for="item in fieldList" :key="item.id" :span="12">
|
||||||
<div class="items" v-if="item.field_type!=='draw'">
|
<div class="items" v-if="item.field_type!=='draw'&&item.field_value!==null&&item.field_value!==''">
|
||||||
<span class="itemLabel">{{item.field_name}}:</span>
|
<span class="itemLabel">{{item.field_name}}:</span>
|
||||||
<span>{{item.field_value}}</span>
|
<span>{{item.field_value}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -693,6 +713,8 @@
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 20,
|
page_size: 20,
|
||||||
},
|
},
|
||||||
|
create_by_: '',
|
||||||
|
update_time: '',
|
||||||
formLabelWidth: '',
|
formLabelWidth: '',
|
||||||
formLabelWidthL: '',
|
formLabelWidthL: '',
|
||||||
actstate_: {
|
actstate_: {
|
||||||
|
@ -1109,6 +1131,8 @@
|
||||||
handleRecordDetail(scope) {
|
handleRecordDetail(scope) {
|
||||||
let that = this;
|
let that = this;
|
||||||
that.fieldList = [];
|
that.fieldList = [];
|
||||||
|
that.create_by_ = scope.row.create_by_.name;
|
||||||
|
that.update_time = scope.row.update_time;
|
||||||
getTestRecordItem(scope.row.id).then((res) => {
|
getTestRecordItem(scope.row.id).then((res) => {
|
||||||
if (res.code >= 200) {
|
if (res.code >= 200) {
|
||||||
that.recordFinishedVisible = true;
|
that.recordFinishedVisible = true;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
from rest_framework_simplejwt.views import (TokenObtainPairView,
|
||||||
|
TokenRefreshView)
|
||||||
|
# Register your models here.
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AuthConfig(AppConfig):
|
||||||
|
name = 'apps.auth1'
|
||||||
|
verbose_name = "认证"
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
|
@ -0,0 +1,5 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
class LoginSerializer(serializers.Serializer):
|
||||||
|
username = serializers.CharField(label="用户名")
|
||||||
|
password = serializers.CharField(label="密码")
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,12 @@
|
||||||
|
from django.urls import path
|
||||||
|
from rest_framework_simplejwt.views import (TokenObtainPairView,
|
||||||
|
TokenRefreshView)
|
||||||
|
|
||||||
|
from apps.auth1.views import LoginView, LogoutView, TokenBlackView
|
||||||
|
urlpatterns = [
|
||||||
|
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
|
||||||
|
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
||||||
|
path('token/black/', TokenBlackView.as_view(), name='token_black'),
|
||||||
|
path('login/', LoginView.as_view(), name='api_login'),
|
||||||
|
path('logout/', LogoutView.as_view(), name='api_logout')
|
||||||
|
]
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
from django.shortcuts import render
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
from django.contrib.auth import authenticate, login, logout
|
||||||
|
from rest_framework.generics import CreateAPIView
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
|
from apps.auth1.serializers import LoginSerializer
|
||||||
|
# Create your views here.
|
||||||
|
|
||||||
|
class TokenBlackView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs): # 可将token加入黑名单
|
||||||
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
class LoginView(CreateAPIView):
|
||||||
|
authentication_classes = []
|
||||||
|
permission_classes = []
|
||||||
|
serializer_class = LoginSerializer
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
账户密码登录
|
||||||
|
"""
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.validated_data
|
||||||
|
user = authenticate(username = vdata.get('username'),
|
||||||
|
password = vdata.get('password'))
|
||||||
|
if user is not None:
|
||||||
|
login(request, user)
|
||||||
|
return Response()
|
||||||
|
return Response('登录失败', status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
class LogoutView(APIView):
|
||||||
|
authentication_classes = []
|
||||||
|
permission_classes = []
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
退出登录
|
||||||
|
"""
|
||||||
|
logout(request)
|
||||||
|
return Response()
|
|
@ -2,7 +2,7 @@ from django.db.models import base
|
||||||
from rest_framework import urlpatterns
|
from rest_framework import urlpatterns
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateFIFOItem, UpdateLastTestResult, UpdateSpg
|
from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateLastTestResult, UpdateSpg
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('cleandata/', CleanDataView.as_view()),
|
path('cleandata/', CleanDataView.as_view()),
|
||||||
|
@ -10,6 +10,7 @@ urlpatterns = [
|
||||||
path('update_last_result/', UpdateLastTestResult.as_view()),
|
path('update_last_result/', UpdateLastTestResult.as_view()),
|
||||||
path('update_last_result/', UpdateLastTestResult.as_view()),
|
path('update_last_result/', UpdateLastTestResult.as_view()),
|
||||||
path('update_fifoitem/', UpdateFIFOItem.as_view()),
|
path('update_fifoitem/', UpdateFIFOItem.as_view()),
|
||||||
path('update_spg/', UpdateSpg.as_view())
|
path('update_spg/', UpdateSpg.as_view()),
|
||||||
|
path('update_equip_state/', UpdateEquipState.as_view())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ from apps.sam.models import Order
|
||||||
from apps.wf.models import Ticket
|
from apps.wf.models import Ticket
|
||||||
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
|
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
|
||||||
from apps.wpm.services import WpmServies
|
from apps.wpm.services import WpmServies
|
||||||
|
from apps.em.tasks import update_equip_state_by_next_check_date
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
class CleanDataView(APIView):
|
class CleanDataView(APIView):
|
||||||
|
@ -91,3 +92,11 @@ class UpdateSpg(APIView):
|
||||||
for i in SubProductionPlan.objects.filter(subproduction__process__id=1):
|
for i in SubProductionPlan.objects.filter(subproduction__process__id=1):
|
||||||
WpmServies.update_subproduction_progress_main(sp=i)
|
WpmServies.update_subproduction_progress_main(sp=i)
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateEquipState(APIView):
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
|
||||||
|
def post(self, request, format=None):
|
||||||
|
update_equip_state_by_next_check_date()
|
||||||
|
return Response()
|
|
@ -0,0 +1,13 @@
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from celery import shared_task
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from apps.em.models import Equipment
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def update_equip_state_by_next_check_date():
|
||||||
|
Equipment.objects.filter(next_check_date__lt=timezone.now()).update(
|
||||||
|
state = Equipment.EQUIP_STATE_DISABLE
|
||||||
|
)
|
|
@ -6,20 +6,9 @@ from apps.system.serializers import UserListSerializer, UserSimpleSerializer
|
||||||
from django.db.models.query import Prefetch
|
from django.db.models.query import Prefetch
|
||||||
|
|
||||||
class EmployeeSerializer(ModelSerializer):
|
class EmployeeSerializer(ModelSerializer):
|
||||||
# user_ = UserListSerializer(source='user', read_only=True)
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
fields = '__all__'
|
exclude = ['face_data']
|
||||||
# @staticmethod
|
|
||||||
# def setup_eager_loading(queryset):
|
|
||||||
# """ Perform necessary eager loading of data. """
|
|
||||||
# queryset = queryset.select_related('user', 'user__dept')
|
|
||||||
# # queryset = queryset.prefetch_related('user','user__dept')
|
|
||||||
# queryset = queryset.prefetch_related(
|
|
||||||
# Prefetch('user_',
|
|
||||||
# queryset=User.objects.filter(employee_user__isnull=True))
|
|
||||||
# )
|
|
||||||
# return queryset
|
|
||||||
|
|
||||||
class FaceLoginSerializer(serializers.Serializer):
|
class FaceLoginSerializer(serializers.Serializer):
|
||||||
base64 = serializers.CharField()
|
base64 = serializers.CharField()
|
||||||
|
|
|
@ -3,7 +3,9 @@ import uuid
|
||||||
import face_recognition
|
import face_recognition
|
||||||
import os
|
import os
|
||||||
from apps.hrm.models import Employee
|
from apps.hrm.models import Employee
|
||||||
|
from apps.hrm.tasks import update_all_user_facedata_cache
|
||||||
from apps.system.models import User
|
from apps.system.models import User
|
||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
class HRMService:
|
class HRMService:
|
||||||
|
|
||||||
|
@ -22,18 +24,25 @@ class HRMService:
|
||||||
return None, '头像解码失败'
|
return None, '头像解码失败'
|
||||||
|
|
||||||
# 匹配人脸库
|
# 匹配人脸库
|
||||||
user_faces = Employee.objects.filter(face_data__isnull=False,
|
face_datas = cache.get('face_datas')
|
||||||
user__is_active=True).values('user', 'face_data')
|
face_users = cache.get('face_users')
|
||||||
user_l = []
|
if face_datas is None:
|
||||||
face_l = []
|
update_all_user_facedata_cache()
|
||||||
for i in user_faces:
|
|
||||||
user_l.append(i['user'])
|
|
||||||
face_l.append(i['face_data'])
|
|
||||||
|
|
||||||
results = face_recognition.compare_faces(face_l, unknown_face_encoding, tolerance=0.5)
|
results = face_recognition.compare_faces(face_datas, unknown_face_encoding, tolerance=0.5)
|
||||||
for index, value in enumerate(results):
|
for index, value in enumerate(results):
|
||||||
if value:
|
if value:
|
||||||
# 识别成功
|
# 识别成功
|
||||||
user = User.objects.get(id=user_l[index])
|
user = User.objects.get(id=face_users[index])
|
||||||
return user, ''
|
return user, ''
|
||||||
return None, '识别失败'
|
return None, '识别失败'
|
||||||
|
|
||||||
|
def get_facedata_from_img(cls, img_rpath):
|
||||||
|
try:
|
||||||
|
photo_path = settings.BASE_DIR + img_rpath
|
||||||
|
picture_of_me = face_recognition.load_image_file(photo_path)
|
||||||
|
my_face_encoding = face_recognition.face_encodings(picture_of_me)[0]
|
||||||
|
face_data_list = my_face_encoding.tolist()
|
||||||
|
return face_data_list
|
||||||
|
except:
|
||||||
|
return None
|
|
@ -2,6 +2,10 @@ from django.db.models.signals import post_save
|
||||||
from apps.system.models import User
|
from apps.system.models import User
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from apps.hrm.models import Employee
|
from apps.hrm.models import Employee
|
||||||
|
from django.conf import settings
|
||||||
|
import face_recognition
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger('log')
|
||||||
|
|
||||||
@receiver(post_save, sender=User)
|
@receiver(post_save, sender=User)
|
||||||
def createEmployee(sender, instance, created, **kwargs):
|
def createEmployee(sender, instance, created, **kwargs):
|
||||||
|
|
|
@ -1,8 +1,31 @@
|
||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
from apps.hrm.models import Employee
|
||||||
|
from apps.system.models import User
|
||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def x():
|
def update_all_user_not_atwork():
|
||||||
print('ok')
|
"""
|
||||||
|
将所有员工设为非在岗状态
|
||||||
|
"""
|
||||||
|
User.objects.all().update(is_atwork=False)
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def update_all_user_facedata_cache():
|
||||||
|
"""
|
||||||
|
更新人脸数据缓存
|
||||||
|
"""
|
||||||
|
facedata_queyset = Employee.objects.filter(face_data__isnull=False,
|
||||||
|
user__is_active=True).values('user', 'face_data')
|
||||||
|
face_users = []
|
||||||
|
face_datas = []
|
||||||
|
for i in facedata_queyset:
|
||||||
|
face_users.append(i['user'])
|
||||||
|
face_datas.append(i['face_data'])
|
||||||
|
cache.set('face_users', face_users, timeout=None)
|
||||||
|
cache.set('face_datas', face_datas, timeout=None)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from functools import update_wrapper
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
@ -5,13 +6,13 @@ from rest_framework.viewsets import ModelViewSet, GenericViewSet
|
||||||
from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin
|
from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin
|
||||||
from apps.hrm.filters import ClockRecordFilterSet
|
from apps.hrm.filters import ClockRecordFilterSet
|
||||||
from apps.hrm.services import HRMService
|
from apps.hrm.services import HRMService
|
||||||
|
from apps.hrm.tasks import update_all_user_facedata_cache
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||||
from apps.hrm.models import ClockRecord, Employee
|
from apps.hrm.models import ClockRecord, Employee
|
||||||
from apps.hrm.serializers import ClockRecordListSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer
|
from apps.hrm.serializers import ClockRecordListSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer
|
||||||
import face_recognition
|
|
||||||
from django.conf import settings
|
|
||||||
from django.core.cache import cache
|
|
||||||
import logging
|
|
||||||
from rest_framework.generics import CreateAPIView
|
from rest_framework.generics import CreateAPIView
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework_simplejwt.tokens import RefreshToken
|
from rest_framework_simplejwt.tokens import RefreshToken
|
||||||
|
@ -19,20 +20,8 @@ from rest_framework import exceptions
|
||||||
from apps.system.models import User
|
from apps.system.models import User
|
||||||
from apps.system.serializers import UserSimpleSerializer
|
from apps.system.serializers import UserSimpleSerializer
|
||||||
from rest_framework.permissions import AllowAny
|
from rest_framework.permissions import AllowAny
|
||||||
logger = logging.getLogger('log')
|
|
||||||
|
|
||||||
|
|
||||||
def load_face_data(username:int, path:str):
|
|
||||||
"""
|
|
||||||
将某用户face_encoding加载进缓存
|
|
||||||
"""
|
|
||||||
face_datas = cache.get_or_set('face_datas', {}, timeout=None)
|
|
||||||
photo_path = settings.BASE_DIR + path
|
|
||||||
picture_of_me = face_recognition.load_image_file(photo_path)
|
|
||||||
my_face_encoding = face_recognition.face_encodings(picture_of_me)[0]
|
|
||||||
face_datas[username] = my_face_encoding
|
|
||||||
cache.set('face_datas', face_datas, timeout=None)
|
|
||||||
return my_face_encoding
|
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMixin, RetrieveModelMixin, GenericViewSet):
|
class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMixin, RetrieveModelMixin, GenericViewSet):
|
||||||
|
@ -44,16 +33,23 @@ class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMix
|
||||||
serializer_class = EmployeeSerializer
|
serializer_class = EmployeeSerializer
|
||||||
ordering = ['-pk']
|
ordering = ['-pk']
|
||||||
|
|
||||||
def perform_update(self, serializer):
|
def update(self, request, *args, **kwargs):
|
||||||
instance = serializer.save(update_by = self.request.user)
|
partial = kwargs.pop('partial', False)
|
||||||
try:
|
instance = self.get_object()
|
||||||
photo_path = settings.BASE_DIR + instance.photo
|
data = request.data
|
||||||
picture_of_me = face_recognition.load_image_file(photo_path)
|
serializer = self.get_serializer(instance, data=data, partial=partial)
|
||||||
my_face_encoding = face_recognition.face_encodings(picture_of_me)[0]
|
serializer.is_valid(raise_exception=True)
|
||||||
instance.face_data = my_face_encoding.tolist()
|
photo = data.get('photo', None)
|
||||||
instance.save()
|
if instance.photo != photo:
|
||||||
except:
|
f_l = HRMService.get_facedata_from_img(photo)
|
||||||
logger.error('人脸识别出错')
|
if f_l:
|
||||||
|
serializer.save(update_by=request.user, face_data = f_l)
|
||||||
|
# 更新人脸缓存
|
||||||
|
update_all_user_facedata_cache.delay()
|
||||||
|
return Response()
|
||||||
|
return Response('头像识别失败', status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
serializer.save(update_by=request.user)
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
|
class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
|
||||||
|
|
|
@ -15,7 +15,8 @@ class MbFilterSet(filters.FilterSet):
|
||||||
|
|
||||||
def filter_tag(self, queryset, name, value):
|
def filter_tag(self, queryset, name, value):
|
||||||
if value == 'expired':
|
if value == 'expired':
|
||||||
queryset = queryset.exclude(expiration_date=None).filter(expiration_date__lte=timezone.now())
|
queryset = queryset.exclude(expiration_date=None).filter(
|
||||||
|
expiration_date__lte=timezone.now())
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ class MaterialBatchSerializer(serializers.ModelSerializer):
|
||||||
class IProductListSerializer(serializers.ModelSerializer):
|
class IProductListSerializer(serializers.ModelSerializer):
|
||||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||||
is_mtested = serializers.BooleanField(source='wproduct.is_mtested', read_only=True)
|
|
||||||
is_mtestok = serializers.BooleanField(source='wproduct.is_mtestok', read_only=True)
|
is_mtestok = serializers.BooleanField(source='wproduct.is_mtestok', read_only=True)
|
||||||
remark_mtest = serializers.CharField(source='wproduct.remark_mtest', read_only=True)
|
remark_mtest = serializers.CharField(source='wproduct.remark_mtest', read_only=True)
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,36 @@
|
||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
|
|
||||||
from apps.sam.models import Order
|
from apps.sam.models import Order
|
||||||
|
from django.db.models import F
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
|
||||||
class OrderFilterSet(filters.FilterSet):
|
class OrderFilterSet(filters.FilterSet):
|
||||||
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
||||||
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
|
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
|
||||||
material = filters.NumberFilter(method='filter_material')
|
material = filters.NumberFilter(method='filter_material')
|
||||||
|
tag = filters.CharFilter(method='filter_tag')
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Order
|
model = Order
|
||||||
fields = ['product', 'contract', 'customer', 'create_time_start', 'create_time_end']
|
fields = ['product', 'contract', 'customer', 'create_time_start',
|
||||||
|
'create_time_end', 'tag']
|
||||||
|
|
||||||
def filter_material(self, queryset, name, value):
|
def filter_material(self, queryset, name, value):
|
||||||
"""
|
"""
|
||||||
按物料筛选
|
按物料筛选
|
||||||
"""
|
"""
|
||||||
return queryset.filter(plan_order__subplan_plan__progress_subplan__material__id=value).distinct()
|
return queryset.filter(
|
||||||
|
plan_order__subplan_plan__progress_subplan__material__id=value).distinct()
|
||||||
|
|
||||||
|
def filter_tag(self, queryset, name, value):
|
||||||
|
if value == 'near_delivery':
|
||||||
|
day7_after = datetime.now() + timedelta(days=7)
|
||||||
|
queryset = queryset.filter(delivered_count__lt=F('count'),
|
||||||
|
delivery_date__lte = datetime.date(day7_after))
|
||||||
|
elif value == 'out_delivery':
|
||||||
|
queryset = queryset.filter(delivered_count__lt=F('count'),
|
||||||
|
delivery_date__gt = datetime.date(datetime.now()))
|
||||||
|
return queryset
|
||||||
|
|
||||||
class ContractFilterSet(filters.FilterSet):
|
class ContractFilterSet(filters.FilterSet):
|
||||||
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-01-24 05:44
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sam', '0010_auto_20211208_1408'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='order',
|
||||||
|
name='need_mtest',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='是否需要军检'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -66,6 +66,7 @@ class Order(CommonAModel):
|
||||||
planed_count = models.PositiveIntegerField('已排数量', default=0)
|
planed_count = models.PositiveIntegerField('已排数量', default=0)
|
||||||
delivered_count = models.PositiveIntegerField('已交货数量', default=0)
|
delivered_count = models.PositiveIntegerField('已交货数量', default=0)
|
||||||
delivery_date = models.DateField('交货日期')
|
delivery_date = models.DateField('交货日期')
|
||||||
|
need_mtest = models.BooleanField('是否需要军检', default=False)
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '订单信息'
|
verbose_name = '订单信息'
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
|
|
|
@ -63,7 +63,7 @@ class OrderSimpleSerializer(serializers.ModelSerializer):
|
||||||
customer_ = CustomerSimpleSerializer(source='customer', read_only=True)
|
customer_ = CustomerSimpleSerializer(source='customer', read_only=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Order
|
model = Order
|
||||||
fields = '__all__'
|
fields = ['id', 'number', 'contract_', 'customer_', 'need_mtest']
|
||||||
|
|
||||||
class SaleCreateSerializer(serializers.ModelSerializer):
|
class SaleCreateSerializer(serializers.ModelSerializer):
|
||||||
iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), many=True)
|
iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), many=True)
|
||||||
|
|
|
@ -136,13 +136,6 @@ class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, C
|
||||||
fifo.inout_date = timezone.now()
|
fifo.inout_date = timezone.now()
|
||||||
fifo.create_by = request.user
|
fifo.create_by = request.user
|
||||||
fifo.save()
|
fifo.save()
|
||||||
# 出库条目 暂时不校验是否军检
|
|
||||||
# spds = SaleProduct.objects.filter(sale=obj)
|
|
||||||
# for i in spds:
|
|
||||||
# if i.is_mtested and i.is_mtestok:
|
|
||||||
# pass
|
|
||||||
# else:
|
|
||||||
# raise exceptions.APIException('存在未军检产品')
|
|
||||||
# 创建出库条目
|
# 创建出库条目
|
||||||
ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
||||||
items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
from .models import User
|
from .models import User
|
||||||
|
from utils.mixins import DynamicFieldsFilterMixin
|
||||||
|
|
||||||
|
|
||||||
class UserFilter(filters.FilterSet):
|
class UserFilter(DynamicFieldsFilterMixin, filters.FilterSet):
|
||||||
|
name = filters.CharFilter(field_name='name', lookup_expr='contains')
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = {
|
fields = ['name', 'is_active', 'is_atwork']
|
||||||
'name': ['exact', 'contains'],
|
|
||||||
'is_active': ['exact'],
|
|
||||||
}
|
|
|
@ -5,6 +5,7 @@ from rest_framework import serializers
|
||||||
|
|
||||||
from .models import (Dict, DictType, File, Organization, Permission, Position,
|
from .models import (Dict, DictType, File, Organization, Permission, Position,
|
||||||
Role, User)
|
Role, User)
|
||||||
|
from utils.mixins import DynamicFieldsSerializerMixin
|
||||||
|
|
||||||
class IntervalSerializer(serializers.ModelSerializer):
|
class IntervalSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -132,7 +133,7 @@ class UserSimpleSerializer(serializers.ModelSerializer):
|
||||||
# fields = ['id', 'username', 'name', 'is_active', 'dept_name', 'dept']
|
# fields = ['id', 'username', 'name', 'is_active', 'dept_name', 'dept']
|
||||||
|
|
||||||
|
|
||||||
class UserListSerializer(serializers.ModelSerializer):
|
class UserListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer):
|
||||||
"""
|
"""
|
||||||
用户列表序列化
|
用户列表序列化
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -48,12 +48,6 @@ class TaskList(APIView):
|
||||||
tasks = list(sorted(name for name in celery_app.tasks if not name.startswith('celery.')))
|
tasks = list(sorted(name for name in celery_app.tasks if not name.startswith('celery.')))
|
||||||
return Response(tasks)
|
return Response(tasks)
|
||||||
|
|
||||||
class LogoutView(APIView):
|
|
||||||
permission_classes = []
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs): # 可将token加入黑名单
|
|
||||||
return Response(status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
class PTaskViewSet(OptimizationMixin, ModelViewSet):
|
class PTaskViewSet(OptimizationMixin, ModelViewSet):
|
||||||
perms_map = {'get': '*', 'post': 'ptask_create',
|
perms_map = {'get': '*', 'post': 'ptask_create',
|
||||||
'put': 'ptask_update', 'delete': 'ptask_delete'}
|
'put': 'ptask_update', 'delete': 'ptask_delete'}
|
||||||
|
|
|
@ -2,6 +2,7 @@ from django_filters import rest_framework as filters
|
||||||
from apps.mtm.models import Material, Step
|
from apps.mtm.models import Material, Step
|
||||||
|
|
||||||
from apps.wpm.services import WpmServies
|
from apps.wpm.services import WpmServies
|
||||||
|
from utils.mixins import DynamicFieldsFilterMixin
|
||||||
from .models import Operation, OperationMaterial, OperationRecord, WMaterial, WProduct
|
from .models import Operation, OperationMaterial, OperationRecord, WMaterial, WProduct
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,11 +29,15 @@ class WMaterialFilterSet(filters.FilterSet):
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class WProductFilterSet(filters.FilterSet):
|
class WProductFilterSet(DynamicFieldsFilterMixin, filters.FilterSet):
|
||||||
tag = filters.CharFilter(method='filter_tag')
|
tag = filters.CharFilter(method='filter_tag')
|
||||||
production_plan = filters.NumberFilter(
|
production_plan = filters.NumberFilter(
|
||||||
field_name='subproduction_plan__production_plan')
|
field_name='subproduction_plan__production_plan')
|
||||||
|
def filter_fields(self, queryset, name, value):
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def filter_omit(self, queryset, name, value):
|
||||||
|
return queryset
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WProduct
|
model = WProduct
|
||||||
fields = ['step', 'subproduction_plan', 'material',
|
fields = ['step', 'subproduction_plan', 'material',
|
||||||
|
|
|
@ -120,7 +120,6 @@ class WProduct(CommonAModel):
|
||||||
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket')
|
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket')
|
||||||
|
|
||||||
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
|
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
|
||||||
is_mtested = models.BooleanField('是否军检', default=False)
|
|
||||||
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
|
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
|
||||||
remark_mtest = models.TextField('军检备注', null=True, blank=True)
|
remark_mtest = models.TextField('军检备注', null=True, blank=True)
|
||||||
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
|
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
|
||||||
|
@ -194,7 +193,6 @@ class WproductFlow(CommonAModel):
|
||||||
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
|
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
|
||||||
on_delete=models.SET_NULL, null=True, blank=True)
|
on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
|
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
|
||||||
is_mtested = models.BooleanField('是否军检', default=False)
|
|
||||||
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
|
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
|
||||||
remark_mtest = models.TextField('军检备注', null=True, blank=True)
|
remark_mtest = models.TextField('军检备注', null=True, blank=True)
|
||||||
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
|
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
|
||||||
|
|
|
@ -20,6 +20,7 @@ from apps.system.serializers import UserSimpleSerializer
|
||||||
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket
|
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from apps.sam.models import Order
|
from apps.sam.models import Order
|
||||||
|
from utils.mixins import DynamicFieldsSerializerMixin
|
||||||
|
|
||||||
class PickHalfSerializer(serializers.Serializer):
|
class PickHalfSerializer(serializers.Serializer):
|
||||||
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
||||||
|
@ -147,7 +148,7 @@ class WProductBaseSerializer(serializers.ModelSerializer):
|
||||||
model = WProduct
|
model = WProduct
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
class WProductListSerializer(serializers.ModelSerializer):
|
class WProductListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer):
|
||||||
"""
|
"""
|
||||||
半成品列表
|
半成品列表
|
||||||
"""
|
"""
|
||||||
|
@ -157,6 +158,7 @@ class WProductListSerializer(serializers.ModelSerializer):
|
||||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||||
children = serializers.SerializerMethodField()
|
children = serializers.SerializerMethodField()
|
||||||
to_order_ = OrderSimpleSerializer(source='to_order', read_only=True)
|
to_order_ = OrderSimpleSerializer(source='to_order', read_only=True)
|
||||||
|
order_ = serializers.SerializerMethodField()
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WProduct
|
model = WProduct
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -167,6 +169,11 @@ class WProductListSerializer(serializers.ModelSerializer):
|
||||||
return WProductBaseSerializer(instance=wps, many=True).data
|
return WProductBaseSerializer(instance=wps, many=True).data
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def get_order_(self, obj):
|
||||||
|
order = Order.objects.select_related('contract', 'customer').filter(
|
||||||
|
plan_order__subplan_plan__wproduct_subplan=obj).first()
|
||||||
|
return OrderSimpleSerializer(instance=order).data
|
||||||
|
|
||||||
class WProductCardBaseSerializer(serializers.ModelSerializer):
|
class WProductCardBaseSerializer(serializers.ModelSerializer):
|
||||||
"""
|
"""
|
||||||
产品流程序列化
|
产品流程序列化
|
||||||
|
@ -224,6 +231,8 @@ class WProductDetailSerializer(serializers.ModelSerializer):
|
||||||
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
||||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||||
children = serializers.SerializerMethodField()
|
children = serializers.SerializerMethodField()
|
||||||
|
to_order_ = OrderSimpleSerializer(source='to_order', read_only=True)
|
||||||
|
order_ = OrderSimpleSerializer(source='subproduction_plan__production_plan__order', read_only=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WProduct
|
model = WProduct
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -231,7 +240,6 @@ class WProductDetailSerializer(serializers.ModelSerializer):
|
||||||
def get_children(self, obj):
|
def get_children(self, obj):
|
||||||
wps = WProduct.objects.filter(child=obj)
|
wps = WProduct.objects.filter(child=obj)
|
||||||
if wps.exists():
|
if wps.exists():
|
||||||
print(wps)
|
|
||||||
return WProductBaseSerializer(instance=wps, many=True).data
|
return WProductBaseSerializer(instance=wps, many=True).data
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,8 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
||||||
"""
|
"""
|
||||||
perms_map = {'*': '*'}
|
perms_map = {'*': '*'}
|
||||||
queryset = WProduct.objects.select_related('step', 'material',
|
queryset = WProduct.objects.select_related('step', 'material',
|
||||||
'subproduction_plan', 'warehouse', 'to_order').prefetch_related('wproduct_child')
|
'subproduction_plan', 'warehouse', 'subproduction_plan__production_plan__order',
|
||||||
|
'to_order').prefetch_related('wproduct_child')
|
||||||
serializer_class = WProductListSerializer
|
serializer_class = WProductListSerializer
|
||||||
filterset_class = WProductFilterSet
|
filterset_class = WProductFilterSet
|
||||||
search_fields = ['number']
|
search_fields = ['number']
|
||||||
|
@ -398,12 +399,11 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
||||||
军检
|
军检
|
||||||
"""
|
"""
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
if obj.is_mtested:
|
if obj.is_mtestok is None:
|
||||||
raise exceptions.APIException('已进行军检')
|
raise exceptions.APIException('已进行军检')
|
||||||
if obj.material.type != Material.MA_TYPE_GOOD:
|
if obj.material.type != Material.MA_TYPE_GOOD:
|
||||||
raise exceptions.APIException('军检必须是成品')
|
raise exceptions.APIException('军检必须是成品')
|
||||||
obj.remark_mtest = request.data.get('remark_mtest', None)
|
obj.remark_mtest = request.data.get('remark_mtest', None)
|
||||||
obj.is_mtested = True
|
|
||||||
is_mtestok = request.data.get('is_mtestok')
|
is_mtestok = request.data.get('is_mtestok')
|
||||||
obj.is_mtestok = is_mtestok
|
obj.is_mtestok = is_mtestok
|
||||||
if is_mtestok:
|
if is_mtestok:
|
||||||
|
|
|
@ -48,6 +48,7 @@ INSTALLED_APPS = [
|
||||||
'simple_history',
|
'simple_history',
|
||||||
'apps.system',
|
'apps.system',
|
||||||
'apps.monitor',
|
'apps.monitor',
|
||||||
|
'apps.auth1',
|
||||||
'apps.pum',
|
'apps.pum',
|
||||||
'apps.em',
|
'apps.em',
|
||||||
'apps.hrm',
|
'apps.hrm',
|
||||||
|
@ -194,7 +195,7 @@ AUTHENTICATION_BACKENDS = (
|
||||||
# CACHES = {
|
# CACHES = {
|
||||||
# "default": {
|
# "default": {
|
||||||
# "BACKEND": "django_redis.cache.RedisCache",
|
# "BACKEND": "django_redis.cache.RedisCache",
|
||||||
# "LOCATION": "redis://redis:6379/1",
|
# "LOCATION": "redis://127.0.0.1:6379/0",
|
||||||
# "OPTIONS": {
|
# "OPTIONS": {
|
||||||
# "CLIENT_CLASS": "django_redis.client.DefaultClient",
|
# "CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||||
# "PICKLE_VERSION": -1
|
# "PICKLE_VERSION": -1
|
||||||
|
@ -203,7 +204,7 @@ AUTHENTICATION_BACKENDS = (
|
||||||
# }
|
# }
|
||||||
|
|
||||||
# celery配置,celery正常运行必须安装redis
|
# celery配置,celery正常运行必须安装redis
|
||||||
CELERY_BROKER_URL = "redis://redis:6379/0" # 任务存储
|
CELERY_BROKER_URL = "redis://127.0.0.1:6379/1" # 任务存储
|
||||||
CELERYD_MAX_TASKS_PER_CHILD = 100 # 每个worker最多执行300个任务就会被销毁,可防止内存泄露
|
CELERYD_MAX_TASKS_PER_CHILD = 100 # 每个worker最多执行300个任务就会被销毁,可防止内存泄露
|
||||||
CELERY_TIMEZONE = 'Asia/Shanghai' # 设置时区
|
CELERY_TIMEZONE = 'Asia/Shanghai' # 设置时区
|
||||||
CELERY_ENABLE_UTC = True # 启动时区设置
|
CELERY_ENABLE_UTC = True # 启动时区设置
|
||||||
|
|
|
@ -13,7 +13,7 @@ Including another URLconf
|
||||||
1. Import the include() function: from django.urls import include, path
|
1. Import the include() function: from django.urls import include, path
|
||||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
from apps.system.views import FileViewSet, LogoutView
|
from apps.system.views import FileViewSet
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
@ -23,8 +23,6 @@ from drf_yasg import openapi
|
||||||
from drf_yasg.views import get_schema_view
|
from drf_yasg.views import get_schema_view
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
from rest_framework.documentation import include_docs_urls
|
from rest_framework.documentation import include_docs_urls
|
||||||
from rest_framework_simplejwt.views import (TokenObtainPairView,
|
|
||||||
TokenRefreshView)
|
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from utils.view import GenSignature, UpdateDevelop
|
from utils.view import GenSignature, UpdateDevelop
|
||||||
|
|
||||||
|
@ -53,12 +51,10 @@ urlpatterns = [
|
||||||
path('api/redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
|
path('api/redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
|
||||||
|
|
||||||
# api
|
# api
|
||||||
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
|
|
||||||
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
|
||||||
path('api/token/black/', LogoutView.as_view(), name='token_black'),
|
|
||||||
path('api/file/', include(router.urls)),
|
path('api/file/', include(router.urls)),
|
||||||
path('api/system/', include('apps.system.urls')),
|
path('api/system/', include('apps.system.urls')),
|
||||||
path('api/monitor/', include('apps.monitor.urls')),
|
path('api/monitor/', include('apps.monitor.urls')),
|
||||||
|
path('api/auth/', include('apps.auth1.urls')),
|
||||||
path('api/pum/', include('apps.pum.urls')),
|
path('api/pum/', include('apps.pum.urls')),
|
||||||
path('api/em/', include('apps.em.urls')),
|
path('api/em/', include('apps.em.urls')),
|
||||||
path('api/hrm/', include('apps.hrm.urls')),
|
path('api/hrm/', include('apps.hrm.urls')),
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
"""
|
||||||
|
Mixin to dynamically select only a subset of fields per DRF resource.
|
||||||
|
"""
|
||||||
|
# import warnings
|
||||||
|
from django_filters import rest_framework as filters
|
||||||
|
|
||||||
|
# from django.conf import settings
|
||||||
|
class DynamicFieldsFilterMixin(object):
|
||||||
|
fields = filters.CharFilter(method='filter_fields')
|
||||||
|
omit = filters.CharFilter(method='filter_omit')
|
||||||
|
def filter_fields(self, queryset, name, value):
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def filter_omit(self, queryset, name, value):
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fields(self):
|
||||||
|
fields = super(DynamicFieldsFilterMixin, self).fields
|
||||||
|
fields.extend(['fields', 'omit'])
|
||||||
|
return fields
|
||||||
|
|
||||||
|
class DynamicFieldsSerializerMixin(object):
|
||||||
|
"""
|
||||||
|
A serializer mixin that takes an additional `fields` argument that controls
|
||||||
|
which fields should be displayed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fields(self):
|
||||||
|
"""
|
||||||
|
Filters the fields according to the `fields` query parameter.
|
||||||
|
A blank `fields` parameter (?fields) will remove all fields. Not
|
||||||
|
passing `fields` will pass all fields individual fields are comma
|
||||||
|
separated (?fields=id,name,url,email).
|
||||||
|
"""
|
||||||
|
fields = super(DynamicFieldsSerializerMixin, self).fields
|
||||||
|
|
||||||
|
if not hasattr(self, '_context'):
|
||||||
|
# We are being called before a request cycle
|
||||||
|
return fields
|
||||||
|
|
||||||
|
# Only filter if this is the root serializer, or if the parent is the
|
||||||
|
# root serializer with many=True
|
||||||
|
is_root = self.root == self
|
||||||
|
parent_is_list_root = self.parent == self.root and getattr(self.parent, 'many', False)
|
||||||
|
if not (is_root or parent_is_list_root):
|
||||||
|
return fields
|
||||||
|
|
||||||
|
try:
|
||||||
|
request = self.context['request']
|
||||||
|
except KeyError:
|
||||||
|
# conf = getattr(settings, 'DRF_DYNAMIC_FIELDS', {})
|
||||||
|
# if not conf.get('SUPPRESS_CONTEXT_WARNING', False) is True:
|
||||||
|
# warnings.warn('Context does not have access to request. '
|
||||||
|
# 'See README for more information.')
|
||||||
|
return fields
|
||||||
|
|
||||||
|
# NOTE: drf test framework builds a request object where the query
|
||||||
|
# parameters are found under the GET attribute.
|
||||||
|
params = getattr(
|
||||||
|
request, 'query_params', getattr(request, 'GET', None)
|
||||||
|
)
|
||||||
|
# if params is None:
|
||||||
|
# warnings.warn('Request object does not contain query paramters')
|
||||||
|
|
||||||
|
try:
|
||||||
|
filter_fields = params.get('fields', None).split(',')
|
||||||
|
except AttributeError:
|
||||||
|
filter_fields = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
omit_fields = params.get('omit', None).split(',')
|
||||||
|
except AttributeError:
|
||||||
|
omit_fields = []
|
||||||
|
|
||||||
|
# Drop any fields that are not specified in the `fields` argument.
|
||||||
|
existing = set(fields.keys())
|
||||||
|
if filter_fields is None:
|
||||||
|
# no fields param given, don't filter.
|
||||||
|
allowed = existing
|
||||||
|
else:
|
||||||
|
allowed = set(filter(None, filter_fields))
|
||||||
|
|
||||||
|
# omit fields in the `omit` argument.
|
||||||
|
omitted = set(filter(None, omit_fields))
|
||||||
|
|
||||||
|
for field in existing:
|
||||||
|
|
||||||
|
if field not in allowed:
|
||||||
|
fields.pop(field, None)
|
||||||
|
|
||||||
|
if field in omitted:
|
||||||
|
fields.pop(field, None)
|
||||||
|
|
||||||
|
return fields
|
Loading…
Reference in New Issue