refactor(steelGrade): 重构钢种管理页面布局和交互

feat(roller): 调整轧辊页面布局并移除标准组件

style(pdo): 修改操作按钮样式为文本类型

chore: 更新pnpm-lock.yaml文件依赖配置
This commit is contained in:
砂糖
2025-12-16 13:25:49 +08:00
parent 133d41c4e5
commit 8a31475852
8 changed files with 316 additions and 258 deletions

View File

@@ -82,6 +82,6 @@ export function getSteelGradeInfo(gradeid) {
export function deleteSteelGrade(id) {
return l2Request({
method: 'delete',
url: `/l2-api/api/steelGrade/delete/${id}`
url: `/api/steelGrade/delete/${id}`
})
}

View File

@@ -121,13 +121,13 @@
<div class="card-footer">
<el-button
size="mini"
type="primary"
type="text"
icon="el-icon-edit"
@click.stop="handleEdit(item)"
>操作</el-button>
<el-button
size="mini"
type="danger"
type="text"
icon="el-icon-delete"
:loading="item.deleteLoading"
@click.stop="handleDelete(item)"

View File

@@ -32,6 +32,10 @@
<el-table-column prop="rolledWeight" label="重量" show-overflow-tooltip />
<el-table-column prop="rolledCount" label="轧制数量" show-overflow-tooltip />
<el-table-column prop="instalTime" label="装机时间" show-overflow-tooltip />
<!-- <el-table-column prop="usableLength" label="可用长度" show-overflow-tooltip />
<el-table-column prop="leftLength" label="剩余长度" show-overflow-tooltip />
<el-table-column prop="usableWeight" label="可用重量" show-overflow-tooltip />
<el-table-column prop="leftWeight" label="剩余重量" show-overflow-tooltip /> -->
</el-table>
</div>
</template>

View File

@@ -1,82 +0,0 @@
<!-- 换坤标准props接收在线辊的表格数据 -->
<template>
<div class="standard-roll">
<div class="panel-header">
<h4>换辊标准</h4>
</div>
<el-table
:data="onlineData"
border
stripe
size="mini"
class="compact-table"
v-loading="loading"
:show-overflow-tooltip="true"
header-align="center"
align="center"
style="width: 100%; table-layout: fixed;"
>
<el-table-column prop="usableLength" label="可用长度" show-overflow-tooltip />
<el-table-column prop="leftLength" label="剩余长度" show-overflow-tooltip />
<el-table-column prop="usableWeight" label="可用重量" show-overflow-tooltip />
<el-table-column prop="leftWeight" label="剩余重量" show-overflow-tooltip />
</el-table>
</div>
</template>
<script>
export default {
name: "Standard",
props: {
onlineData: {
type: Array,
default: () => []
}
},
data() {
return {
loading: false
}
},
watch: {
onlineData: {
handler() {
this.loading = false
},
immediate: true
}
}
}
</script>
<style scoped lang="scss">
.standard-roll {
display: flex;
flex-direction: column;
height: 100%;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
h4 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #333;
}
}
.compact-table {
width: 100%;
}
::v-deep .el-table th,
::v-deep .el-table td {
text-align: center;
white-space: nowrap;
}
</style>

View File

