You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

704 lines
20 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div
v-loading="loading"
class="view-container"
element-loading-text="拼命加载中"
>
<!-- 上半部分-->
<div class="view-container-top">
<div class="view-container-tl ">
<div class="view-container-tlt">
<Detail v-for="(item,index) in desc" :key="index" :count="item.count" :desc="item.desc" :img="item.img" />
</div>
<div class="view-container-tlb view-content">
<div class="header">
<div class="title">环境监控图</div>
<div>
<el-select v-model="client_id" placeholder="请选择柜体" @change="(val) => valueChange('id',val)">
<el-option
v-for="item in clientOptions"
:key="item.id"
:label="item.client_name"
:value="item.client_id"
/>
</el-select>
<el-select v-model="client_date" placeholder="请选择" @change="(val) => valueChange('date',val)">
<el-option
v-for="(item,index) in options"
:key="index"
:label="item"
:value="index+1"
/>
</el-select>
<el-radio-group v-model="radio1" @change="(val) => valueChange('radio',val)">
<el-radio-button :label="1">温度</el-radio-button>
<el-radio-button :label="2">湿度</el-radio-button>
<el-radio-button :label="3">VOC</el-radio-button>
</el-radio-group>
</div>
</div>
<div
id="line"
v-loading="loadingLineData"
class="view"
element-loading-text="拼命加载中"
/>
</div>
</div>
<div class="view-container-tr view-content">
<div class="header">
<div class="title">库存余量
<el-popover
placement="right"
title="怎么看试剂余量?"
width="200"
trigger="hover"
content="如“2/50”表示该试剂最后一次入库后共50瓶当前剩余2瓶。"
>
<i slot="reference" class="el-icon-warning-outline" />
</el-popover>
</div>
<div>
<!-- <el-button >查看全部</el-button>-->
</div>
</div>
<div class="header">
<!-- <el-select v-model="client_id" style="margin-right: 0" placeholder="请选择">-->
<!-- <el-option-->
<!-- v-for="item in options"-->
<!-- :key="item.value"-->
<!-- :label="item.label"-->
<!-- :value="item.value"-->
<!-- />-->
<!-- </el-select>-->
<el-select v-model="rclient_id" :disabled="rloading" style="margin-right: 0" placeholder="请选择柜体" @change="remainingPageChange(1)">
<el-option
v-for="item in clientOptions"
:key="item.client_id"
:label="item.client_name"
:value="item.client_id"
/>
</el-select>
</div>
<div class="view">
<el-table
v-loading="rloading"
:data="remainingData"
height="34vh"
stripe
style="width: calc(100% - 1.25rem)"
element-loading-text="拼命加载中"
>
<el-table-column
prop="name"
align="center"
label="试剂名称"
/>
<el-table-column
prop="surplus_number"
align="center"
label="余量"
/>
</el-table>
<div class="my-pagination" style="text-align: center">
<el-pagination
background
layout="prev, pager, next"
:total="rtotal"
:disabled="rloading"
:current-page.sync="rpage"
:page-size.sync="rpage_size"
@current-change="remainingPageChange"
/>
</div>
</div>
</div>
</div>
<!-- 下半部分-->
<div class="view-container-bottom">
<div class="view-container-bl">
<div class="view-container-tr view-content">
<div class="header">
<div class="title">近期预警列表</div>
<div>
<el-button @click="warnAll">查看全部</el-button>
</div>
</div>
<div class="content" style="overflow: auto">
<el-table
stripe
:data="tableData"
>
<el-table-column
align="center"
prop="warning_date"
label="预警时间"
/>
<el-table-column
align="center"
prop="object_type"
label="预警信息类型"
>
<template slot-scope="scope">
{{ warning_data_map[scope.row.object_type-1] }}
</template>
</el-table-column>
<el-table-column
align="center"
prop="object_name"
label="对象"
/>
<el-table-column
show-overflow-tooltip
align="center"
prop="warning_content"
label="内容"
/>
<el-table-column
align="center"
prop="is_solve"
label="受理情况"
>
<template slot-scope="scope">
<el-tag :type="scope.row.is_solve === 0?'warning':'success' ">
{{ scope.row.is_solve === 0 ? '未受理':'已受理' }}
</el-tag>
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- align="center"-->
<!-- prop="address"-->
<!-- label="位置"-->
<!-- />-->
</el-table>
</div>
</div>
</div>
<div class="view-container-br">
<div class="view-container-tr view-content">
<div class="header-warn">
<div class="title">预警信息总览</div>
<div class="count">{{ warning_data_info.count_number }}</div>
<div class="desc">总计(条)</div>
</div>
<div id="pie" />
</div>
</div>
</div>
<!-- // 弹框-->
<el-dialog title="预警信息" width="70%" :visible.sync="dialogTableVisible">
<div class="header-custom">
<el-date-picker
v-model="start_time"
clearable
type="datetime"
placeholder="选择生产日期"
value-format="yyyy-MM-dd HH:mm:ss"
/>
<el-date-picker
v-model="end_time"
clearable
type="datetime"
placeholder="选择过期日期"
value-format="yyyy-MM-dd HH:mm:ss"
/>
<el-select v-model="object_type" clearable placeholder="请选择预警信息类型">
<el-option
v-for="(item,index) in warning_data_map"
:key="index"
:label="item"
:value="index + 1"
/>
</el-select>
<el-input v-model="seach_word" clearable placeholder="请输入搜索试剂名称" />
<el-button :disabled="loadingReagent" type="primary" icon="el-icon-search" @click="searchData">搜索</el-button>
</div>
<el-table
v-loading="loadingReagent"
:data="gridData"
stripe
height="400"
element-loading-text="拼命加载中"
:header-cell-style="headerStyle"
>
<el-table-column
align="center"
prop="warning_date"
label="预警时间"
/>
<el-table-column
align="center"
prop="object_type"
label="预警信息类型"
>
<template slot-scope="scope">
{{ warning_data_map[scope.row.object_type-1] }}
</template>
</el-table-column>
<el-table-column
align="center"
prop="object_name"
label="对象"
/>
<el-table-column
align="center"
show-overflow-tooltip
prop="warning_content"
label="内容"
/>
<el-table-column
align="center"
prop="is_solve"
label="受理情况"
>
<template slot-scope="scope">
<el-tag :type="scope.row.is_solve === 0?'warning':'success' ">
{{ scope.row.is_solve === 0 ? '未受理':'已受理' }}
</el-tag>
</template>
</el-table-column>
<el-table-column
align="center"
prop="is_solve"
label="操作"
>
<template slot-scope="scope">
<el-button type="primary" @click="optClick(scope.row)">操作</el-button>
</template>
</el-table-column>
</el-table>
<div class="my-pagination" style="text-align: center">
<el-pagination
background
layout="prev, pager, next"
:disabled="loadingReagent"
:current-page.sync="page"
:total="total"
:page-size.sync="page_size"
@current-change="pageChange"
/>
</div>
<el-dialog
width="50%"
title="预警详情"
:visible.sync="innerVisible"
append-to-body
>
<el-descriptions :column="2" border>
<el-descriptions-item label="预警对象" span="2">{{ rowData.object_name }}</el-descriptions-item>
<el-descriptions-item label="预警内容" span="2">{{ rowData.warning_content }}</el-descriptions-item>
<el-descriptions-item label="预警类型">{{ warning_data_map[rowData.object_type -1] }}</el-descriptions-item>
<el-descriptions-item label="预警来源">{{ rowData.object_name }}</el-descriptions-item>
<!-- <el-descriptions-item label="生产日期">{{ this.rowData.object_name }}</el-descriptions-item>-->
<!-- <el-descriptions-item label="过期日期">{{ this.rowData.object_name }}</el-descriptions-item>-->
<!-- <el-descriptions-item label="试剂余量">{{ this.rowData.object_name }}</el-descriptions-item>-->
<!-- <el-descriptions-item label="所属终端">{{ this.rowData.object_name }}</el-descriptions-item>-->
<el-descriptions-item label="最后使用人"><el-tag>{{ rowData.warning_user_name }}</el-tag></el-descriptions-item>
<el-descriptions-item label="受理情况">
<el-tag :type="rowData.is_solve === 0?'warning':'success' ">
{{ rowData.is_solve === 0 ? '未受理':'已受理' }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
<div style="text-align: center;margin-top: 20px">
<el-button @click="innerVisible=false">取消</el-button>
<el-button type="primary" @click="innerVisible=false"></el-button>
</div>
</el-dialog>
</el-dialog>
</div>
</template>
<script>
import Detail from '@/components/Detail/index'
import { home_info, home_warning_list, home_drug_remaining, get_monitoring_info } from '@/api/reagent/overView'
import { client_list } from '@/api/common'
import stringify from '@/utils/stringify'
export default {
name: 'MainOverview',
components: { Detail },
data() {
return {
headerStyle: { 'background': '#E6E6E6' },
loading: false,
dialogTableVisible: false,
innerVisible: false,
myChart: null,
myChart2: null,
warning_data_info: {},
warning_data_map: ['试剂临期', '试剂过期', '余量不足', '环境异常', '出库临期', '出库超期', '未称重'],
desc: [
{
count: 0,
desc: '今日入库',
img: require('@/assets/3-主概览/今日入库.png')
},
{
count: 0,
desc: '今日领用',
img: require('@/assets/3-主概览/今日领用.png')
},
{
count: 0,
desc: '今日归还',
img: require('@/assets/3-主概览/今日归还.png')
},
{
count: 0,
desc: '今日未归还',
img: require('@/assets/3-主概览/今日未归还.png')
}
],
tableData: [],
clientOptions: [],
options: ['近24小时', '近七天', '近一个月'],
value: '',
radio1: 1,
gridData: [],
seach_word: '',
page: 1,
total: 0,
page_size: 15,
start_time: '',
end_time: '',
object_type: '',
loadingReagent: false,
rowData: {},
remainingData: [],
rpage: 1,
rtotal: 0,
rpage_size: 15,
rclient_id: null,
rloading: false,
client_id: null,
client_date: 1,
linechartData: [],
loadingLineData: true
}
},
async created() {
this.loading = true
await this.initClientData()
this.getMonitoringData()
home_info().then(res => {
this.initDataFunc(res.data)
this.initAllCharts()
}).finally(() => (this.loading = false))
this.remainingPageChange(1)
},
beforeDestroy() {
window.removeEventListener('resize', () => {
this.myChart.resize()
this.myChart2.resize()
})
},
methods: {
initClientData() {
return new Promise((resolve, reject) => {
client_list().then(
res => {
this.clientOptions = res.data.data_list
this.client_id = this.clientOptions[0].client_id
this.rclient_id = this.client_id
resolve()
}
)
})
},
valueChange(t, value) {
this.getMonitoringData()
this.lineCharts(t)
},
getMonitoringData() {
const data = {
client_id: this.client_id,
time_type: this.client_date,
obj_type: this.radio1
}
this.loadingLineData = true
get_monitoring_info(stringify(data)).then(
res => {
this.linechartData = res.data
}
).finally(() => { this.loadingLineData = false })
},
remainingPageChange(page) {
this.rpage = page
this.getRemainingData()
},
getRemainingData() {
const data = {
client_id: this.rclient_id,
page: this.rpage,
page_size: this.rpage_size
}
this.rloading = true
home_drug_remaining(stringify(data)).then(res => {
this.remainingData = res.data.data
this.rtotal = res.data.total_count
}).finally(() => (this.rloading = false))
},
optClick(row) {
this.rowData = row
this.innerVisible = true
},
searchData() {
this.getWarnList()
},
getWarnList() {
const data = {
'seach_word': this.seach_word,
'object_type': this.object_type,
'start_time': this.start_time,
'end_time': this.end_time,
'page': this.page,
'page_size': this.page_size
}
this.loadingReagent = true
home_warning_list(stringify(data)).then(res => {
this.gridData = res.data.data_list
this.total = res.data.total_count
}).finally(() => (this.loadingReagent = false))
},
pageChange(page) {
this.page = page
this.getWarnList()
},
initDataFunc(data) {
const { new_day_record_number, warning_data_info, warning_list } = data
const nowstore = new_day_record_number.find(item => item.record_type === 1)
const nowget = new_day_record_number.find(item => item.record_type === 2)
const nowsend = new_day_record_number.find(item => item.record_type === 3)
const nowno = new_day_record_number.find(item => item.record_type === 100)
if (nowstore) {
this.desc[0].count = nowstore.type_number
}
if (nowget) {
this.desc[1].count = nowget.type_number
}
if (nowsend) {
this.desc[2].count = nowsend.type_number
}
if (nowno) {
this.desc[3].count = nowno.type_number
}
this.warning_data_info = warning_data_info
this.tableData = warning_list
},
initAllCharts() {
this.getLoadEcharts()
this.lineCharts()
window.addEventListener('resize', () => {
// 第六步执行echarts自带的resize方法即可做到让echarts图表自适应
this.myChart.resize()
this.myChart2.resize()
})
},
format(percentage) {
return `${percentage / 100}%`
},
warnAll() {
this.dialogTableVisible = true
// 拉去数据
this.getWarnList()
},
getLoadEcharts() {
this.myChart = this.$echarts.init(
document.getElementById('pie')
)
const data = this.warning_data_info.data_list.map(item => {
item.name = this.warning_data_map[item.object_type - 1]
item.value = item.type_number
return item
})
const option = {
series: [
{
name: 'Nightingale Chart',
type: 'pie',
radius: [8, 60],
roseType: 'area',
label: {
normal: {
show: true,
formatter: '{b}:{d}%'
}
},
data
}
]
}
this.myChart.setOption(option)
},
lineCharts(t) {
if (t) {
this.myChart2.clear()
} else {
this.myChart2 = this.$echarts.init(
document.getElementById('line')
)
}
const raOption = ['温度', '湿度', 'VOC含量']
const tmp = ['°C', 'RH%', 'ppm']
const option = {
title: {
text: this.options[this.client_date - 1] + raOption[this.radio1 - 1] + '变化'
},
tooltip: {
trigger: 'axis'
},
legend: {},
toolbox: {
show: true,
feature: {
magicType: { type: ['line', 'bar'] },
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: this.linechartData.map(item => item.record_date)
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value} ' + tmp[[this.radio1 - 1]]
}
},
series: [
{
name: this.clientOptions.find(item => item.client_id === this.client_id).client_name,
type: 'line',
areaStyle: {},
smooth: true,
data: this.linechartData.map(item => item.data_value),
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' }
]
},
markLine: {
data: [{ type: 'average', name: 'Avg' }]
}
}
]
}
this.myChart2.setOption(option)
}
}
}
</script>
<style lang="scss" scoped>
.view-container {
margin: 1rem;
.view-container-top {
display: flex;
margin-bottom: 1rem;
.view-container-tl {
width: 66%;
margin-right: 1rem;
.view-container-tlt {
padding-bottom: 1rem;
display: flex;
justify-content: space-between;
}
}
.view-container-tr {
width: 33%;
background-color: white;
}
}
.view-container-bottom {
display: flex;
.view-container-bl {
width: 66%;
background-color: white;
margin-right: 1rem;
}
.view-container-br {
width: 33%;
background-color: white;
}
}
}
.view {
height: 14rem;
width: 33.75rem;
}
.header {
display: flex;
margin-bottom: 0.5rem;
justify-content: space-between;
align-items: center;
.el-input{
width: 150px;
}
.el-select {
margin-right: 1rem;
}
.title {
font-size: 20px;
font-weight: bold;
color: #303133;
}
}
.data-progress {
margin-top: 1rem;
width: 93%;
.data-progress-header {
display: flex;
justify-content: space-between;
}
}
.header-warn{
.title {
font-size: 20px;
font-weight: bold;
color: #303133;
}
.count{
font-size: 36px;
font-weight: bold;
color: #303133;
margin-top: 3rem;
}
.desc{
font-size: 14px;
font-weight: 400;
color: #606266;
}
}
.view-content{
padding: 1rem;
background-color: white;
}
#pie{
width: 30rem;
height: 18rem;
}
#line{
width: 65rem;
height: 15.25rem;
}
.header-custom{
margin-bottom: 1rem;
.el-input{
width: 12.5rem;
margin-right: 1rem;
}
.el-select{
margin-right: 1rem;
}
}
</style>