Compare commits

...

7 Commits

Author SHA1 Message Date
lb
c600d14f8f update 设备产量时序图 2023-09-20 17:03:39 +08:00
lb
8ad84a4d61 update 设备产量时序图 2023-09-20 14:44:39 +08:00
lb
928258e509 update 设备状态时序图 2023-09-20 14:11:36 +08:00
lb
a12530b835 update 质量检测统计数据 2023-09-20 11:17:34 +08:00
lb
b3db8dcae8 update 检测统计数据chart 2023-09-20 10:49:17 +08:00
lb
24a0857808 update 质量检测统计数据 2023-09-20 09:50:38 +08:00
lb
e0cc022e34 update 产品质量分析样式 2023-09-20 09:11:31 +08:00
12 changed files with 731 additions and 260 deletions

View File

@ -98,7 +98,7 @@ export default {
return h( return h(
'el-button', 'el-button',
{ {
props: { type: 'text', size: 'mini' }, props: { type: 'text' },
on: { on: {
click: function () { click: function () {
console.log('inejctdata', _this.injectData); console.log('inejctdata', _this.injectData);

View File

@ -98,7 +98,7 @@ export default {
return h( return h(
'el-button', 'el-button',
{ {
props: { type: 'text', size: 'mini' }, props: { type: 'text' },
on: { on: {
click: function () { click: function () {
console.log('inejctdata', _this.injectData); console.log('inejctdata', _this.injectData);

View File

@ -41,7 +41,7 @@ export default {
opt.push([eq.equipmentName, eq.okQuantity, eq.nokQuantity]); opt.push([eq.equipmentName, eq.okQuantity, eq.nokQuantity]);
}); });
return { return {
color: ['#8EF0AB', '#288AFF'], color: ['#288AFF', '#8EF0AB'],
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { axisPointer: {
@ -51,7 +51,7 @@ export default {
legend: { legend: {
itemWidth: 12, itemWidth: 12,
itemHeight: 12, itemHeight: 12,
right: 0, right: 0
}, },
grid: { grid: {
left: '1%', left: '1%',
@ -90,13 +90,6 @@ export default {
}, },
}, },
series: [ series: [
{
name: '不合格数量',
type: 'bar',
barWidth: 20,
stack: 's',
data: opt.map((item) => item[2]),
},
{ {
name: '合格数量', name: '合格数量',
type: 'bar', type: 'bar',
@ -104,6 +97,13 @@ export default {
stack: 's', stack: 's',
data: opt.map((item) => item[1]), data: opt.map((item) => item[1]),
}, },
{
name: '不合格数量',
type: 'bar',
barWidth: 20,
stack: 's',
data: opt.map((item) => item[2]),
},
], ],
}; };
}, },

View File

@ -19,7 +19,7 @@
v-model="activeName" v-model="activeName"
:stretch="true" :stretch="true"
@tab-click="handleTabClick"> @tab-click="handleTabClick">
<el-tab-pane label="数据列表" name="table"> <el-tab-pane :label="'数据列表'" name="table">
<!-- 列表 --> <!-- 列表 -->
<base-table <base-table
:table-props="tableProps" :table-props="tableProps"
@ -28,7 +28,7 @@
:table-data="list" :table-data="list"
@emitFun="handleEmitFun"></base-table> @emitFun="handleEmitFun"></base-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="柱状图" name="graph"> <el-tab-pane :label="'\u3000柱状图\u3000'" name="graph">
<div v-if="activeName == 'graph'" class="graph" style="height: 40vh; display: flex; flex-direction: column;"> <div v-if="activeName == 'graph'" class="graph" style="height: 40vh; display: flex; flex-direction: column;">
<div class="blue-title">各设备加工数量</div> <div class="blue-title">各设备加工数量</div>
<LineChart :list="list" /> <LineChart :list="list" />
@ -373,8 +373,8 @@ export default {
} }
.el-tabs__item { .el-tabs__item {
padding-left: 8px !important; padding-left: 0 !important;
padding-right: 8px !important; padding-right: 0 !important;
line-height: 36px !important; line-height: 36px !important;
height: 36px; height: 36px;
} }

View File

@ -21,7 +21,14 @@ export default {
chart: null, chart: null,
}; };
}, },
computed: {}, watch: {
config: {
handler(value) {
if (value != null) this.setOption(value);
},
deep: true,
},
},
mounted() { mounted() {
this.init(); this.init();
}, },
@ -32,9 +39,11 @@ export default {
}, },
methods: { methods: {
init() { init() {
console.log('thsi el', this.$el);
if (!this.chart) this.chart = echarts.init(this.$el); if (!this.chart) this.chart = echarts.init(this.$el);
this.chart.setOption(this.config); this.setOption(this.config);
},
setOption(option) {
if (this.chart) this.chart.setOption(option);
}, },
}, },
}; };

View File

@ -6,25 +6,44 @@
--> -->
<template> <template>
<div class="app-container"> <div
<h1>设备产量时序图</h1> class="production-timegraph-container"
<!-- 搜索工作栏 --> style="background: #f2f4f9; flex: 1">
<SearchBar <el-row
:formConfigs="searchBarFormConfig" class=""
ref="search-bar" style="
@headBtnClick="handleSearchBarBtnClick" /> margin-bottom: 12px;
background: #fff;
padding: 16px 16px 0;
border-radius: 8px;
">
<div class="blue-title">生产节拍时序图</div>
<!-- <h1>设备状态时序图</h1> -->
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="searchBarFormConfig"
ref="search-bar"
:remove-blue="true"
@headBtnClick="handleSearchBarBtnClick" />
</el-row>
<div class="main-area"> <el-row
<div class="graphs" v-if="graphList.length"> class=""
<div class="graph" v-for="(eq, index) in graphList" :key="eq.key"> style="
<h2 class="graph-title">{{ eq.key }}</h2> margin-bottom: 12px;
<LineChart background: #fff;
:key="eq.key + '__linechart'" padding: 16px 16px 24px;
:config="getRealConfig(index)" /> border-radius: 8px;
">
<div class="blue-title">设备产量时序图</div>
<div class="main-area">
<div class="graphs" v-if="graphList.length">
<LineChart :config="templateConfig" />
</div> </div>
<div class="no-data-bg" v-else></div>
</div> </div>
<h2 v-else>请添加设备</h2> </el-row>
</div>
<!-- 对话框(添加 / 修改) --> <!-- 对话框(添加 / 修改) -->
<base-dialog <base-dialog
@ -58,6 +77,7 @@ export default {
props: {}, props: {},
data() { data() {
return { return {
accumulators: new Map(),
searchBarFormConfig: [ searchBarFormConfig: [
{ {
type: 'select', type: 'select',
@ -77,15 +97,16 @@ export default {
{ {
type: 'datePicker', type: 'datePicker',
label: '时间段', label: '时间段',
dateType: 'daterange', // datetimerange dateType: 'date', // datetimerange
// format: 'yyyy-MM-dd HH:mm:ss', // format: 'yyyy-MM-dd HH:mm:ss',
format: 'yyyy-MM-dd', format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss', valueFormat: 'yyyy-MM-dd HH:mm:ss',
// valueFormat: 'timestamp', // valueFormat: 'timestamp',
rangeSeparator: '-', // rangeSeparator: '-',
startPlaceholder: '开始日期', // startPlaceholder: '',
endPlaceholder: '结束日期', // endPlaceholder: '',
defaultTime: ['00:00:00', '23:59:59'], // defaultTime: ['00:00:00', '23:59:59'],
placeholder: '选择日期',
param: 'recordTime', param: 'recordTime',
}, },
{ {
@ -99,9 +120,9 @@ export default {
}, },
{ {
type: 'button', type: 'button',
btnName: '设备对比', btnName: '添加对比',
name: 'compare', name: 'compare',
color: 'warning', color: 'primary',
plain: true, plain: true,
}, },
], ],
@ -115,30 +136,47 @@ export default {
eqList: [], eqList: [],
graphList: [], graphList: [],
templateConfig: { templateConfig: {
color: ['#283D68', '#FFB61F', '#4481FF', '#5AD8A6', '#E97466'],
grid: { grid: {
top: 88, top: 48,
left: 56, left: 48,
right: 56, right: 24,
bottom: 56, bottom: 24,
}, },
legend: { legend: {
top: 0, top: 0,
left: 0, right: 12,
padding: 5, padding: 6,
icon: 'roundRect', itemWidth: 16,
itemWidth: 12, itemHeight: 8,
itemHeight: 12,
itemGap: 20, itemGap: 20,
textStyle: { textStyle: {
fontSize: 14, fontSize: 12,
lineHeight: 14, lineHeight: 12,
color: '#0007',
}, },
}, },
tooltip: {
show: true,
trigger: 'axis',
},
xAxis: { xAxis: {
type: 'category', type: 'category',
data: Array(24) boundaryGap: true,
.fill(1) axisTick: {
.map((item, index) => `${index}:00`), // show: false,
alignWithLabel: true,
lineStyle: {
color: '#0003',
},
},
axisLabel: {
color: '#0007',
},
data: [],
// data: Array(24)
// .fill(1)
// .map((item, index) => `${index}:00`),
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
@ -146,19 +184,41 @@ export default {
nameLocation: 'end', nameLocation: 'end',
nameTextStyle: { nameTextStyle: {
fontSize: 14, fontSize: 14,
align: 'right', align: 'center',
}, },
nameGap: 26, nameGap: 26,
max: function (value) {
return value.max + Math.floor(value.max / 5);
},
}, },
series: [ series: [
{ // {
name: '产线1', // name: '线1',
data: Array(24) // data: Array(24)
.fill(1) // .fill(1)
.map(() => Math.random() * 100), // .map(() => Math.random() * 100),
type: 'line', // type: 'line',
smooth: true, // symbol: 'circle',
}, // // smooth: true,
// },
// {
// name: '线2',
// data: Array(24)
// .fill(1)
// .map(() => Math.random() * 100),
// type: 'line',
// symbol: 'circle',
// // smooth: true,
// },
// {
// name: '线3',
// data: Array(24)
// .fill(1)
// .map(() => Math.random() * 100),
// type: 'line',
// symbol: 'circle',
// // smooth: true,
// },
], ],
}, },
}; };
@ -176,7 +236,12 @@ export default {
this.queryParams.lineId = payload.lineId || null; this.queryParams.lineId = payload.lineId || null;
this.queryParams.sectionId = payload.sectionId || null; this.queryParams.sectionId = payload.sectionId || null;
this.queryParams.equipmentId = payload.equipmentId || null; this.queryParams.equipmentId = payload.equipmentId || null;
this.queryParams.recordTime = payload.recordTime || null; this.queryParams.recordTime = payload.recordTime
? [
payload.recordTime,
payload.recordTime.replace('00:00:00', '23:59:59'),
]
: null;
this.getList(); this.getList();
break; break;
case 'compare': case 'compare':
@ -230,10 +295,41 @@ export default {
// ]; // ];
// eq2.key = 'SS2'; // eq2.key = 'SS2';
// this.graphList = [eq1, eq2]; // this.graphList = [eq1, eq2];
console.log('graph list', this.graphList);
this.graphList.forEach(this.setSeries);
} else {
this.graphList = [];
this.graphList.forEach(this.setSeries);
} }
}, },
setSeries(eqArr) {
if (eqArr.length == 0) {
this.templateConfig.series = [];
return;
}
let isInit = false;
if (this.accumulators.has(eqArr.key) == false) {
this.accumulators.set(eqArr.key, 0);
isInit = true;
}
let accumulator = this.accumulators.get(eqArr.key);
if ((accumulator && !isInit) || (accumulator == 0 && isInit == false)) {
accumulator++;
this.accumulators.set(eqArr.key, accumulator);
}
this.templateConfig.series.push({
name: eqArr.key + (accumulator == 0 ? '' : '-' + accumulator),
// name: Math.random(),
type: 'line',
symbol: 'circle',
data: this.getEquipmentQuantity(eqArr),
});
},
/** 获得设备产量 */ /** 获得设备产量 */
getEquipmentQuantity(equipmentArr) { getEquipmentQuantity(equipmentArr) {
return equipmentArr.map((item) => item.totalQuantity); return equipmentArr.map((item) => item.totalQuantity);
@ -246,19 +342,6 @@ export default {
); );
}, },
getRealConfig(index) {
// if (!this.graphList || this.graphList.length == 0) return;
const config = JSON.parse(JSON.stringify(this.templateConfig));
// config.legend.data = this.graphList[index].key;
config.series[0].name = this.graphList[index]?.key;
// console.log("this.graphList?.[index]", this.graphList?.[index]);
config.series[0].data = this.getEquipmentQuantity(
this.graphList?.[index] || []
);
config.xAxis.data = this.getTimeinfo(this.graphList?.[index] || []);
return config;
},
/** 准备设备数据 */ /** 准备设备数据 */
async initEquipment() { async initEquipment() {
const { code, data } = await this.$axios({ const { code, data } = await this.$axios({
@ -313,18 +396,42 @@ export default {
method: 'get', method: 'get',
params: this.queryParams, params: this.queryParams,
}); });
this.queryParams.equipmentId = null; //
if (code == 0) { if (code == 0) {
const newEqlist = this.objectToArray(data); const newEqlist = this.objectToArray(data);
if (!newEqlist || newEqlist.length == 0) { if (!newEqlist || newEqlist.length == 0) {
this.$message.error('该设备没有产量数据'); this.$message.error('该设备没有产量数据');
return; return;
} }
this.graphList.push(newEqlist[0]); this.graphList.push(...newEqlist);
newEqlist.forEach(this.setSeries);
} }
this.open = false; this.open = false;
} },
}, },
}; };
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss">
.blue-title {
position: relative;
padding: 4px 0;
padding-left: 12px;
font-size: 14px;
color: #606266;
font-weight: 700;
margin-bottom: 12px;
&::before {
content: '';
position: absolute;
left: 0;
top: 6px;
height: 16px;
width: 4px;
border-radius: 1px;
background: #0b58ff;
}
}
</style>

View File

@ -6,29 +6,51 @@
--> -->
<template> <template>
<div class="app-container"> <div class="status-timegraph-container" style="background: #f2f4f9; flex: 1">
<h1>设备状态时序图</h1> <el-row
<!-- 搜索工作栏 --> class=""
<SearchBar style="
:formConfigs="searchBarFormConfig" margin-bottom: 12px;
ref="search-bar" background: #fff;
@headBtnClick="handleSearchBarBtnClick" /> padding: 16px 16px 0;
border-radius: 8px;
">
<div class="blue-title">生产节拍时序图</div>
<!-- <h1>设备状态时序图</h1> -->
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="searchBarFormConfig"
ref="search-bar"
:remove-blue="true"
@headBtnClick="handleSearchBarBtnClick" />
</el-row>
<div class="main-area"> <el-row
<div class="legend-row"> class=""
<div class="legend"> style="
<div class="icon running"></div> margin-bottom: 12px;
<div>运行中</div> background: #fff;
</div> padding: 16px 16px 32px;
<!-- <div class="legend"> border-radius: 8px;
">
<el-row :gutter="20">
<el-col :span="6">
<div class="blue-title">设备状态时序图</div>
</el-col>
<el-col :span="18" class="legend-row">
<div class="legend">
<div class="icon running"></div>
<div>运行中</div>
</div>
<!-- <div class="legend">
<div class="icon waiting"></div> <div class="icon waiting"></div>
<div>待机</div> <div>待机</div>
</div> --> </div> -->
<div class="legend"> <div class="legend">
<div class="icon fault"></div> <div class="icon fault"></div>
<div>故障</div> <div>故障</div>
</div> </div>
<!-- <div class="legend"> <!-- <div class="legend">
<div class="icon lack"></div> <div class="icon lack"></div>
<div>缺料</div> <div>缺料</div>
</div> </div>
@ -36,83 +58,51 @@
<div class="icon full"></div> <div class="icon full"></div>
<div>满料</div> <div>满料</div>
</div> --> </div> -->
<div class="legend"> <div class="legend">
<div class="icon stop"></div> <div class="icon stop"></div>
<div>计划停机</div> <div>计划停机</div>
</div>
</el-col>
</el-row>
<div class="main-area">
<div class="graphs" v-if="graphList.length">
<div class="graph" v-for="eq in graphList" :key="eq.key">
<h2 class="graph-title">{{ eq.key }}</h2>
<div class="graph-content">
<el-popover
trigger="hover"
v-for="blc in eq"
:key="blc.startTime"
:title="
blc.status == 0
? '运行'
: blc.status == 2
? '故障'
: '计划停机'
"
placement="top"
:content="new Date(blc.startTime).toLocaleTimeString()">
<div
slot="reference"
:key="blc.startTime + '__div'"
class="graph-item-fixed tick"
:class="{
running: blc.status == 0,
fault: blc.status == 2,
stop: blc.status == 1,
}"
:style="{ height: '32px', width: blc.duration * 2 + 'px' }"
:data-time="
new Date(blc.startTime).toLocaleTimeString()
"></div>
</el-popover>
</div>
</div>
</div> </div>
<h2 v-else>请添加设备</h2>
</div> </div>
<div class="graphs" v-if="graphList.length"> </el-row>
<!-- <div class="graph">
<h2 class="graph-title">设备1</h2>
<div class="graph-item running tick" data-time="00:00"></div>
<div class="graph-item running"></div>
<div class="graph-item running"></div>
<div class="graph-item lack tick" data-time="03:00"></div>
<div class="graph-item full tick" data-time="04:00"></div>
<div class="graph-item waiting tick" data-time="05:00"></div>
<div class="graph-item running tick" data-time="06:00"></div>
<div class="graph-item running"></div>
<div class="graph-item fault tick" data-time="08:00"></div>
<div class="graph-item waiting tick" data-time="09:00"></div>
<div class="graph-item running tick" data-time="10:00"></div>
<div class="graph-item running"></div>
<div class="graph-item running"></div>
<div class="graph-item lack tick" data-time="13:00"></div>
<div class="graph-item full tick" data-time="14:00"></div>
<div class="graph-item running tick" data-time="15:00"></div>
<div class="graph-item running"></div>
<div class="graph-item running"></div>
<div class="graph-item fault tick" data-time="18:00"></div>
<div class="graph-item running tick" data-time="19:00"></div>
<div class="graph-item running"></div>
<div class="graph-item running"></div>
<div class="graph-item running"></div>
<div class="graph-item stop tick" data-time="23:00"></div>
</div> -->
<div class="graph" v-for="eq in graphList" :key="eq.key">
<h2 class="graph-title">{{ eq.key }}</h2>
<div
v-for="blc in eq"
:key="blc.startTime"
class="graph-item-fixed tick"
:class="{
running: blc.status == 0,
fault: blc.status == 2,
stop: blc.status == 1,
}"
:style="{ width: blc.duration * 2 + 'px' }"
:data-time="new Date(blc.startTime).toLocaleTimeString()"></div>
</div>
<!-- <div class="graph">
<h2 class="graph-title">设备3</h2>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
<div class="graph-item"></div>
</div> -->
</div>
<h2 v-else>请添加设备</h2>
</div>
<!-- 对话框(添加 / 修改) --> <!-- 对话框(添加 / 修改) -->
<base-dialog <base-dialog
@ -185,9 +175,9 @@ export default {
}, },
{ {
type: 'button', type: 'button',
btnName: '设备对比', btnName: '添加对比',
name: 'compare', name: 'compare',
color: 'warning', color: 'primary',
plain: true, plain: true,
}, },
], ],
@ -344,26 +334,52 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
.graph { .graph {
border: 1px solid #ccc; // border: 1px solid #ccc;
padding: 12px 12px 28px 12px; // padding: 12px 12px 28px 12px;
margin: 64px 0; // margin: 64px 0;
position: relative; position: relative;
display: flex; display: flex;
} }
.graph-title { .graph-title {
position: absolute; // position: absolute;
top: -64px; // top: -64px;
left: -1px; // left: -1px;
padding: 8px 18px; // padding: 8px 18px;
background: #ccc; padding: 0 12px;
font-size: 18px; font-size: 14px;
line-height: 1; line-height: 1;
} }
.graph-content {
display: flex;
flex: 1;
padding: 22px 12px;
border: 1px solid #ccc;
border-bottom-width: 2px;
border-top: none;
position: relative;
}
.graph-content::after,
.graph-content::before {
content: '';
position: absolute;
width: 3px;
height: 80%;
background: #fff;
right: -1px;
top: 0;
}
.graph-content::before {
right: unset;
left: -1px;
}
.graph-item, .graph-item,
.graph-item-fixed { .graph-item-fixed {
height: 88px; // height: 88px;
// width: 24px; // width: 24px;
flex: 1; flex: 1;
// border: 1px solid #ccc; // border: 1px solid #ccc;
@ -405,32 +421,40 @@ export default {
} }
.running { .running {
background-color: #84f04e; background-color: #5ad8a6;
// background-color: #84f04e;
} }
.waiting { .waiting {
background-color: #409eff; background-color: #5ad8a6;
// background-color: #409eff;
} }
.fault { .fault {
background-color: #ea5b5b; // background-color: #ea5b5b;
background-color: #fc9c91;
} }
.full { .full {
background-color: #e6a23c; // background-color: #e6a23c;
background-color: #598fff;
} }
.lack { .lack {
background-color: #a69c8d; // background-color: #a69c8d;
background-color: #7585a2;
} }
.stop { .stop {
background-color: #000c; background-color: #000;
} }
.legend-row { .legend-row {
margin: 12px 0; margin: 6px 0;
padding-right: 12px;
display: flex; display: flex;
justify-content: flex-end;
> .legend:not(:last-child) { > .legend:not(:last-child) {
margin-right: 12px; margin-right: 12px;
} }
@ -441,9 +465,32 @@ export default {
} }
.icon { .icon {
width: 16px; width: 8px;
height: 8px;
border-radius: 2px;
margin-right: 4px;
margin-top: 1px;
}
}
.blue-title {
position: relative;
padding: 4px 0;
padding-left: 12px;
font-size: 14px;
color: #606266;
font-weight: 700;
margin-bottom: 12px;
&::before {
content: '';
position: absolute;
left: 0;
top: 6px;
height: 16px; height: 16px;
margin-right: 8px; width: 4px;
border-radius: 1px;
background: #0b58ff;
} }
} }
</style> </style>

View File

@ -124,7 +124,7 @@ export default {
return h( return h(
'el-button', 'el-button',
{ {
props: { type: 'text', size: 'mini' }, props: { type: 'text' },
on: { on: {
click: function () { click: function () {
console.log('inejctdata', _this.injectData); console.log('inejctdata', _this.injectData);

View File

@ -82,18 +82,22 @@ export default {
computed: { computed: {
config() { config() {
return { return {
color: ['#fde19a', '#8be2b9', '#288aff', '#7164ff'],
// title: { // title: {
// text: '线', // text: '线',
// }, // },
grid: { grid: {
top: '24%', top: '12%',
left: '3%', left: '2%',
right: '5%', right: '5%',
bottom: '5%', bottom: '5%',
containLabel: true, containLabel: true,
}, },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: {
type: 'shadow',
},
}, },
legend: { legend: {
data: this.legend, data: this.legend,
@ -107,13 +111,145 @@ export default {
// }, // },
xAxis: { xAxis: {
type: 'category', type: 'category',
boundaryGap: false, boundaryGap: true,
onZero: false,
axisTick: {
show: false,
},
axisLine: {
lineStyle: {
// color: 'red'
},
},
data: this.xProps, data: this.xProps,
// data: [
// '1',
// '2',
// '3',
// '4',
// '5',
// '6',
// '7',
// '8',
// '9',
// '10',
// '11',
// '12',
// '13',
// '14',
// '15',
// '16',
// '17',
// '18',
// '19',
// '20',
// ],
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
name: '单位/片',
nameTextStyle: {
color: '#999',
fontSize: 14,
align: 'right',
},
max: function (value) {
return value.max + Math.floor(value.max / 5);
},
},
// -
dataZoom: {
type: 'inside',
}, },
series: this.series, series: this.series,
// series: [
// {
// name: '',
// type: 'bar',
// // barWidth: 12,
// data: [
// 10,
// 12,
// 43,
// 4,
// 22,
// 32,
// 12,
// 8,
// 122,
// 0,
// ,
// 43,
// 4,
// 22,
// 32,
// 12,
// 8,
// 122,
// 77,
// 99,
// ],
// },
// {
// name: '',
// type: 'bar',
// // barWidth: 12,
// data: [
// 10,
// 12,
// 43,
// 4,
// 22,
// 32,
// 12,
// 8,
// 122,
// 0,
// 4,
// 22,
// 32,
// 12,
// 8,
// 122,
// 0,
// ,
// 43,
// 4,
// 22,
// 32,
// ],
// },
// {
// name: '',
// type: 'bar',
// // barWidth: 12,
// barCategoryGap: 12,
// data: [
// 10,
// 12,
// 43,
// 4,
// 22,
// 4,
// 22,
// 32,
// 12,
// 8,
// 122,
// 0,
// ,
// 43,
// 4,
// 22,
// 32,
// 32,
// 12,
// 8,
// 122,
// 0,
// ],
// },
// ],
}; };
}, },
}, },

View File

@ -7,9 +7,9 @@
<template> <template>
<!-- 列表 --> <!-- 列表 -->
<!-- height="35vh" -->
<base-table <base-table
:table-props="tableProps" :table-props="tableProps"
height="35vh"
:page="queryParams.pageNo" :page="queryParams.pageNo"
:limit="queryParams.pageSize" :limit="queryParams.pageSize"
:table-data="list"></base-table> :table-data="list"></base-table>

View File

@ -7,14 +7,20 @@
<template> <template>
<div class="graph-page"> <div class="graph-page">
<DetailGraph id="dg1" key="dg1" ref="dg1" title="数据总览"> <!-- <DetailGraph id="dg1" key="dg1" ref="dg1" title="数据总览">
<TotalGraph :summary-list="summaryList" /> <TotalGraph :summary-list="summaryList" />
</DetailGraph> </DetailGraph> -->
<DetailGraph id="dg2" key="dg2" ref="dg2" title="检测内容数据"> <!-- <DetailGraph id="dg2" key="dg2" ref="dg2" title="检测内容数据">
<LineGraph :x-props="lineData.xProps" :legend="legend" :series="series" /> <LineGraph :x-props="lineData.xProps" :legend="legend" :series="series" />
</DetailGraph> </DetailGraph> -->
<!-- <DetailGraph id="dg3" key="dg3" ref="dg3" /> <!-- <DetailGraph id="dg3" key="dg3" ref="dg3" />
<DetailGraph id="dg4" key="dg4" ref="dg4" /> --> <DetailGraph id="dg4" key="dg4" ref="dg4" /> -->
<div v-if="!series || series.length == 0" style="color: #777; font-size: 16px; letter-spacing: 1px; text-align: center; padding-top: 56px; text-decoration: underline;">暂无数据</div>
<LineGraph
v-else
:x-props="lineData.xProps"
:legend="legend"
:series="series" />
</div> </div>
</template> </template>
@ -55,7 +61,8 @@ export default {
console.log('this.list', this.lineData.list, this.lineData.xProps); console.log('this.list', this.lineData.list, this.lineData.xProps);
const seriesItem = { const seriesItem = {
name: item.inspectionContent, name: item.inspectionContent,
type: 'line', type: 'bar',
barCategoryGap: 12,
data: [], data: [],
}; };

View File

@ -6,33 +6,84 @@
--> -->
<template> <template>
<div class="app-container"> <div class="quality-container" style="background: #f2f4f9; flex: 1">
<!-- 搜索工作栏 --> <el-row
<SearchBar class=""
:formConfigs="searchBarFormConfig" style="
ref="search-bar" margin-bottom: 12px;
@headBtnClick="handleSearchBarBtnClick" /> background: #fff;
padding: 16px 16px 0;
border-radius: 8px;
">
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="searchBarFormConfig"
ref="search-bar"
@headBtnClick="handleSearchBarBtnClick" />
</el-row>
<transition mode="out-in" name="fade-down"> <el-row
<template v-if="mode == 'table'"> class=""
<!-- 列表 --> style="
<base-table margin-top: 0;
v-if="mode == 'table'" margin-bottom: 12px;
:table-props="tableProps" background: #fff;
:page="queryParams.pageNo" padding: 12px 16px 16px;
:limit="queryParams.pageSize" border-radius: 8px;
:table-data="list" ">
@emitFun="handleEmitFun"></base-table> <div class="blue-title">产线检测总览</div>
</template> <summaryTable :list="summaryList" />
</el-row>
<GraphPage <el-row
v-else class=""
:summary-list="summaryList" style="
:line-data="{ list: list, xProps: dynamicProps.map((v) => v.prop) }" /> margin-top: 0;
</transition> margin-bottom: 12px;
background: #fff;
padding: 12px 16px 16px;
border-radius: 8px;
">
<el-row style="display: flex; align-items: center">
<div class="blue-title">产线检测详细</div>
<div class="custom-tabs">
<el-tabs
v-model="activeName"
:stretch="true"
@tab-click="handleTabClick">
<el-tab-pane
:label="'\u2002数据列表\u2002'"
name="table"></el-tab-pane>
<el-tab-pane
:label="'\u3000柱状图\u3000'"
name="graph"></el-tab-pane>
</el-tabs>
</div>
</el-row>
<transition mode="out-in" name="fade-down">
<template v-if="mode == 'table'">
<base-table
v-if="mode == 'table'"
:table-props="tableProps"
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-data="list"
@emitFun="handleEmitFun"></base-table>
</template>
<GraphPage
v-else
:summary-list="summaryList"
:line-data="{
list: list,
xProps: dynamicProps.map((v) => v.prop),
}" />
</transition>
</el-row>
<!-- todo: 数据总览用弹窗包裹的 table 实现 --> <!-- todo: 数据总览用弹窗包裹的 table 实现 -->
<base-dialog <!-- <base-dialog
dialogTitle="数据总览" dialogTitle="数据总览"
:dialogVisible="summaryOpen" :dialogVisible="summaryOpen"
width="50%" width="50%"
@ -40,7 +91,7 @@
@cancel="handleSummaryClose" @cancel="handleSummaryClose"
@confirm="handleSummaryClose"> @confirm="handleSummaryClose">
<summaryTable :list="summaryList" /> <summaryTable :list="summaryList" />
</base-dialog> </base-dialog> -->
</div> </div>
</template> </template>
@ -48,13 +99,58 @@
import GraphPage from './graphPage.vue'; import GraphPage from './graphPage.vue';
import summaryTable from './components/summaryTable.vue'; import summaryTable from './components/summaryTable.vue';
class DateGetter {
constructor() {
this.today = new Date();
this.y = this.today.getFullYear();
this.m = this.today.getMonth();
this.d = this.today.getDate();
}
getWeekRange() {
const weekStart = new Date(this.y, this.m, this.d - this.today.getDay());
const weekEnd = new Date(
this.y,
this.m,
this.d + (6 - this.today.getDay()),
23,
59,
59
);
// console.log('week', [weekStart, weekEnd]);
return [weekStart, weekEnd];
}
getMonthRange() {
const monthStart = new Date(this.y, this.m, 1);
const monthEnd = new Date(this.y, this.m + 1, 0, 23, 59, 59);
// console.log('month', [monthStart, monthEnd]);
return [monthStart, monthEnd];
}
getQuarterRange() {
const quarterStart = new Date(this.y, this.m - (this.m % 3), 1);
const quarterEnd = new Date(
this.y,
this.m - (this.m % 3) + 3,
0,
23,
59,
59
);
// console.log('quarter', [quarterStart, quarterEnd]);
return [quarterStart, quarterEnd];
}
}
export default { export default {
name: 'QualityStatistics', name: 'QualityStatistics',
components: { GraphPage, summaryTable }, components: { GraphPage, summaryTable },
props: {}, props: {},
data() { data() {
const dateGetter = new DateGetter();
return { return {
mode: 'table', // defaults to 'table' // mode: 'table', // defaults to 'table'
activeName: 'table', // defaults to 'table'
searchBarFormConfig: [ searchBarFormConfig: [
{ {
type: 'datePicker', type: 'datePicker',
@ -69,6 +165,28 @@ export default {
endPlaceholder: '结束日期', endPlaceholder: '结束日期',
defaultTime: ['00:00:00', '23:59:59'], defaultTime: ['00:00:00', '23:59:59'],
param: 'timerange', param: 'timerange',
pickerOptions: {
shortcuts: [
{
text: '本周',
onClick(picker) {
picker.$emit('pick', dateGetter.getWeekRange());
},
},
{
text: '本月',
onClick(picker) {
picker.$emit('pick', dateGetter.getMonthRange());
},
},
{
text: '本季',
onClick(picker) {
picker.$emit('pick', dateGetter.getQuarterRange());
},
},
],
},
}, },
{ {
type: 'button', type: 'button',
@ -76,33 +194,33 @@ export default {
name: 'search', name: 'search',
color: 'primary', color: 'primary',
}, },
{ // {
type: 'separate', // type: 'separate',
}, // },
{ // {
type: 'button', // type: 'button',
btnName: '数据总览', // btnName: '',
name: 'summary', // name: 'summary',
color: 'text', // color: 'text',
}, // },
{ // {
type: 'separate', // type: 'separate',
}, // },
{ // {
type: 'button', // type: 'button',
btnName: '表格版', // btnName: '',
name: 'tableVersion', // name: 'tableVersion',
color: 'text btn-table', // color: 'text btn-table',
}, // },
{ // {
type: 'separate', // type: 'separate',
}, // },
{ // {
type: 'button', // type: 'button',
btnName: '图形版', // btnName: '',
name: 'graphVersion', // name: 'graphVersion',
color: 'text btn-graph', // color: 'text btn-graph',
}, // },
], ],
// props // props
dynamicProps: [], dynamicProps: [],
@ -165,6 +283,9 @@ export default {
}; };
}, },
computed: { computed: {
mode() {
return this.activeName;
},
tableProps() { tableProps() {
return [ return [
{ {
@ -287,6 +408,14 @@ export default {
}; };
}); });
}, },
handleTabClick(tab, event) {
const { name } = tab;
if (name == 'graph') {
//
} else {
//
}
},
/** 总览关闭 */ /** 总览关闭 */
handleSummaryClose() { handleSummaryClose() {
this.summaryOpen = false; this.summaryOpen = false;
@ -371,6 +500,42 @@ export default {
.fade-down-leave { .fade-down-leave {
transform: translateY(0); transform: translateY(0);
} }
.blue-title {
position: relative;
padding: 4px 0;
padding-left: 12px;
font-size: 14px;
color: #606266;
font-weight: 700;
margin-bottom: 12px;
&::before {
content: '';
position: absolute;
left: 0;
top: 6px;
height: 16px;
width: 4px;
border-radius: 1px;
background: #0b58ff;
}
}
:deep(.custom-tabs) {
.el-tabs__header {
margin-left: 12px;
margin-bottom: 8px;
display: inline-block;
transform: translateY(-6px);
}
.el-tabs__item {
padding-left: 0 !important;
padding-right: 0 !important;
height: 36px;
}
}
</style> </style>
<!-- <!--