添加首页,实时生产监控页面 修改其它页面

This commit is contained in:
hzz 2024-04-12 18:59:31 +08:00
parent 9bc2e73e84
commit 8c55198470
24 changed files with 805 additions and 317 deletions

View File

@ -20,7 +20,7 @@
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "10.6.1",
"axios": "0.27.2",
"echarts": "5.4.3",
"echarts": "^5.5.0",
"element-plus": "2.4.3",
"file-saver": "2.0.5",
"fuse.js": "6.6.2",

View File

@ -45,7 +45,7 @@ export function delQuality(id) {
// 获取合格率
export function qualitystandardRate() {
return request({
url: '/casm/qualitystandardRate',
url: '/casm/quality/standardRate',
method: 'get'
})
}

View File

@ -7,3 +7,34 @@ export function getHomeDeviceInfoVO() {
method: 'get'
})
}
// 首页设备利用率
//参数同首页其他接口
export function homeDeviceRate() {
return request({
url: '/casm/device/homeDeviceRate',
method: 'get'
})
}
//实时生产监控 半小时产量
export function halfHourOutputTotal() {
return request({
url: '/casm/quality/halfHourOutputTotal',
method: 'get'
})
}
//首页 设备 产品 人员信息
export function getBaseInfoNew() {
return request({
url: '/casm/quality/getBaseInfoNew',
method: 'get'
})
}
//首页 产量堆叠图
export function qualitynewDeviceOutputQuality() {
return request({
url: '/casm/quality/newDeviceOutputQuality',
method: 'get'
})
}

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 4503445 */
src: url('iconfont.woff2?t=1712819070350') format('woff2'),
url('iconfont.woff?t=1712819070350') format('woff'),
url('iconfont.ttf?t=1712819070350') format('truetype');
src: url('iconfont.woff2?t=1712901332022') format('woff2'),
url('iconfont.woff?t=1712901332022') format('woff'),
url('iconfont.ttf?t=1712901332022') format('truetype');
}
.iconfont {
@ -13,6 +13,42 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-renyuanxinxi-copy:before {
content: "\e601";
}
.icon-baojing:before {
content: "\e64b";
}
.icon-zidongtaiyajiao:before {
content: "\e61f";
}
.icon-taiyajiaogaodu:before {
content: "\e623";
}
.icon-jizhenzhenshu:before {
content: "\e61a";
}
.icon-caijian:before {
content: "\e66e";
}
.icon-shebeixinxi:before {
content: "\ea02";
}
.icon-tonganrenyuanxinxi:before {
content: "\e61e";
}
.icon-a-zu496:before {
content: "\e600";
}
.icon-shengchanxiaoshuai:before {
content: "\e612";
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1712901827131" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4225" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M0 0m256 0l512 0q256 0 256 256l0 512q0 256-256 256l-512 0q-256 0-256-256l0-512q0-256 256-256Z" fill="#F99D5E" p-id="4226"></path><path d="M427.136 394.1888c14.592 0 26.624 10.752 28.2368 24.832l0.2048 3.328a28.16 28.16 0 0 1-28.416 28.1344h-55.7568a28.16 28.16 0 0 1 0-56.32h55.7312z m0 112.5888c14.592 0 26.624 10.752 28.2368 24.832l0.2048 3.328a28.16 28.16 0 0 1-28.416 28.1344h-55.7568a28.16 28.16 0 1 1 0-56.32h55.7312z m169.1648-112.5888c33.792 0 60.8512 27.8528 60.8512 67.8912 0 15.3344-9.216 37.4784-20.3264 53.8112-6.5024 8.1664-3.6608 15.2576 1.0752 17.792l26.624 14.72 0.64 0.3584c10.3424 5.7088 17.92 9.984 23.0144 13.056 13.312 8.9088 19.712 15.5136 20.7104 27.1872v29.056c0 0.9472-0.4608 1.28-1.024 1.28h-223.1296c-0.384 0-1.024-0.5376-1.024-1.28v-29.056c0-11.008 6.3744-17.7152 20.48-27.136a1383.936 1383.936 0 0 1 49.8944-27.904c4.7872-2.7648 7.5776-9.5488 0.512-18.5088-10.368-15.3344-19.456-37.76-19.456-53.376 0-40.3968 26.8288-67.8912 61.184-67.8912zM286.72 675.6608H737.024V337.8944H286.72v337.7664zM737.28 281.6c30.9248 0 56.0128 25.1904 56.0128 56.1152V675.84a56.2176 56.2176 0 0 1-56.0128 56.1152H286.4128A56.1152 56.1152 0 0 1 230.4 675.84V337.7152C230.4 306.7392 255.6672 281.6 286.4128 281.6H737.28z" fill="#FFFFFF" p-id="4227"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1712902048974" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1290" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M0 0h768Q1024 0 1024 256v512Q1024 1024 768 1024h-512Q0 1024 0 768v-512Q0 0 256 0z" fill="#8DE98A" p-id="1291"></path><path d="M628.658424 443.066182a25.832727 25.832727 0 0 0-21.271272-21.224727H589.110303c-42.542545 3.10303-72.921212-51.541333-48.64-84.883394l9.138424-18.214788c3.10303-6.035394 6.081939-12.117333 0-15.142788a51.525818 51.525818 0 0 0-42.542545-27.291152c-15.220364-3.10303-21.271273 12.148364-27.368727 21.224728a66.327273 66.327273 0 0 1-9.138425 15.173818 44.450909 44.450909 0 0 1-27.368727 18.183757 56.490667 56.490667 0 0 1-69.911273-30.332121c-15.220364-27.291152-24.312242-30.332121-51.680969-12.117333-3.10303 3.009939-6.081939 3.009939-9.138425 6.035394a21.519515 21.519515 0 0 0-6.050909 33.357576c3.10303 9.107394 9.091879 15.142788 12.132849 24.250181 15.220364 30.332121-9.091879 69.725091-42.542546 75.807031h-30.378666a20.355879 20.355879 0 0 0-21.271273 12.117333 99.902061 99.902061 0 0 0 0 42.433939 16.647758 16.647758 0 0 0 18.230303 12.148364h15.220364a58.166303 58.166303 0 0 1 48.64 18.183758 58.864485 58.864485 0 0 1 6.050909 72.79709c-18.230303 30.301091-15.189333 39.408485 15.220363 54.551273a11.170909 11.170909 0 0 0 9.091879 3.103031 20.355879 20.355879 0 0 0 24.312243-9.107394 48.593455 48.593455 0 0 0 12.179393-21.224728 57.002667 57.002667 0 0 1 97.264485 0 75.450182 75.450182 0 0 0 12.179394 21.224728c9.091879 12.148364 15.220364 12.148364 30.363152 6.066424s30.440727-12.117333 33.450666-33.326546a23.086545 23.086545 0 0 0-6.081939-15.173818c-3.10303-6.066424-9.091879-12.117333-12.148364-18.183757a55.001212 55.001212 0 0 1 39.501576-75.807031 123.407515 123.407515 0 0 1 33.450667 0c15.220364 0 21.271273-6.066424 21.271273-21.224727a34.133333 34.133333 0 0 0 6.112969-33.404121z m-200.626424 97.047273a80.35297 80.35297 0 1 1 0-160.67491 80.35297 80.35297 0 0 1 0 160.67491z m373.915152 63.612121a43.240727 43.240727 0 0 0-6.08194-18.183758 12.737939 12.737939 0 0 0-18.230303-9.076363 71.819636 71.819636 0 0 1-24.312242 6.066424 40.339394 40.339394 0 0 1-36.538182-51.572364c6.081939-21.224727 3.10303-27.260121-15.189333-30.301091-18.230303-6.066424-24.312242 0-30.409697 18.183758v3.10303a37.655273 37.655273 0 0 1-63.813819 18.183758 41.999515 41.999515 0 0 0-12.179394-9.076364 14.320485 14.320485 0 0 0-18.230303-3.10303q-31.914667 18.168242-9.138424 45.474909a48.624485 48.624485 0 0 1 15.220364 33.357576 38.679273 38.679273 0 0 1-33.450667 33.326545c-18.230303 6.066424-21.271273 12.148364-15.220364 30.332121s12.179394 21.224727 30.440728 15.142788a36.926061 36.926061 0 0 1 42.542545 6.066424c15.220364 12.148364 15.220364 27.291152 9.091879 45.474909-3.10303 6.066424-6.050909 15.173818 0 18.214788a34.428121 34.428121 0 0 0 33.450667 9.076364c12.179394 0 12.179394-12.117333 12.179394-18.183758a11.217455 11.217455 0 0 1 3.009939-9.107394 39.641212 39.641212 0 0 1 63.860364-18.183757c3.10303 3.10303 9.138424 6.066424 12.132848 12.148364a20.262788 20.262788 0 0 0 18.261333 3.009939c21.271273-9.076364 24.281212-27.260121 9.091879-45.474909l-3.10303-3.10303a39.346424 39.346424 0 0 1 15.220364-66.715152c3.10303 0 6.081939-3.10303 12.132848-3.10303 6.081939 3.10303 9.138424-3.10303 9.138424-12.117334z m-136.812607 84.914424a54.566788 54.566788 0 1 1 54.72194-54.582303 50.936242 50.936242 0 0 1-54.737455 54.628848z" fill="#FFFFFF" p-id="1292"></path></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -61,6 +61,9 @@ export default {
"添加成功": "Add Success",
"修改成功": "Edit Success",
"删除成功": "Delete Success",
"合格": "Pass",
"不合格": "Fail",
"未完成": "Unfinished",
},
"validate": {
"不能为空": "Can not be empty ",
@ -103,6 +106,24 @@ export default {
"fixedHeader": "Fixed Header",
"sidebarLogo": "Sidebar Logo"
},
"home":{
"员工总数": "Staff Total",
"设备总数": "Device Total",
"产出进度": "Output Progress",
"设备": "Device",
"使用中": "In Use",
"停机": "Down",
"总数": "Total",
"工作人员": "Staff",
"加工信息": "Process Info",
"产量": "Output",
"稼动率": "Utilization",
"设备利用率": "Device Utilization",
"设备状态": "Device Status",
"台": "Units",
"人": "Pepole",
},
"device": {
"设备信息": "Device Info",
"设备名称": "Device Name",
@ -130,6 +151,8 @@ export default {
"底线编码": "BottomCode",
"面线编码": "UpperCode",
"表面张力": "Tension",
"最小张力": "Min Tension",
"最大张力": "Max Tension",
"最小值": "Min",
"最大值": "Max",
"最小针数": "MinNeedle",
@ -141,7 +164,7 @@ export default {
"梭芯信息": "Bobbin",
"排序": "Sort",
"类型": "Type",
"第几": "Needle No.",
"第几": "Needle No.",
"步骤": "Step",
},
"produce": {

View File

@ -62,6 +62,9 @@ export default {
"添加成功": "添加成功",
"修改成功": "修改成功",
"删除成功": "删除成功",
'合格': '合格',
'不合格': '不合格',
"未完成": "未完成",
},
"validate": {
"不能为空": "不能为空",
@ -104,6 +107,23 @@ export default {
"fixedHeader": "固定 Header",
"sidebarLogo": "侧边栏 Logo"
},
"home":{
"员工总数": "员工总数",
"设备总数": "设备总数",
"产出进度": "产出进度",
"设备": "设备",
"使用中": "使用中",
"停机": "停机",
"总数": "总数",
"工作人员": "工作人员",
"加工信息": "加工信息",
"产量": "产量",
"稼动率": "稼动率",
"设备利用率": "设备利用率",
"设备状态": "设备状态",
"台": "台",
"人": "人",
},
"device": {
"设备信息": "设备信息",
"设备名称": "设备名称",
@ -131,6 +151,8 @@ export default {
"底线编码": "底线编码",
"面线编码": "面线编码",
"表面张力": "表面张力",
"最小张力": "最小张力",
"最大张力": "最大张力",
"最小值": "最小值",
"最大值": "最大值",
"最小针数": "最小针数",

View File

@ -51,12 +51,13 @@ import { getStoredLanguage, saveStoredLanguage } from "@/utils/languageStorage";
import VECharts from 'vue-echarts'
import { use } from 'echarts/core'
// 手动引入 ECharts 各模块来减小打包体积
//引入iconfont
import './assets/iconfont/iconfont.css'
import {
CanvasRenderer
} from 'echarts/renderers'
import {
PieChart,LineChart
PieChart,LineChart,BarChart
} from 'echarts/charts'
import {
TitleComponent,
@ -72,6 +73,7 @@ use([
GridComponent,
PieChart,
LineChart,
BarChart
]);

View File

@ -66,7 +66,7 @@ export const constantRoutes = [
path: '/index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '实时生产监控', icon: 'dashboard', affix: true }
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},

316
src/views/dashboard.vue Normal file
View File

@ -0,0 +1,316 @@
<template>
<div class="app-container">
<el-row :gutter="10" class="mb8">
<el-col :span="3">
<div class="card-box">
{{ tLang('home', '员工总数') }}200{{ tLang('home', '人') }}
</div>
</el-col>
<el-col :span="3">
<div class="card-box">
{{ tLang('home', '产出进度') }}60%
</div>
</el-col>
</el-row>
<div class="chart-content">
<div class="chart-content-card">
<v-chart class="line-chart" :option="line_option" />
</div>
<div class="chart-content-card">
<v-chart class="line-chart" :option="pie_option" />
</div>
<div class="right-content-card">
<div>{{ deviceState.on + tLang('home', '台') }}/{{ deviceState.total + tLang('home', '台') }}</div>
<div>{{ tLang('home', '设备') + `:` + tLang('home', '使用中') + `/` + tLang('home', '总数') }}</div>
</div>
</div>
<div class="bottom">
<div class="device-item" v-for="(item, index) in produceList"
:style="{ 'background-color': item_bgcolor[item.state] }">
<span class="iconfont icon-shengchanxiaoshuai icon-style"
:style="{ color: item_color[item.progressSignal], borderColor: item_color[item.progressSignal] }"></span>
<div class="device-item-content">
<div class="device-item-content-flex left">
<img class="frj-img" :src="item.file" alt="">
<span>{{ tLang('device', '设备编码') + `` + item.deviceCode }}</span>
</div>
<div class="device-item-content-flex right">
<ul class="produce-list">
<li>{{ tLang('home', '工作人员') + `` + item.userName }}</li>
<li>{{ tLang('home', '加工信息') + `` + item.productionCode }}</li>
<li>{{ tLang('home', '产量') + `` + item.output }}/{{ item.planOutput }}</li>
<li>{{ tLang('home', '稼动率') + `` + item.activation }}</li>
</ul>
</div>
</div>
</div>
</div>
<div class="pagination">
<el-pagination :hide-on-single-page="false" v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize" layout="total, prev, pager, next, jumper" :total="total"
@size-change="getList" @current-change="getList" />
</div>
</div>
</template>
<script setup>
import { getHomeDeviceInfoVO, homeDeviceRate, halfHourOutputTotal } from "@/api/home";
const { proxy } = getCurrentInstance();
let loading = ref(true)
//
let queryParams = reactive({
pageNum: 1,
pageSize: 10,
})
const baseUrl = import.meta.env.VITE_APP_BASE_API;
let total = ref(0)
let deviceState = reactive({
on: 0,
off: 0,
total: 0
})
let produceList = ref([])
let item_bgcolor = {
0: '#E8E8E8',
1: '#E9E5C9',
2: '#C9F6CC',
3: '#E9E5C9',
4: '#EFCAC5',
}
let item_color = {
0: '#5EF417',
1: '#176AF4',
2: '#DACB71',
3: '#D81E06',
4: '#CCCCCC',
}
const line_option = ref({
title: {
text: proxy.tLang('home', '产量')
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true
}
]
});
const pie_option = ref({
title: {
"text": proxy.tLang('home', '设备利用率') + "60%",
"left": "0",
"top": 0,
"textStyle": {
"color": "#333",
"fontSize": 24
}
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
right: '5%',
},
series: [
{
name: proxy.tLang('home', '设备状态'),
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 10
},
label: {
show: true,
fontSize: 16,
formatter: '{b} : {c} ({d}%)'
},
data: []
}
]
})
function getList() {
loading.value = true;
halfHourOutputTotal().then(response => {
line_option.value.series[0].data = response.data.count
line_option.value.xAxis.data = response.data.time
});
homeDeviceRate().then(response => {
pie_option.value.series[0].data = [
{ value: response.data.on, name: proxy.tLang('home', '使用中') },
{ value: response.data.off, name: proxy.tLang('home', '停机') }
]
deviceState.on = response.data.on;
deviceState.off = response.data.off;
deviceState.total = response.data.total;
pie_option.value.title.text = proxy.tLang('home', '设备利用率') + `${((response.data.on / response.data.total) * 100).toFixed(1)}%`
});
getHomeDeviceInfoVO().then(response => {
produceList.value = response.rows.map((item, index) => {
item.file = baseUrl + item.file;
return item;
});
total.value = response.total;
// loading.value = false;
});
}
onMounted(() => {
getList();
})
</script>
<style scoped lang="scss">
@import '@/assets/iconfont/iconfont.css';
.card-box {
background-color: #C8EAF4;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
padding: 5px 5px;
text-align: center;
font-size: 18px;
font-weight: 700;
color: #333333;
}
.chart-content {
width: 100%;
height: 310px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
.chart-content-card {
width: 40%;
height: 100%;
.line-chart {
width: 100%;
height: 100%;
}
}
.right-content-card {
width: 200px;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 18px;
font-weight: 700;
color: #333333;
div {
margin-bottom: 10px;
}
}
}
.bottom {
width: 100%;
height: calc(100vh - 310px - 110px);
display: grid;
grid-template-columns: 16.66% 16.66% 16.66% 16.66% 16.66% 16.66%;
grid-template-rows: 50% 50%;
/* 设置网格项目间间隙 */
gap: 10px 10px;
.device-item {
width: 100%;
height: 100%;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
text-align: center;
padding: 8px 2px 2px 2px;
box-sizing: border-box;
.icon-style {
font-size: 30px;
border: 2px solid;
border-radius: 50%;
padding: 10px;
line-height: 50px;
/*color: #bfc;*/
}
.device-item-content {
width: calc(100% - 4px);
height: calc(100% - 50px - 4px);
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
.left {
width: 50%;
}
.right {
flex: 1;
font-size: 12px;
}
.device-item-content-flex {
height: 100%;
box-sizing: border-box;
padding: 10px 0;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
overflow: hidden;
.frj-img {
max-width: 100%;
max-height: 70%;
margin-bottom: 5px;
}
.produce-list {
padding: 0;
margin: 0 0 0 15px;
width: 100%;
height: 100%;
display: flex;
justify-content: space-around;
align-items: flex-start;
flex-direction: column;
li {
list-style: none;
}
}
}
}
}
}
.pagination {
width: 100%;
margin: 10px;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@ -1,95 +1,187 @@
<template>
<div class="app-container">
<el-row :gutter="10" class="mb8">
<el-col :span="3">
<div class="card-box">
员工总数200
<div class="left-content">
<div class="top-box">
<div class="device-info">
<div class="info-title">
<i class="iconfont icon-shebeixinxi" style="color: #46B3F8;font-size: 30px;"></i>
设备信息
</div>
</el-col>
<el-col :span="3">
<div class="card-box">
产出进度60%
</div>
</el-col>
<div class="info-content">
<el-row justify="space-evenly">
<el-col :span="12">设备编码</el-col>
<el-col :span="12">11</el-col>
</el-row>
<el-row>
<el-col :span="12">设备名称</el-col>
<el-col :span="12">11</el-col>
</el-row>
<el-row>
<el-col :span="12">运行时长</el-col>
<el-col :span="12">11</el-col>
</el-row>
<div class="chart-content">
<div class="chart-content-card">
<v-chart class="line-chart" :option="line_option" />
</div>
<div class="chart-content-card">
<v-chart class="line-chart" :option="pie_option" />
</div>
<div class="right-content-card">
<div>20/70</div>
<div>设备使用中/总数</div>
</div>
</div>
<div class="bottom">
<div class="device-item" v-for="(item, index) in produceList" :style="{'background-color':item_bgcolor[item.state]}">
<span class="iconfont icon-shengchanxiaoshuai icon-style" :style="{color:item_color[item.progressSignal],borderColor:item_color[item.progressSignal]}"></span>
<div class="device-item-content">
<div class="device-item-content-flex left">
<img class="frj-img" :src="item.file" alt="">
<span>设备编号{{ item.deviceCode }}</span>
<div class="user-info">
<div class="info-title">
<svg-icon icon-class="renyuanxinxi" style="font-size: 30px;" />
人员信息
</div>
<div class="device-item-content-flex right">
<ul class="produce-list">
<li>工作人员{{ item.userName }}</li>
<li>加工信息{{ item.productionCode }}</li>
<li>产量{{item.output}}/{{ item.planOutput }}</li>
<li>稼动率{{ item.activation }}</li>
</ul>
<div class="info-content">
<el-row justify="space-evenly">
<el-col :span="12">操作员</el-col>
<el-col :span="12">张一一</el-col>
</el-row>
<el-row>
<el-col :span="12">人员ID</el-col>
<el-col :span="12">11</el-col>
</el-row>
</div>
</div>
</div>
<div class="produce-info">
<div class="info-title">
<svg-icon icon-class="shengchanxinxi" style="font-size: 30px;" /> 生产信息
</div>
<div class="pagination">
<el-pagination :hide-on-single-page="false" v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize" layout="total, prev, pager, next, jumper" :total="total"
@size-change="getList" @current-change="getList" />
<div class="info-content">
<el-row justify="space-evenly">
<el-col :span="12">操作员</el-col>
<el-col :span="12">张一一</el-col>
</el-row>
<el-row>
<el-col :span="12">人员ID</el-col>
<el-col :span="12">11</el-col>
</el-row>
</div>
</div>
<div class="barchart">
<v-chart class="chart-class" :option="bar_option" />
</div>
</div>
<div class="right-content">
<div class="zhangli">
<v-chart class="chart-class" :option="line_option" />
</div>
<div class="table">
啊啊 1720*828
1680*788
</div>
</div>
</div>
</template>
<script setup>
import { getHomeDeviceInfoVO } from "@/api/home";
import { getBaseInfoNew,qualitynewDeviceOutputQuality } from "@/api/home";
let loading = ref(true)
//
let queryParams = reactive({
pageNum: 1,
pageSize: 10,
})
const baseUrl = import.meta.env.VITE_APP_BASE_API;
let total = ref(0)
let produceList = ref([])
let item_bgcolor = {
0: '#E8E8E8',
1: '#E9E5C9',
2: '#C9F6CC',
3: '#E9E5C9',
4: '#EFCAC5',
}
let item_color = {
0: '#5EF417',
1: '#176AF4',
2: '#DACB71',
3: '#D81E06',
4: '#CCCCCC',
}
const line_option = ref({
let pass = ref([0]);
let noPass = ref([0]);
let bar_option = ref({
title: {
text: '产量'
text: '产量',
textStyle: {
color: '#797979'
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['合格', '不合格'],
textStyle: {
color: '#797979'
},
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: ['0'],
axisLabel: {
fontSize: 12,
color: '#797979'
},
}
],
yAxis: [
{
type: 'value',
axisLabel: {
fontSize: 12,
color: '#797979'
},
splitLine: {
lineStyle: {
type: 'dashed',
}
},
}
],
series: [
{
name: '合格',
type: 'bar',
stack: 'Ad',
shape: 'circle',
emphasis: {
focus: 'series'
},
itemStyle: {
color: '#91cc75'
},
data: [0]
},
{
name: '不合格',
type: 'bar',
stack: 'Ad',
shape: 'circle',
emphasis: {
focus: 'series'
},
itemStyle: {
color: '#5470c6'
},
data: [0],
label: {
show: true,
position: 'top',
color: "#797979",
formatter: function (p) {
let sum = pass.value[p.dataIndex] + noPass.value[p.dataIndex];
return sum;
}
}
}
]
})
let line_option = ref({
title: {
text: '张力值',
left: '0',
textStyle: {
color: '#000'
}
},
xAxis: {
name: '针数',
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
name: '张力',
type: 'value'
},
series: [
@ -99,200 +191,149 @@ const line_option = ref({
smooth: true
}
]
});
const pie_option = ref({
"title": {
"text": "设备利用率60%",
"left": "0",
"top": 0,
"textStyle": {
"color": "#333",
"fontSize": 24
}
},
tooltip: {
trigger: 'item'
},
legend: {
bottom: '5%',
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 10
},
label: {
show: true,
},
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' },
{ value: 580, name: 'Email' },
{ value: 484, name: 'Union Ads' },
{ value: 300, name: 'Video Ads' }
]
}
]
})
function getList() {
loading.value = true;
getHomeDeviceInfoVO().then(response => {
produceList.value = response.rows.map((item, index) => {
item.file = baseUrl + item.file;
return item;
function getData() {
getBaseInfoNew().then(res => {
console.log(res);
});
total.value = response.total;
// loading.value = false;
qualitynewDeviceOutputQuality().then(res => {
pass.value = res.data.pass;
noPass.value = res.data.noPass;
bar_option.value.series[0].data = res.data.pass;
bar_option.value.series[1].data = res.data.noPass;
bar_option.value.xAxis[0].data = res.data.time;
});
}
onMounted(() => {
getList();
})
getData();
});
</script>
<style scoped lang="scss">
@import '@/assets/iconfont/iconfont.css';
.card-box {
background-color: #C8EAF4;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
padding: 5px 5px;
text-align: center;
font-size: 18px;
font-weight: 700;
color: #333333;
}
.chart-content {
<style lang="scss" scoped>
.app-container {
width: 100%;
height: 310px;
height: 828px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
overflow: auto;
.chart-content-card {
width: 40%;
.left-content {
width: 700px;
height: 100%;
margin-right: 15px;
.line-chart {
.info-title {
height: 50px;
font-size: 26px;
color: #797979;
font-weight: bold;
line-height: 50px;
.iconfont {
margin-right: 10px;
}
}
.info-content {
width: 100%;
height: 100%;
}
}
.right-content-card {
width: 200px;
height: 100%;
height: 158px;
font-size: 20px;
display: flex;
flex-direction: column;
justify-content: center;
justify-content: space-around;
}
.top-box {
width: 100%;
height: 208px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
font-weight: 700;
color: #333333;
margin-bottom: 15px;
div {
margin-bottom: 10px;
}
}
}
.bottom {
width: 100%;
height: calc(100vh - 310px - 110px);
display: grid;
grid-template-columns: 16.66% 16.66% 16.66% 16.66% 16.66% 16.66%;
grid-template-rows: 50% 50%;
/* 设置网格项目间间隙 */
gap: 10px 10px;
.device-item {
width: 100%;
.device-info {
width: 48%;
height: 100%;
padding: 5px 5px 5px 10px;
box-sizing: border-box;
background-color: #E9F3FA;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
}
.user-info {
width: 48%;
height: 100%;
padding: 5px 5px 5px 10px;
box-sizing: border-box;
background-color: #FAF1EB;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
}
}
.produce-info {
width: 100%;
height: 208px;
padding: 5px 5px 5px 10px;
box-sizing: border-box;
background-color: #F0F8F0;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
margin-bottom: 15px;
}
.barchart {
width: 100%;
height: calc(100% - 416px - 30px);
padding: 5px;
box-sizing: border-box;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
text-align: center;
padding:8px 2px 2px 2px;
box-sizing: border-box;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
.icon-style {
font-size: 30px;
border: 2px solid;
border-radius: 50%;
padding: 10px;
line-height: 50px;
/*color: #bfc;*/
}
.device-item-content {
width: calc(100% - 4px);
height: calc(100% - 50px - 4px);
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
.left {
width: 50%;
}
.right {
.chart-class {
width: 100%;
height: 100%;
}
.right-content {
flex: 1;
font-size: 12px;
}
.device-item-content-flex {
height: 100%;
.zhangli {
width: 100%;
height: 431px;
padding: 5px;
box-sizing: border-box;
padding: 10px 0;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
overflow: hidden;
.frj-img {
max-width: 100%;
max-height: 70%;
margin-bottom: 5px;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
margin-bottom: 15px;
}
.produce-list {
padding: 0;
margin: 0 0 0 15px;
.table {
width: 100%;
height: 100%;
display: flex;
justify-content: space-around;
align-items: flex-start;
flex-direction: column;
li {
list-style: none;
}
}
height: calc(100% - 416px - 30px);
padding: 5px;
box-sizing: border-box;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
}
}
}
}
.pagination {
width: 100%;
margin: 10px;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@ -1,20 +1,20 @@
<template>
<el-dialog v-model="props.modelValue" title="设备详情" @close="close" width="800">
<el-descriptions title="" column="2">
<el-descriptions-item label="产品名称">{{ props.info.name }}</el-descriptions-item>
<el-descriptions-item label="产品编码">{{ props.info.code }}</el-descriptions-item>
<el-descriptions-item label="产品名称">{{ props.info.productionName }}</el-descriptions-item>
<el-descriptions-item label="产品编码">{{ props.info.productionCode }}</el-descriptions-item>
<el-descriptions-item label="产品类型">{{ props.info.type }}</el-descriptions-item>
<el-descriptions-item label="设备名称">{{ props.info.workShop }}</el-descriptions-item>
<el-descriptions-item label="设备编码">{{ props.info.lineName }}</el-descriptions-item>
<el-descriptions-item label="设备名称">{{ props.info.deviceName }}</el-descriptions-item>
<el-descriptions-item label="设备编码">{{ props.info.deviceCode }}</el-descriptions-item>
<el-descriptions-item label="员工姓名">{{ props.info.maintenance }}</el-descriptions-item>
<el-descriptions-item label="员工编码">{{ props.info.needleNum }}</el-descriptions-item>
<el-descriptions-item label="目标产量">{{ props.info.maintenance }}</el-descriptions-item>
<el-descriptions-item label="实时产量">{{ props.info.needleNum }}</el-descriptions-item>
<el-descriptions-item label="员工姓名">{{ props.info.userName }}</el-descriptions-item>
<el-descriptions-item label="员工编码">{{ props.info.userCode }}</el-descriptions-item>
<el-descriptions-item label="目标产量">{{ props.info.planOutput }}</el-descriptions-item>
<el-descriptions-item label="实时产量">{{ props.info.output }}</el-descriptions-item>
<el-descriptions-item label="开始时间">{{ props.info.maintenance }}</el-descriptions-item>
<el-descriptions-item label="结束时间">{{ props.info.needleNum }}</el-descriptions-item>
<el-descriptions-item label="开始时间">{{ props.info.starttime }}</el-descriptions-item>
<el-descriptions-item label="结束时间">{{ props.info.endtime }}</el-descriptions-item>
</el-descriptions>
<el-descriptions title="" column="1">
<el-descriptions-item label="备注信息">{{ props.info.remark }}</el-descriptions-item>

View File

@ -3,16 +3,16 @@
<el-form ref="formRef" :inline="true" :model="props.form" :rules="rules" class="demo-form-inline"
label-width="100px">
<el-form-item :label="tLang('product', '产品编码')" prop="code">
<el-input v-model="form.code" :disabled="Boolean(props.form.code)" :placeholder="tLang('common', '请输入') + tLang('product', '产品编码')" />
<el-input v-model="form.code" :disabled="Boolean(props.form.id)" :placeholder="tLang('common', '请输入') + tLang('product', '产品编码')" />
</el-form-item>
<el-form-item :label="tLang('product', '针号')" prop="needleNum">
<el-input v-model="form.needleNum" :placeholder="tLang('common', '请输入') + tLang('product', '针号')" />
</el-form-item>
<el-form-item :label="tLang('product', '面线信息')" prop="surfacelineId">
<el-input v-model="form.surfacelineId" :placeholder="tLang('common', '请输入') + tLang('product', '面线信息')" />
<el-form-item :label="tLang('product', '面线信息')" prop="surfacelineCode">
<el-input v-model="form.surfacelineCode" :placeholder="tLang('common', '请输入') + tLang('product', '面线信息')" />
</el-form-item>
<el-form-item :label="tLang('product', '底线信息')" prop="bottomlineId">
<el-input v-model="form.bottomlineId" :placeholder="tLang('common', '请输入') + tLang('product', '底线信息')" />
<el-form-item :label="tLang('product', '底线信息')" prop="bottomlineCode">
<el-input v-model="form.bottomlineCode" :placeholder="tLang('common', '请输入') + tLang('product', '底线信息')" />
</el-form-item>
<!-- <el-form-item :label="tLang('product', '梭芯信息')" prop="shuttlecoreId">
<el-input v-model="form.shuttlecoreId" :placeholder="tLang('common', '请输入') + tLang('product', '梭芯信息')" />
@ -20,10 +20,10 @@
<el-form-item :label="tLang('product', '排序')" prop="sort">
<el-input v-model.number="form.sort" :placeholder="tLang('common', '请输入') + tLang('product', '排序')" />
</el-form-item>
<el-form-item :label="tLang('product', '最小')" prop="min">
<el-form-item :label="tLang('product', '最小张力')" prop="min">
<el-input-number v-model="form.min" :min="1" @change="handleChange" />
</el-form-item>
<el-form-item :label="tLang('product', '最大')" prop="max">
<el-form-item :label="tLang('product', '最大张力')" prop="max">
<el-input-number v-model="form.max" :min="1" @change="handleChange" />
</el-form-item>
<el-form-item :label="tLang('product', '备注')" prop="remark">

View File

@ -51,13 +51,13 @@
<!-- <el-table-column :label="主键id" align="center" prop="id" /> -->
<el-table-column :label="tLang('product', '产品编码')" align="center" v-if="columns[0].visible" prop="code" />
<el-table-column :label="tLang('product', '针号')" align="center" v-if="columns[1].visible" prop="needleNum" />
<el-table-column :label="tLang('product', '面线信息')" align="center" v-if="columns[2].visible" prop="surfacelineId" />
<el-table-column :label="tLang('product', '底线信息')" align="center" width="80" v-if="columns[3].visible"
prop="bottomlineId" />
<el-table-column :label="tLang('product', '梭芯信息')" align="center" v-if="columns[4].visible" prop="shuttlecoreId" />
<el-table-column :label="tLang('product', '排序')" align="center" v-if="columns[5].visible" prop="sort" />
<el-table-column :label="tLang('product', '最小')" align="center" v-if="columns[6].visible" prop="min" />
<el-table-column :label="tLang('product', '最大')" align="center" v-if="columns[7].visible" prop="max" />
<el-table-column :label="tLang('product', '面线信息')" align="center" v-if="columns[2].visible" prop="surfacelineCode" />
<el-table-column :label="tLang('product', '底线信息')" align="center" v-if="columns[3].visible"
prop="bottomlineCode" />
<el-table-column :label="tLang('product', '梭芯信息')" align="center" v-if="columns[4].visible" prop="shuttlecoreCode" />
<!-- <el-table-column :label="tLang('product', '排序')" align="center" v-if="columns[5].visible" prop="sort" /> -->
<el-table-column :label="tLang('product', '最小张力')" align="center" v-if="columns[6].visible" prop="min" />
<el-table-column :label="tLang('product', '最大张力')" align="center" v-if="columns[7].visible" prop="max" />
<!-- <el-table-column :label="tLang('product','类型')" align="center" v-if="columns[8].visible" prop="type" /> -->
<!-- <el-table-column :label="备注" align="center" prop="remark" /> -->
<el-table-column :label="tLang('common', '操作')" align="center" class-name="small-padding fixed-width">
@ -215,9 +215,8 @@ function reset() {
id: null,
code: null,
needleNum: null,
surfacelineId: null,
bottomlineId: null,
shuttlecoreId: null,
surfacelineCode: null,
bottomlineCode: null,
sort: null,
min: 1,
max: 1,

View File

@ -3,7 +3,7 @@
<el-form ref="formRef" :inline="true" :model="props.form" :rules="rules" class="demo-form-inline"
label-width="100px">
<el-form-item :label="tLang('product', '产品编码')" prop="code">
<el-input v-model="props.form.code" :disabled="Boolean(props.form.code)" :placeholder="tLang('common', '请输入') + tLang('product', '产品编码')" />
<el-input v-model="props.form.code" :disabled="Boolean(props.form.disabled)" :placeholder="tLang('common', '请输入') + tLang('product', '产品编码')" />
</el-form-item>
<el-form-item :label="tLang('product', '产品名称')" prop="name">
<el-input v-model="props.form.name" :placeholder="tLang('common', '请输入') + tLang('product', '产品名称')" />

View File

@ -79,7 +79,7 @@
<el-image-viewer v-if="showImagePreview" :url-list="showsrcListref" hide-on-click-modal teleported
@close="closePreview" style="z-index: 3000" />
</div>
<canvas ref="myCanvas" width="350" height="250" style="display: none;"></canvas>
<canvas ref="myCanvas" width="250" height="350" style="display: none;background-color: #fff;"></canvas>
</template>
<script setup>
@ -136,10 +136,14 @@ function getProductQRCode(code) {
console.log(list);
ctx = myCanvas.value.getContext('2d');
//
ctx.fillStyle = '#ffffff';
//
ctx.fillRect(0, 0, myCanvas.value.width, myCanvas.value.height);
//
const qrImage = new Image();
qrImage.onload = function () {
ctx.drawImage(qrImage, 30, 10, 200, 200); //
ctx.drawImage(qrImage, 20, 60, 220, 220); //
addListInfo(list);
};
qrImage.src = qrCodeURL;
@ -149,12 +153,13 @@ function getProductQRCode(code) {
//
function addListInfo(list) {
ctx.font = "12px Arial";
ctx.font = "bold 20px Arial";
ctx.fillStyle = "black";
Object.keys(list).forEach((key,index) => {
ctx.fillText(key +':'+ list[key], 240, 30 + index * 20); //
});
ctx.textAlign="center";
ctx.fillText("产品编码" + ':' + code, 125, 310); //
// Object.keys(list).forEach((key,index) => {
// ctx.fillText(key +':'+ list[key], 240, 30 + index * 20); //
// });
downloadImage();
}
@ -254,12 +259,12 @@ function cancel() {
//
function reset() {
form.value = {
id: null,
name: '',
type: '',
code: '',
remark: "",
file: ""
file: "",
disabled: false
};
//resetForm("form");
}
@ -270,6 +275,7 @@ function handleUpdate(row) {
const id = row.code || ids.value
getProduction(id).then(response => {
form.value = response.data;
form.value.disabled = true;
open.value = true;
title.value = proxy.tLang('common', '修改') + proxy.tLang('product', '产品信息');
});

View File

@ -7,8 +7,8 @@
</el-descriptions>
<el-descriptions title="" column="3" v-for="(zhen,index) in props.info.zhen" :key="index">
<el-descriptions-item>{{ zhen.needle_num }}</el-descriptions-item>
<el-descriptions-item :label="tLang('product','底线编码')">{{ zhen.bottomline_code }}</el-descriptions-item>
<el-descriptions-item :label="tLang('product','面线编码')">{{ zhen.surfaceline_code }}</el-descriptions-item>
<el-descriptions-item :label="tLang('product','底线编码')">{{ zhen.bottomlineCode }}</el-descriptions-item>
<el-descriptions-item :label="tLang('product','面线编码')">{{ zhen.surfacelineCode }}</el-descriptions-item>
</el-descriptions>
<el-descriptions title="" column="3" v-for="(zhen,index) in props.info.zhen" :key="index">
<el-descriptions-item >{{ zhen.needle_num + "表面张力" }}</el-descriptions-item>

View File

@ -3,9 +3,9 @@
<el-form ref="formRef" :inline="true" :model="props.form" :rules="rules" class="demo-form-inline"
label-width="100px">
<el-form-item :label="tLang('product', '产品编码')" prop="code">
<el-input v-model="form.code" :disabled="Boolean(props.form.code)" :placeholder="tLang('common', '请输入') + tLang('product', '产品编码')" />
<el-input v-model="form.code" :disabled="Boolean(props.form.id)" :placeholder="tLang('common', '请输入') + tLang('product', '产品编码')" />
</el-form-item>
<el-form-item :label="tLang('product', '第几')" prop="num">
<el-form-item :label="tLang('product', '第几')" prop="num">
<el-input-number v-model="form.num" :min="1" @change="handleChange" />
</el-form-item>
<el-form-item :label="tLang('product', '步骤')" prop="step">
@ -14,10 +14,10 @@
<el-form-item :label="tLang('product', '排序')" prop="sort">
<el-input v-model="form.sort" :placeholder="tLang('common', '请输入') + tLang('product', '排序')" />
</el-form-item>
<el-form-item :label="tLang('product', '最小')" prop="min">
<el-form-item :label="tLang('product', '最小针数')" prop="min">
<el-input-number v-model="form.min" :min="1" @change="handleChange" />
</el-form-item>
<el-form-item :label="tLang('product', '最大')" prop="max">
<el-form-item :label="tLang('product', '最大针数')" prop="max">
<el-input-number v-model="form.max" :min="1" @change="handleChange" />
</el-form-item>
<el-form-item :label="tLang('product', '备注')" prop="remark">

View File

@ -33,10 +33,10 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" :label="tLang('common', '序号')" width="60" align="center" />
<el-table-column :label="tLang('product', '产品编码')" align="center" v-if="columns[0].visible" prop="code" />
<el-table-column :label="tLang('product', '第几')" align="center" v-if="columns[1].visible" prop="num" />
<el-table-column :label="tLang('product', '第几')" align="center" v-if="columns[1].visible" prop="num" />
<el-table-column :label="tLang('product', '步骤')" align="center" v-if="columns[2].visible" prop="step" />
<el-table-column :label="tLang('product', '最小')" align="center" v-if="columns[3].visible" prop="min" />
<el-table-column :label="tLang('product', '最大')" align="center" v-if="columns[4].visible" prop="max" />
<el-table-column :label="tLang('product', '最小针数')" align="center" v-if="columns[3].visible" prop="min" />
<el-table-column :label="tLang('product', '最大针数')" align="center" v-if="columns[4].visible" prop="max" />
<el-table-column :label="tLang('product', '排序')" align="center" v-if="columns[5].visible" prop="sort" />
<el-table-column :label="tLang('product', '备注')" align="center" v-if="columns[6].visible" prop="remark" />
<el-table-column :label="tLang('common', '操作')" align="center" class-name="small-padding fixed-width">
@ -102,7 +102,7 @@ let procedureList = ref([])
//
const columns = ref([
{ key: 0, label: proxy.tLang('product', '产品编码'), visible: true },
{ key: 1, label: proxy.tLang('product', '第几'), visible: true },
{ key: 1, label: proxy.tLang('product', '第几'), visible: true },
{ key: 2, label: proxy.tLang('product', '步骤'), visible: true },
{ key: 3, label: proxy.tLang('product', '最小值'), visible: true },
{ key: 4, label: proxy.tLang('product', '最大值'), visible: true },

View File

@ -49,11 +49,13 @@
</el-form>
<el-row :gutter="20" class="mb8">
<el-col :span="2">
<el-statistic :title="tLang('quality', '产品合格率')" :value="qualifiedRate" :precision="1" :value-style="{ color: 'green' }"
<el-statistic :title="tLang('quality', '产品合格率')" :value="qualifiedRate" :precision="1"
:value-style="{ color: 'green' }"
:formatter="(val) => { return ((val / total) * 100).toFixed(1) + '%' }" />
</el-col>
<el-col :span="2">
<el-statistic :title="tLang('quality', '产品不合格率')" :value="unqualifiedRate" :precision="1" :value-style="{ color: 'red' }"
<el-statistic :title="tLang('quality', '产品不合格率')" :value="unqualifiedRate" :precision="1"
:value-style="{ color: 'red' }"
:formatter="(val) => { return ((val / total) * 100).toFixed(1) + '%' }" />
</el-col>
<el-col :span="2">
@ -90,7 +92,15 @@
<span>{{ parseTime(scope.row.endtime, '{y}-{m}-{d} {hh}:{mm}:{ss}') }}</span>
</template>
</el-table-column>
<el-table-column :label="tLang('quality', '状态')" v-if="columns[7].visible" align="center" prop="state" />
<el-table-column :label="tLang('quality', '状态')" v-if="columns[7].visible" align="center" prop="state">
<template #default="scope">
<div>
<el-tag type="success" size="mini" v-if="scope.row.state === '0'">{{tLang('common','合格')}}</el-tag>
<el-tag type="danger" size="mini" v-else-if="scope.row.state === '1'">{{tLang('common','不合格')}}</el-tag>
<el-tag type="error" size="mini" v-else>{{tLang('common','未完成')}}</el-tag>
</div>
</template>
</el-table-column>
<!-- <el-table-column :label="tLang('quality','')操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="详情" placement="top" v-if="scope.row.userId !== 1">