@@ -17,12 +17,12 @@
:show-overflow-tooltip="true"
style="width: 100%; table-layout: fixed;"
>
<el-table-column fixed="left" label="位置/类型" min-width="130" show-overflow-tooltip>
<el-table-column label="位置/类型" show-overflow-tooltip>
<template #default="scope">
{{ getRollerTitle(scope.row.type, scope.row.position) }}
</template>
</el-table-column>
<el-table-column prop="rollid" label="轧辊号" min-width="150" show-overflow-tooltip>
<el-table-column prop="rollid" label="轧辊号" show-overflow-tooltip>
<template #default="scope">
<el-select
size="mini"
@@ -30,6 +30,7 @@
clearable
allow-create
v-model="scope.row.rollid"
style="width: 100%;"
placeholder="请选择轧辊号"
@change="handleChange(scope.row)"
>
@@ -37,19 +38,19 @@
</el-select>
</template>
</el-table-column>
<el-table-column prop="diameter" label="直径" min-width="110" show-overflow-tooltip>
<el-table-column prop="diameter" label="直径" show-overflow-tooltip>
<template #default="scope">
<el-input size="mini" :disabled="!scope.row.rollid" v-model="scope.row.diameter" placeholder="请输入直径" />
<el-input style="width: 100%;" size="mini" :disabled="!scope.row.rollid" v-model="scope.row.diameter" placeholder="请输入直径" />
</template>
</el-table-column>
<el-table-column prop="rough" label="粗糙度" min-width="110" show-overflow-tooltip>
<el-table-column prop="rough" label="粗糙度" show-overflow-tooltip>
<template #default="scope">
<el-input size="mini" :disabled="!scope.row.rollid" v-model="scope.row.rough" placeholder="请输入粗糙度" />
<el-input style="width: 100%;" size="mini" :disabled="!scope.row.rollid" v-model="scope.row.rough" placeholder="请输入粗糙度" />
</template>
</el-table-column>
<el-table-column prop="crown" label="凹度" min-width="110" show-overflow-tooltip>
<el-table-column prop="crown" label="凹度" show-overflow-tooltip>
<template #default="scope">
<el-input size="mini" :disabled="!scope.row.rollid" v-model="scope.row.crown" placeholder="请输入凹度" />
<el-input style="width: 100%;" size="mini" :disabled="!scope.row.rollid" v-model="scope.row.crown" placeholder="请输入凹度" />
</template>
</el-table-column>
</el-table>

View File

