699 lines
20 KiB
Vue
699 lines
20 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="roller-page" v-loading="loading">
|
|||
|
|
<el-row :gutter="12" style="height: 90vh;">
|
|||
|
|
<!-- 历史记录表格区域 -->
|
|||
|
|
<el-col :span="18" class="panel-col" style="height: 100%;">
|
|||
|
|
<div class="panel-card">
|
|||
|
|
<div class="history-container">
|
|||
|
|
<div class="history-table" ref="historyWrapper" @mouseleave="handleTableLeave">
|
|||
|
|
<el-table
|
|||
|
|
:data="tableData"
|
|||
|
|
border
|
|||
|
|
stripe
|
|||
|
|
class="compact-table"
|
|||
|
|
height="70vh"
|
|||
|
|
:show-overflow-tooltip="true"
|
|||
|
|
@cell-mouse-enter="handleCellEnter"
|
|||
|
|
@row-mouseleave="handleRowLeave"
|
|||
|
|
>
|
|||
|
|
<el-table-column prop="changeid" label="换辊号" align="center" show-overflow-tooltip />
|
|||
|
|
<el-table-column prop="rollid" label="轧辊号" align="center" show-overflow-tooltip />
|
|||
|
|
<el-table-column prop="standid" label="机架号" align="center" show-overflow-tooltip />
|
|||
|
|
<el-table-column label="位置" align="center" prop="position">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<dict-tag :options="dict.type.main_roll_position" :value="scope.row.position" />
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column label="类型" align="center" prop="type">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<dict-tag :options="dict.type.main_roll_type" :value="scope.row.type" />
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column prop="changeType" label="换辊类型" align="center" show-overflow-tooltip />
|
|||
|
|
<el-table-column prop="changeTime" label="换辊时间" align="center" show-overflow-tooltip />
|
|||
|
|
<el-table-column prop="instalTime" label="安装时间" align="center" show-overflow-tooltip />
|
|||
|
|
<el-table-column prop="deinstalTime" label="拆卸时间" align="center" show-overflow-tooltip />
|
|||
|
|
</el-table>
|
|||
|
|
<transition name="el-fade-in-linear">
|
|||
|
|
<div
|
|||
|
|
v-if="tooltipVisible && hoveredRow"
|
|||
|
|
class="row-tooltip"
|
|||
|
|
:style="tooltipStyle"
|
|||
|
|
ref="rowTooltip"
|
|||
|
|
>
|
|||
|
|
<div class="tooltip-title">详细信息</div>
|
|||
|
|
<div class="tooltip-list">
|
|||
|
|
<div
|
|||
|
|
class="tooltip-item"
|
|||
|
|
v-for="field in detailFields"
|
|||
|
|
:key="field.prop"
|
|||
|
|
>
|
|||
|
|
<span class="label">{{ field.label }}:</span>
|
|||
|
|
<span class="value">{{ formatTooltipValue(hoveredRow, field) }}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</transition>
|
|||
|
|
</div>
|
|||
|
|
<el-pagination
|
|||
|
|
v-show="pagination.total>0"
|
|||
|
|
:total="pagination.total"
|
|||
|
|
v-model:current-page="pagination.currentPage"
|
|||
|
|
v-model:page-size="pagination.pageSize"
|
|||
|
|
@current-change="getList"
|
|||
|
|
@size-change="handleSizeChange"
|
|||
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</el-col>
|
|||
|
|
|
|||
|
|
<!-- 筛选条件区域 -->
|
|||
|
|
<el-col :span="6" class="panel-col" style="height: 100%;">
|
|||
|
|
<div class="panel-card">
|
|||
|
|
<div class="filter-container">
|
|||
|
|
<div class="filter-panel">
|
|||
|
|
<div class="panel-header">
|
|||
|
|
<h4>历史检索</h4>
|
|||
|
|
</div>
|
|||
|
|
<div class="filter-item">
|
|||
|
|
<div class="filter-label">• 按时间</div>
|
|||
|
|
<div class="filter-content time-range">
|
|||
|
|
<div class="time-label">开始时间:</div>
|
|||
|
|
<el-date-picker
|
|||
|
|
v-model="startDate"
|
|||
|
|
type="date"
|
|||
|
|
placeholder="选择日期"
|
|||
|
|
value-format="yyyy-MM-dd"
|
|||
|
|
style="width: 140px"
|
|||
|
|
></el-date-picker>
|
|||
|
|
<el-time-picker
|
|||
|
|
v-model="startTime"
|
|||
|
|
format="HH:mm"
|
|||
|
|
placeholder="选择时间"
|
|||
|
|
value-format="HH:mm"
|
|||
|
|
style="width: 140px; margin-left: 5px"
|
|||
|
|
></el-time-picker>
|
|||
|
|
|
|||
|
|
<div class="time-label" style="margin-top: 10px">结束时间:</div>
|
|||
|
|
<el-date-picker
|
|||
|
|
v-model="endDate"
|
|||
|
|
type="date"
|
|||
|
|
placeholder="选择日期"
|
|||
|
|
value-format="yyyy-MM-dd"
|
|||
|
|
style="width: 140px"
|
|||
|
|
></el-date-picker>
|
|||
|
|
<el-time-picker
|
|||
|
|
v-model="endTime"
|
|||
|
|
format="HH:mm"
|
|||
|
|
placeholder="选择时间"
|
|||
|
|
value-format="HH:mm"
|
|||
|
|
style="width: 140px; margin-left: 5px"
|
|||
|
|
></el-time-picker>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="filter-item">
|
|||
|
|
<div class="filter-label">• 按换辊号</div>
|
|||
|
|
<div class="filter-content">
|
|||
|
|
<div class="input-label">换辊号:</div>
|
|||
|
|
<el-select filterable v-model="queryParams.changeId" placeholder="请选择" clearable style="width: 240px">
|
|||
|
|
<el-option
|
|||
|
|
v-for="item in changeIdOptions"
|
|||
|
|
:key="item"
|
|||
|
|
:label="item"
|
|||
|
|
:value="item"
|
|||
|
|
></el-option>
|
|||
|
|
</el-select>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="filter-item">
|
|||
|
|
<div class="filter-label">• 按轧辊号</div>
|
|||
|
|
<div class="filter-content">
|
|||
|
|
<div class="input-label">轧辊号:</div>
|
|||
|
|
<el-select filterable v-model="queryParams.rollId" placeholder="请选择" clearable style="width: 240px">
|
|||
|
|
<el-option
|
|||
|
|
v-for="item in rollIdOptions"
|
|||
|
|
:key="item"
|
|||
|
|
:label="item"
|
|||
|
|
:value="item"
|
|||
|
|
></el-option>
|
|||
|
|
</el-select>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="filter-buttons">
|
|||
|
|
<el-button type="primary" @click="handleSearch">查 询</el-button>
|
|||
|
|
<el-button @click="resetQuery">重 置</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import createFetch from '@/api/l2/roller'
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
name: 'Roller',
|
|||
|
|
dicts: ['main_roll_type','main_roll_position'],
|
|||
|
|
props: {
|
|||
|
|
baseURL: {
|
|||
|
|
type: String,
|
|||
|
|
default: '140.143.206.120:18081'
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
// 原有父组件数据
|
|||
|
|
onlineData: [],
|
|||
|
|
loading: false,
|
|||
|
|
historyParams: {},
|
|||
|
|
|
|||
|
|
// FilterVue 组件数据
|
|||
|
|
activeUrl: '140.143.206.120:18081',
|
|||
|
|
queryParams: {
|
|||
|
|
changeId: '',
|
|||
|
|
rollId: ''
|
|||
|
|
},
|
|||
|
|
startDate: '',
|
|||
|
|
startTime: '',
|
|||
|
|
endDate: '',
|
|||
|
|
endTime: '',
|
|||
|
|
changeIdOptions: [],
|
|||
|
|
rollIdOptions: [],
|
|||
|
|
rollerApi: undefined,
|
|||
|
|
|
|||
|
|
// History 组件数据
|
|||
|
|
tableData: [],
|
|||
|
|
pagination: {
|
|||
|
|
currentPage: 1,
|
|||
|
|
pageSize: 15,
|
|||
|
|
total: 0
|
|||
|
|
},
|
|||
|
|
tooltipVisible: false,
|
|||
|
|
tooltipStyle: {
|
|||
|
|
top: '0px',
|
|||
|
|
left: '0px'
|
|||
|
|
},
|
|||
|
|
hoveredRow: null,
|
|||
|
|
searching: false,
|
|||
|
|
searchForm: {
|
|||
|
|
changeId: '',
|
|||
|
|
rollId: '',
|
|||
|
|
changeTimeRange: [],
|
|||
|
|
instalTimeRange: [],
|
|||
|
|
deinstalTimeRange: []
|
|||
|
|
},
|
|||
|
|
detailFields: [
|
|||
|
|
{ label: '换辊号', prop: 'changeid' },
|
|||
|
|
{ label: '轧辊号', prop: 'rollid' },
|
|||
|
|
{ label: '机架号', prop: 'standid' },
|
|||
|
|
{ label: '位置', prop: 'position', dict: 'main_roll_position' },
|
|||
|
|
{ label: '类型', prop: 'type', dict: 'main_roll_type' },
|
|||
|
|
{ label: '换辊类型', prop: 'changeType' },
|
|||
|
|
{ label: '换辊时间', prop: 'changeTime' },
|
|||
|
|
{ label: '安装时间', prop: 'instalTime' },
|
|||
|
|
{ label: '拆卸时间', prop: 'deinstalTime' },
|
|||
|
|
{ label: '直径', prop: 'diameter' },
|
|||
|
|
{ label: '粗糙度', prop: 'rough' },
|
|||
|
|
{ label: '凸度', prop: 'crown' },
|
|||
|
|
{ label: '成分', prop: 'composition' },
|
|||
|
|
{ label: '磨削次数', prop: 'grindCount' },
|
|||
|
|
{ label: '轧制重量', prop: 'rolledWeight' },
|
|||
|
|
{ label: '轧制数量', prop: 'rolledCount' },
|
|||
|
|
{ label: '轧制长度', prop: 'rolledLength' },
|
|||
|
|
{ label: '总轧制重量', prop: 'totalRolledWeight' },
|
|||
|
|
{ label: '总轧制长度', prop: 'totalRolledLength' },
|
|||
|
|
{ label: '总轧制数量', prop: 'totalRolledCount' }
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
watch: {
|
|||
|
|
baseURL: {
|
|||
|
|
handler(newVal, oldVal) {
|
|||
|
|
if (newVal !== oldVal) {
|
|||
|
|
this.rollerApi = createFetch(newVal)
|
|||
|
|
this.getChangeIdOptions()
|
|||
|
|
this.getRollIdOptions()
|
|||
|
|
this.setDefaultTimeRange()
|
|||
|
|
this.fetchHistoryData()
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
immediate: true
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
setHistoryParams(params) {
|
|||
|
|
console.log(params, 'params,setHistoryParams');
|
|||
|
|
this.historyParams = params
|
|||
|
|
// 触发数据查询
|
|||
|
|
this.pagination.currentPage = 1
|
|||
|
|
this.fetchHistoryData()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// ========== FilterVue 组件方法 ==========
|
|||
|
|
getChangeIdOptions() {
|
|||
|
|
this.rollerApi.getChangeIdList().then(res => {
|
|||
|
|
console.log('换辊号列表响应:', res)
|
|||
|
|
if (res.code === 200 && res.data) {
|
|||
|
|
this.changeIdOptions = res.data
|
|||
|
|
} else {
|
|||
|
|
this.$message.error(res.msg || '获取换辊号列表失败')
|
|||
|
|
}
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error('获取换辊号列表失败', error)
|
|||
|
|
this.$message.error('获取换辊号列表失败:' + (error.message || '未知错误'))
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getRollIdOptions() {
|
|||
|
|
this.rollerApi.getRollIdList().then(res => {
|
|||
|
|
console.log('轧辊号列表响应:', res)
|
|||
|
|
if (res.code === 200 && res.data) {
|
|||
|
|
this.rollIdOptions = res.data
|
|||
|
|
} else {
|
|||
|
|
this.$message.error(res.msg || '获取轧辊号列表失败')
|
|||
|
|
}
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error('获取轧辊号列表失败', error)
|
|||
|
|
this.$message.error('获取轧辊号列表失败:' + (error.message || '未知错误'))
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
formatDateStr(date) {
|
|||
|
|
const year = date.getFullYear()
|
|||
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|||
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|||
|
|
return `${year}-${month}-${day}`
|
|||
|
|
},
|
|||
|
|
formatTimeStr(date) {
|
|||
|
|
const hours = String(date.getHours()).padStart(2, '0')
|
|||
|
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
|||
|
|
return `${hours}:${minutes}`
|
|||
|
|
},
|
|||
|
|
setDefaultTimeRange() {
|
|||
|
|
this.startDate = '2020-01-01'
|
|||
|
|
this.startTime = '10:00'
|
|||
|
|
this.setEndToNow()
|
|||
|
|
},
|
|||
|
|
setEndToNow() {
|
|||
|
|
const now = new Date()
|
|||
|
|
this.endDate = this.formatDateStr(now)
|
|||
|
|
this.endTime = this.formatTimeStr(now)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleSearch() {
|
|||
|
|
this.setEndToNow()
|
|||
|
|
// 构建搜索参数
|
|||
|
|
const params = {
|
|||
|
|
startTime: `${this.startDate} ${this.startTime}:00`,
|
|||
|
|
endTime: `${this.endDate} ${this.endTime}:00`,
|
|||
|
|
changeId: this.queryParams.changeId || '',
|
|||
|
|
rollid: this.queryParams.rollId || ''
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('搜索参数:', params)
|
|||
|
|
this.historyParams = params
|
|||
|
|
this.pagination.currentPage = 1
|
|||
|
|
this.fetchHistoryData()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
resetQuery() {
|
|||
|
|
this.queryParams = {
|
|||
|
|
changeId: '',
|
|||
|
|
rollId: ''
|
|||
|
|
}
|
|||
|
|
this.setDefaultTimeRange()
|
|||
|
|
this.historyParams = {}
|
|||
|
|
this.pagination.currentPage = 1
|
|||
|
|
this.fetchHistoryData()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// ========== History 组件方法 ==========
|
|||
|
|
fetchHistoryData() {
|
|||
|
|
const requestBody = {
|
|||
|
|
...this.historyParams,
|
|||
|
|
...this.buildSearchParams(),
|
|||
|
|
pageNum: this.pagination.currentPage,
|
|||
|
|
pageSize: this.pagination.pageSize
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const loading = this.$loading({
|
|||
|
|
lock: true,
|
|||
|
|
text: '加载中...',
|
|||
|
|
spinner: 'el-icon-loading',
|
|||
|
|
background: 'rgba(0, 0, 0, 0.7)'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return this.rollerApi.getRollHistorytList(requestBody)
|
|||
|
|
.then(res => {
|
|||
|
|
if (res.code === 200 && res.data) {
|
|||
|
|
this.tableData = res.data.list || []
|
|||
|
|
this.pagination.total = res.data.total || 0
|
|||
|
|
this.pagination.currentPage = res.data.pageNum || 1
|
|||
|
|
|
|||
|
|
this.tableData.forEach(item => {
|
|||
|
|
if (item.changeTime) item.changeTime = this.formatDate(item.changeTime)
|
|||
|
|
if (item.instalTime) item.instalTime = this.formatDate(item.instalTime)
|
|||
|
|
if (item.deinstalTime) item.deinstalTime = this.formatDate(item.deinstalTime)
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
this.$message.error(res.msg || '获取数据失败')
|
|||
|
|
this.tableData = []
|
|||
|
|
this.pagination.total = 0
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.catch(error => {
|
|||
|
|
console.error('获取轧辊历史数据失败', error)
|
|||
|
|
this.$message.error('获取数据失败:' + (error.message || '未知错误'))
|
|||
|
|
this.tableData = []
|
|||
|
|
this.pagination.total = 0
|
|||
|
|
})
|
|||
|
|
.finally(() => {
|
|||
|
|
loading.close()
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
formatDate(dateStr) {
|
|||
|
|
if (!dateStr) return ''
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const date = new Date(dateStr)
|
|||
|
|
const year = date.getFullYear()
|
|||
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|||
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|||
|
|
const hours = String(date.getHours()).padStart(2, '0')
|
|||
|
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
|||
|
|
const seconds = String(date.getSeconds()).padStart(2, '0')
|
|||
|
|
|
|||
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
|||
|
|
} catch (error) {
|
|||
|
|
return dateStr
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getList() {
|
|||
|
|
this.fetchHistoryData()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleSizeChange(pageSize) {
|
|||
|
|
this.pagination.pageSize = pageSize
|
|||
|
|
this.fetchHistoryData()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
buildSearchParams() {
|
|||
|
|
const params = {}
|
|||
|
|
if (this.searchForm.changeId) {
|
|||
|
|
params.changeId = this.searchForm.changeId
|
|||
|
|
}
|
|||
|
|
if (this.searchForm.rollId) {
|
|||
|
|
params.rollid = this.searchForm.rollId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const [changeStart, changeEnd] = this.searchForm.changeTimeRange || []
|
|||
|
|
if (changeStart && changeEnd) {
|
|||
|
|
params.changeTimeBegin = changeStart
|
|||
|
|
params.changeTimeEnd = changeEnd
|
|||
|
|
}
|
|||
|
|
const [instalStart, instalEnd] = this.searchForm.instalTimeRange || []
|
|||
|
|
if (instalStart && instalEnd) {
|
|||
|
|
params.instalTimeBegin = instalStart
|
|||
|
|
params.instalTimeEnd = instalEnd
|
|||
|
|
}
|
|||
|
|
const [deinstalStart, deinstalEnd] = this.searchForm.deinstalTimeRange || []
|
|||
|
|
if (deinstalStart && deinstalEnd) {
|
|||
|
|
params.deinstalTimeBegin = deinstalStart
|
|||
|
|
params.deinstalTimeEnd = deinstalEnd
|
|||
|
|
}
|
|||
|
|
return params
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleCellEnter(row, column, cell, event) {
|
|||
|
|
if (!row || !event) return
|
|||
|
|
this.hoveredRow = row
|
|||
|
|
this.tooltipVisible = true
|
|||
|
|
this.updateTooltipPosition(event)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleRowLeave() {
|
|||
|
|
this.tooltipVisible = false
|
|||
|
|
this.hoveredRow = null
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleTableLeave() {
|
|||
|
|
this.tooltipVisible = false
|
|||
|
|
this.hoveredRow = null
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
updateTooltipPosition(event) {
|
|||
|
|
this.$nextTick(() => {
|
|||
|
|
const wrapper = this.$refs.historyWrapper
|
|||
|
|
const tooltipEl = this.$refs.rowTooltip
|
|||
|
|
if (!wrapper || !tooltipEl) return
|
|||
|
|
|
|||
|
|
const wrapperRect = wrapper.getBoundingClientRect()
|
|||
|
|
const tooltipRect = tooltipEl.getBoundingClientRect()
|
|||
|
|
let left = event.clientX - wrapperRect.left + 16
|
|||
|
|
let top = event.clientY - wrapperRect.top + 12
|
|||
|
|
|
|||
|
|
if (left + tooltipRect.width > wrapperRect.width) {
|
|||
|
|
left = wrapperRect.width - tooltipRect.width - 8
|
|||
|
|
}
|
|||
|
|
if (left < 8) left = 8
|
|||
|
|
if (top + tooltipRect.height > wrapperRect.height) {
|
|||
|
|
top = wrapperRect.height - tooltipRect.height - 8
|
|||
|
|
}
|
|||
|
|
if (top < 8) top = 8
|
|||
|
|
|
|||
|
|
this.tooltipStyle = {
|
|||
|
|
top: `${top}px`,
|
|||
|
|
left: `${left}px`
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
formatTooltipValue(row, field) {
|
|||
|
|
const value = row[field.prop]
|
|||
|
|
if (value === null || value === undefined || value === '') {
|
|||
|
|
return '-'
|
|||
|
|
}
|
|||
|
|
if (field.dict && this.dict && this.dict.type && this.dict.type[field.dict]) {
|
|||
|
|
const match = this.dict.type[field.dict].find(item => item.value === value)
|
|||
|
|
return match ? match.label : value
|
|||
|
|
}
|
|||
|
|
return value
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.roller-page {
|
|||
|
|
padding: 15px 20px 20px;
|
|||
|
|
background: #f5f5f5;
|
|||
|
|
min-height: calc(100vh - 84px);
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.panel-row {
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
align-items: stretch;
|
|||
|
|
|
|||
|
|
&:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.panel-col {
|
|||
|
|
display: flex;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.panel-card {
|
|||
|
|
background: #ffffff;
|
|||
|
|
border: 1px solid #dcdcdc;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
padding: 12px 0;
|
|||
|
|
width: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
height: 100%;
|
|||
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tall-panel {
|
|||
|
|
height: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bottom-row .panel-card {
|
|||
|
|
min-height: 360px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Filter 组件样式
|
|||
|
|
.filter-container {
|
|||
|
|
height: 100%;
|
|||
|
|
padding: 0;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
|
|||
|
|
.filter-panel {
|
|||
|
|
flex: 1;
|
|||
|
|
padding: 15px;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.panel-header {
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
|
|||
|
|
h4 {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.filter-item {
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
|
|||
|
|
.filter-label {
|
|||
|
|
font-weight: bold;
|
|||
|
|
margin-bottom: 10px;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.filter-content {
|
|||
|
|
padding-left: 15px;
|
|||
|
|
|
|||
|
|
.input-label {
|
|||
|
|
margin-bottom: 5px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-range {
|
|||
|
|
.time-label {
|
|||
|
|
margin-bottom: 5px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.filter-buttons {
|
|||
|
|
text-align: center;
|
|||
|
|
|
|||
|
|
.el-button {
|
|||
|
|
width: 100px;
|
|||
|
|
margin: 0 10px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// History 组件样式
|
|||
|
|
.history-container {
|
|||
|
|
border-radius: 4px;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
height: 100%;
|
|||
|
|
min-height: 0;
|
|||
|
|
|
|||
|
|
.history-search-panel {
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
background: #ffffff;
|
|||
|
|
|
|||
|
|
.history-form {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
align-items: flex-end;
|
|||
|
|
gap: 8px 12px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.history-table {
|
|||
|
|
flex: 1;
|
|||
|
|
overflow: hidden;
|
|||
|
|
position: relative;
|
|||
|
|
margin-bottom: 10px;
|
|||
|
|
background: #ffffff;
|
|||
|
|
|
|||
|
|
.compact-table {
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pagination-container {
|
|||
|
|
margin: 10px 0;
|
|||
|
|
text-align: right;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.button-container {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
padding: 10px 0;
|
|||
|
|
|
|||
|
|
.el-button + .el-button {
|
|||
|
|
margin-left: 20px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
::v-deep .el-table th,
|
|||
|
|
::v-deep .el-table td {
|
|||
|
|
white-space: nowrap;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.row-tooltip {
|
|||
|
|
position: absolute;
|
|||
|
|
background: #ffffff;
|
|||
|
|
border: 1px solid #dcdcdc;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|||
|
|
padding: 12px 14px;
|
|||
|
|
pointer-events: none;
|
|||
|
|
z-index: 5;
|
|||
|
|
max-height: 70%;
|
|||
|
|
overflow: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tooltip-title {
|
|||
|
|
font-size: 13px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #333;
|
|||
|
|
margin-bottom: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tooltip-list {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|||
|
|
gap: 6px 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tooltip-item {
|
|||
|
|
font-size: 12px;
|
|||
|
|
display: flex;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
|
|||
|
|
.label {
|
|||
|
|
color: #666;
|
|||
|
|
margin-right: 4px;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.value {
|
|||
|
|
flex: 1;
|
|||
|
|
color: #333;
|
|||
|
|
font-weight: 500;
|
|||
|
|
word-break: break-all;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|