@@ -1,21 +1,16 @@
<template>
<div class="roller-page" v-loading="loading">
<el-row class="panel-row">
<el-col :span="7">
<el-col :span="8">
<div class="panel-card tall-panel">
<Standby :onlineData="onlineData" @online="fetchData" />
</div>
</el-col>
<el-col :span="12">
<el-col :span="16">
<div class="panel-card tall-panel">
<Online :onlineData="onlineData" />
</div>
</el-col>
<el-col :span="5">
<div class="panel-card tall-panel">
<Standard :onlineData="onlineData" />
</div>
</el-col>
</el-row>
<el-row :gutter="12" style="height: 520px;">
@@ -37,7 +32,6 @@
import FilterVue from './components/filter.vue'
import History from './components/history.vue'
import Online from './components/online.vue'
import Standard from './components/standard.vue'
import Standby from './components/standby.vue'
import { getRollHistorytList, getOnlineRollList } from '@/api/l2/roller'
@@ -48,7 +42,6 @@ export default {
FilterVue,
History,
Online,
Standard,
Standby
},
data() {
@@ -115,7 +108,7 @@ export default {
background: #ffffff;
border: 1px solid #dcdcdc;
border-radius: 4px;
padding: 12px;
padding: 12px 0;
width: 100%;
display: flex;
flex-direction: column;

View File

@@ -1,85 +1,141 @@
<template>
<div class="steel-grade-management">
<!-- 1. 顶部搜索区域自定义容器无el-card -->
<div class="search-container">
<el-form
:inline="true"
:model="queryForm"
ref="queryForm"
label-width="100px"
class="search-form"
>
<el-form-item label="钢种名称" prop="name">
<el-input
size="mini"
v-model="queryForm.name"
placeholder="请输入钢种名称"
clearable
@clear="handleReset"
></el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="handleQuery"
:loading="btnLoading"
icon="el-icon-search"
size="mini"
>查询</el-button>
<el-button
@click="handleReset"
icon="el-icon-refresh"
size="mini"
>重置</el-button>
<el-button
type="success"
@click="handleAdd"
icon="el-icon-plus"
size="mini"
>新增钢种</el-button>
</el-form-item>
</el-form>
</div>
<!-- 整体布局左侧卡片列表 + 右侧明细面板 -->
<div class="layout-container">
<!-- 左侧搜索+卡片列表 -->
<div class="left-panel">
<!-- 顶部搜索区域 -->
<div class="search-container">
<el-form
:inline="true"
:model="queryForm"
ref="queryForm"
label-width="0"
class="search-form"
>
<el-form-item prop="name">
<el-input
size="mini"
v-model="queryForm.name"
placeholder="请输入钢种名称"
clearable
@clear="handleReset"
></el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="handleQuery"
:loading="btnLoading"
icon="el-icon-search"
size="mini"
>查询</el-button>
<el-button
@click="handleReset"
icon="el-icon-refresh"
size="mini"
>重置</el-button>
<el-button
type="success"
@click="handleAdd"
icon="el-icon-plus"
size="mini"
>新增钢种</el-button>
</el-form-item>
</el-form>
</div>
<!-- 2. 钢种数据列表自定义卡片仅展示gradeid和name -->
<div class="card-list-container" v-loading="tableLoading">
<!-- 无数据提示 -->
<div class="empty-tip" v-if="tableData.length === 0 && !tableLoading">
<el-empty description="暂无钢种数据"></el-empty>
<!-- 钢种卡片列表 -->
<div class="card-list-container" v-loading="tableLoading">
<!-- 无数据提示 -->
<div class="empty-tip" v-if="tableData.length === 0 && !tableLoading">
<el-empty description="暂无钢种数据"></el-empty>
</div>
<!-- 循环渲染紧凑卡片 -->
<div
class="steel-grade-card"
v-for="(item) in tableData"
:class="{ active: (selectedItem && selectedItem.gradeid) === item.gradeid }"
@click="handleCardClick(item)"
>
<!-- 卡片第一行钢种名称 # ID -->
<div class="card-row row1">
<span class="grade-name">{{ item.name }}</span>
<span class="grade-id">#{{ item.gradeid }}</span>
</div>
<!-- 卡片第二行插入日期 + 操作按钮 -->
<div class="card-row row2">
<span class="ins-date">{{ parseTime(item.insDate, '{y}-{m}-{d}') }}</span>
<div class="card-actions">
<el-button
size="mini"
type="text"
@click.stop="handleEdit(item)"
icon="el-icon-edit"
>编辑</el-button>
<el-button
size="mini"
type="text"
@click.stop="handleDelete(item)"
:loading="item.deleteLoading"
icon="el-icon-delete"
>删除</el-button>
</div>
</div>
</div>
</div>
</div>
<!-- 循环渲染自定义卡片替代el-card -->
<el-card
style="width: 220px;"
v-for="(item, index) in tableData"
:key="index + item.gradeid"
>
<!-- 卡片内容仅展示接口返回的2个字段 -->
<el-descriptions :column="1">
<el-descriptions-item label="钢种ID">{{ item.gradeid }}</el-descriptions-item>
<el-descriptions-item label="钢种名称">{{ item.name }}</el-descriptions-item>
</el-descriptions>
<!-- 卡片操作按钮 -->
<div class="card-actions">
<el-button
size="mini"
type="primary"
@click="handleEdit(item)"
icon="el-icon-edit"
>编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(item)"
:loading="item.deleteLoading"
icon="el-icon-delete"
>删除</el-button>
<!-- 右侧明细面板 -->
<div class="right-panel">
<!-- 未选择卡片提示 -->
<div class="empty-detail" v-if="!selectedItem && !dialogVisible">
<el-empty description="请选择左侧钢种查看详情"></el-empty>
</div>
</el-card>
<!-- 钢种明细展示 -->
<div class="detail-content" v-if="selectedItem && !dialogVisible">
<div class="detail-header">
<h3>钢种详情</h3>
<el-button
type="primary"
@click="handleEdit(selectedItem)"
icon="el-icon-edit"
size="mini"
>编辑</el-button>
</div>
<el-descriptions :column="2" border style="margin-top: 10px;">
<el-descriptions-item label="钢种ID">{{ selectedItem.gradeid }}</el-descriptions-item>
<el-descriptions-item label="钢种名称">{{ selectedItem.name }}</el-descriptions-item>
<el-descriptions-item label="来源">{{ selectedItem.origin }}</el-descriptions-item>
<el-descriptions-item label="Sigma0">{{ selectedItem.sigma0 }}</el-descriptions-item>
<el-descriptions-item label="首次Sigma0">{{ selectedItem.firstSigma0 }}</el-descriptions-item>
<el-descriptions-item label="初始Sigma">{{ selectedItem.initSigma }}</el-descriptions-item>
<el-descriptions-item label="Ro值">{{ selectedItem.ro }}</el-descriptions-item>
<el-descriptions-item label="分类ID">{{ selectedItem.classId }}</el-descriptions-item>
<el-descriptions-item label="参数A">{{ selectedItem.a }}</el-descriptions-item>
<el-descriptions-item label="参数B">{{ selectedItem.b }}</el-descriptions-item>
<el-descriptions-item label="参数C">{{ selectedItem.c }}</el-descriptions-item>
<el-descriptions-item label="参数D">{{ selectedItem.d }}</el-descriptions-item>
<el-descriptions-item label="KC0参数">{{ selectedItem.kc0 }}</el-descriptions-item>
<el-descriptions-item label="KC1参数">{{ selectedItem.kc1 }}</el-descriptions-item>
<el-descriptions-item label="KC2参数">{{ selectedItem.kc2 }}</el-descriptions-item>
<el-descriptions-item label="KC3参数">{{ selectedItem.kc3 }}</el-descriptions-item>
<el-descriptions-item label="KC4参数">{{ selectedItem.kc4 }}</el-descriptions-item>
<el-descriptions-item label="Nu参数">{{ selectedItem.nu }}</el-descriptions-item>
<el-descriptions-item label="E参数">{{ selectedItem.e }}</el-descriptions-item>
<el-descriptions-item label="Chal参数">{{ selectedItem.chal }}</el-descriptions-item>
<el-descriptions-item label="Temp0参数">{{ selectedItem.temp0 }}</el-descriptions-item>
<el-descriptions-item label="强度">{{ selectedItem.strength }}</el-descriptions-item>
<el-descriptions-item label="焊接代码">{{ selectedItem.weldCode }}</el-descriptions-item>
<el-descriptions-item label="插入日期">{{ parseTime(selectedItem.insDate) }}</el-descriptions-item>
</el-descriptions>
</div>
</div>
</div>
<!-- 3. 编辑/新增弹窗完整保留原表单所有字段 -->
<!-- 编辑/新增弹窗 -->
<el-dialog
:title="dialogTitle"
:visible.sync="dialogVisible"
@@ -94,7 +150,6 @@
class="dialog-form"
>
<el-row :gutter="20">
<!-- 原表单所有字段完整保留 -->
<el-col :span="8">
<el-form-item label="钢种ID" prop="gradeid">
<el-input v-model="formData.gradeid" :disabled="isEdit"></el-input>
@@ -241,7 +296,6 @@ export default {
btnLoading: false,
dialogVisible: false,
dialogTitle: '新增钢种',
// 表单数据完整保留所有字段
formData: {
gradeid: null,
name: '',
@@ -278,7 +332,8 @@ export default {
},
saveLoading: false,
currentRow: {},
isEdit: false
isEdit: false,
selectedItem: null // 选中的钢种项
}
},
created() {
@@ -288,10 +343,9 @@ export default {
getSteelGradeList() {
this.tableLoading = true
getSteelGradeList().then(res => {
// 列表仅保留接口返回的gradeid和name,添加删除加载状态
// 保留完整数据,添加删除加载状态
this.tableData = res.data.map(item => ({
gradeid: item.gradeid,
name: item.name,
...item,
deleteLoading: false
}))
// 前端搜索过滤仅针对name
@@ -316,13 +370,20 @@ export default {
this.$refs.queryForm.resetFields();
this.getSteelGradeList()
},
handleRowClick(row) {
this.currentRow = row
// 卡片点击事件:加载详情并展示
handleCardClick(item) {
// 调用详情接口获取完整数据
getSteelGradeInfo(item.gradeid).then(res => {
this.selectedItem = { ...res.data }
}).catch(() => {
// 降级处理:使用列表数据
this.selectedItem = { ...item }
})
},
handleAdd() {
this.dialogTitle = '新增钢种';
this.isEdit = false;
// 重置表单(所有字段恢复默认值)
// 重置表单
this.formData = {
gradeid: null,
name: '',
@@ -354,15 +415,14 @@ export default {
handleEdit(row) {
this.dialogTitle = '编辑钢种';
this.isEdit = true;
// 调用详情接口获取完整字段数据(适配编辑时需展示所有参数)
// 调用详情接口获取完整字段数据
getSteelGradeInfo(row.gradeid).then(res => {
this.formData = { ...res.data }
}).catch(() => {
// 降级处理若详情接口也仅返回2个字段用列表数据填充核心字段其他字段保留默认
// 降级处理
this.formData = {
...this.formData,
gradeid: row.gradeid,
name: row.name
...row
}
})
this.dialogVisible = true
@@ -374,6 +434,10 @@ export default {
if (res.code === 200) {
this.$message.success('删除成功');
this.getSteelGradeList()
// 若删除的是当前选中项,清空选中状态
if (this.selectedItem?.gradeid === row.gradeid) {
this.selectedItem = null
}
} else this.$message.error(res.msg || '删除失败')
}).finally(() => {
row.deleteLoading = false
@@ -423,20 +487,44 @@ export default {
/* 页面整体容器 */
.steel-grade-management {
padding: 20px;
min-height: calc(100vh - 40px);
min-height: calc(100vh - 100px);
box-sizing: border-box;
}
/* 搜索区域样式自定义容器替代el-card */
.search-container {
margin-bottom: 10px;
}
/* 卡片列表容器:流式布局 + 响应式 */
.card-list-container {
/* 整体布局容器 */
.layout-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 30px;
height: calc(100vh - 100px);
}
/* 左侧面板 */
.left-panel {
width: 320px; /* 缩小左侧面板宽度 */
display: flex;
flex-direction: column;
gap: 10px;
}
/* 搜索区域样式 */
.search-container {
background: #fff;
padding: 10px;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
/* 卡片列表容器 */
.card-list-container {
flex: 1;
background: #fff;
padding: 10px;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 8px; /* 缩小卡片间距 */
}
/* 无数据提示 */
@@ -448,48 +536,113 @@ export default {
align-items: center;
}
/* 自定义钢种卡片完全替代el-card */
/* 钢种卡片样式 - 紧凑两行式 */
.steel-grade-card {
width: calc(25% - 15px); /* 默认4列 */
min-width: 280px; /* 最小宽度,防止窄屏变形 */
border-radius: 8px;
background-color: #333;
transition: all 0.3s ease;
overflow: hidden;
}
/* 卡片hover交互效果 */
.steel-grade-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
padding: 8px 12px; /* 缩小内边距 */
border: 1px solid #e6e6e6;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
flex-direction: column;
gap: 4px; /* 行间距 */
min-height: 60px; /* 固定最小高度 */
}
/* 卡片内容区仅展示gradeid和name */
.card-content {
padding: 20px;
border-bottom: 1px solid #f2f2f2;
.steel-grade-card:hover {
border-color: #409eff;
box-shadow: 0 2px 6px rgba(64, 158, 255, 0.1);
}
.grade-info {
margin-bottom: 12px;
.steel-grade-card.active {
border-color: #409eff;
background-color: #f0f7ff;
}
/* 卡片行样式 */
.card-row {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
/* 第一行:名称 + ID */
.row1 {
font-size: 14px;
}
.grade-info:last-child {
margin-bottom: 0;
}
.info-label {
color: #fff;
margin-right: 8px;
}
.info-value {
color: #fff;
font-weight: 500;
}
/* 卡片操作按钮区 */
.grade-name {
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 180px; /* 限制名称宽度 */
}
.grade-id {
color: #909399;
font-size: 12px;
}
/* 第二行:日期 + 操作按钮 */
.row2 {
font-size: 12px;
color: #666;
}
.ins-date {
color: #909399;
white-space: nowrap;
}
/* 卡片操作按钮区 - 紧凑文本按钮 */
.card-actions {
padding: 12px 20px;
display: flex;
justify-content: flex-end;
gap: 8px;
gap: 4px; /* 缩小按钮间距 */
}
.card-actions .el-button--text {
padding: 0 4px;
font-size: 12px;
}
.card-actions .el-icon {
font-size: 12px;
margin-right: 2px;
}
/* 右侧面板 */
.right-panel {
flex: 1;
background: #fff;
padding: 20px;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
overflow-y: auto;
}
/* 右侧空提示 */
.empty-detail {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
/* 详情内容 */
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.detail-header h3 {
margin: 0;
font-size: 16px;
color: #333;
}
/* 弹窗表单:滚动优化 */
@@ -498,24 +651,25 @@ export default {
overflow-y: auto;
padding-right: 10px;
}
.dialog-footer {
text-align: right;
}
/* 响应式适配:不同屏幕宽度调整卡片列数 */
@media (max-width: 1200px) {
.steel-grade-card {
width: calc(33.33% - 14px); /* 3列 */
}
}
/* 响应式适配 */
@media (max-width: 992px) {
.steel-grade-card {
width: calc(50% - 10px); /* 2列 */
.layout-container {
flex-direction: column;
height: auto;
}
}
@media (max-width: 576px) {
.steel-grade-card {
width: 100%; /* 1列 */
.left-panel {
width: 100%;
height: 400px;
}
.grade-name {
max-width: 280px;
}
}
</style>