feat(pdo): 新增PDO管理功能及相关组件
新增PDO管理页面及相关功能组件,包括: 1. 新增数据修正组件DataCorrection.vue 2. 新增标签打印组件LabelPrint.vue 3. 新增统计汇总组件PdoSummary.vue 4. 新增图表展示组件line.vue 5. 实现主页面index.vue布局及功能 6. 新增API接口文件用于业务数据交互 7. 修改lines/index.vue配置,移除baseURL动态获取逻辑
This commit is contained in:
609
klp-ui/src/views/lines/stop/index.vue
Normal file
609
klp-ui/src/views/lines/stop/index.vue
Normal file
@@ -0,0 +1,609 @@
|
||||
<template>
|
||||
<div class="stoppage-management">
|
||||
<!-- 查询表单区域 -->
|
||||
<div class="stop-header">
|
||||
<el-form :inline="true" :model="queryForm" ref="queryForm" label-width="80px" size="small">
|
||||
<el-form-item label="开始时间" prop="startDate">
|
||||
<el-date-picker v-model="queryForm.startDate" type="date" placeholder="选择开始时间" value-format="yyyy-MM-dd"
|
||||
:clearable="true"></el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="结束时间" prop="endDate">
|
||||
<el-date-picker v-model="queryForm.endDate" type="date" placeholder="选择结束时间" value-format="yyyy-MM-dd"
|
||||
:clearable="true"></el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery" :loading="btnLoading" icon="el-icon-search">查询</el-button>
|
||||
<el-button @click="handleReset" icon="el-icon-refresh">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 卡片网格布局 -->
|
||||
<div v-loading="tableLoading" class="card-grid-container">
|
||||
<el-row :gutter="10">
|
||||
<el-col
|
||||
v-for="(item, index) in tableData"
|
||||
:key="index"
|
||||
:xs="24"
|
||||
:sm="12"
|
||||
:md="8"
|
||||
:lg="6"
|
||||
:xl="5"
|
||||
class="card-col"
|
||||
>
|
||||
<el-card
|
||||
class="parameter-card"
|
||||
shadow="never"
|
||||
:body-style="{ padding: '8px' }"
|
||||
:class="{ 'card-selected': currentRow.stopid === item.stopid }"
|
||||
@click.native="handleRowClick(item)"
|
||||
>
|
||||
<div slot="header" class="card-header">
|
||||
<div class="card-title">停机ID: {{ item.stopid || '-' }}</div>
|
||||
<div class="card-subtitle">钢卷号: {{ item.coilid || '-' }}</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="param-groups-row">
|
||||
<!-- 基本信息 -->
|
||||
<div class="param-group">
|
||||
<div class="group-title">基本信息</div>
|
||||
<div class="param-list">
|
||||
<div class="param-line">
|
||||
<span class="param-label">停机类型:</span>
|
||||
<span class="param-value">{{ item.stopType || '-' }}</span>
|
||||
</div>
|
||||
<div class="param-line">
|
||||
<span class="param-label">班:</span>
|
||||
<span class="param-value">{{ item.shift || '-' }}</span>
|
||||
</div>
|
||||
<div class="param-line">
|
||||
<span class="param-label">组:</span>
|
||||
<span class="param-value">{{ item.crew || '-' }}</span>
|
||||
</div>
|
||||
<div class="param-line">
|
||||
<span class="param-label">区域:</span>
|
||||
<span class="param-value">{{ item.area || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 设备信息 -->
|
||||
<div class="param-group">
|
||||
<div class="group-title">设备信息</div>
|
||||
<div class="param-list">
|
||||
<div class="param-line">
|
||||
<span class="param-label">设备:</span>
|
||||
<span class="param-value">{{ item.seton || '-' }}</span>
|
||||
</div>
|
||||
<div class="param-line">
|
||||
<span class="param-label">机组:</span>
|
||||
<span class="param-value">{{ item.unit || '-' }}</span>
|
||||
</div>
|
||||
<div class="param-line">
|
||||
<span class="param-label">停机时长:</span>
|
||||
<span class="param-value">{{ item.duration || '-' }} 分钟</span>
|
||||
</div>
|
||||
<div class="param-line">
|
||||
<span class="param-label">更新时间:</span>
|
||||
<span class="param-value">{{ formatTime(item.insdate) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 时间信息 -->
|
||||
<div class="param-group">
|
||||
<div class="group-title">时间信息</div>
|
||||
<div class="param-list">
|
||||
<div class="param-line">
|
||||
<span class="param-label">开始时间:</span>
|
||||
<span class="param-value">{{ formatTime(item.startDate) }}</span>
|
||||
</div>
|
||||
<div class="param-line">
|
||||
<span class="param-label">结束时间:</span>
|
||||
<span class="param-value">{{ formatTime(item.endDate) }}</span>
|
||||
</div>
|
||||
<div class="param-line full-width" v-if="item.remark">
|
||||
<span class="param-label">停机原因:</span>
|
||||
<span class="param-value">{{ item.remark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
@click.stop="handleEdit(item)"
|
||||
>编辑</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
:loading="item.deleteLoading"
|
||||
@click.stop="handleDelete(item)"
|
||||
>删除</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div v-if="tableData.length === 0 && !tableLoading" class="empty-data">
|
||||
<el-empty description="暂无数据"></el-empty>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 编辑/新增弹窗 -->
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="60%" :close-on-click-modal="false">
|
||||
<el-form :model="formData" ref="formData" label-width="120px" :rules="formRules">
|
||||
<el-form-item label="停机ID" prop="stopid" v-if="formData.stopid">
|
||||
<el-input v-model="formData.stopid" disabled></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="钢卷号" prop="coilid">
|
||||
<el-input v-model="formData.coilid" placeholder="请输入钢卷号"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="班" prop="shift">
|
||||
<el-select v-model="formData.shift" placeholder="请选择班次" clearable>
|
||||
<el-option label="早班" value="早班"></el-option>
|
||||
<el-option label="中班" value="中班"></el-option>
|
||||
<el-option label="晚班" value="晚班"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="组" prop="crew">
|
||||
<el-input v-model="formData.crew" placeholder="请输入组号"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="区域" prop="area">
|
||||
<el-input v-model="formData.area" placeholder="请输入区域"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="机组" prop="unit">
|
||||
<el-input v-model="formData.unit" placeholder="请输入机组"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="设备" prop="seton">
|
||||
<el-input v-model="formData.seton" placeholder="请输入设备"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="开始时间" prop="startDate">
|
||||
<el-date-picker v-model="formData.startDate" type="datetime" placeholder="选择开始时间"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="结束时间" prop="endDate">
|
||||
<el-date-picker v-model="formData.endDate" type="datetime" placeholder="选择结束时间"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="停机类型" prop="stopType">
|
||||
<el-select v-model="formData.stopType" placeholder="请选择停机类型" clearable>
|
||||
<el-option label="计划停机" value="计划停机"></el-option>
|
||||
<el-option label="故障停机" value="故障停机"></el-option>
|
||||
<el-option label="维护停机" value="维护停机"></el-option>
|
||||
<el-option label="其他" value="其他"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="停机原因" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入停机原因" type="textarea" rows="4"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSave" :loading="saveLoading">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import createFetch from '@/api/l2/stop'; // 导入接口
|
||||
|
||||
export default {
|
||||
name: 'StoppageManagement',
|
||||
data() {
|
||||
return {
|
||||
// 查询表单数据
|
||||
queryForm: {
|
||||
// 只保留年月日YYYY-mm-dd
|
||||
startDate: '2023-08-13',
|
||||
endDate: '2025-08-20'
|
||||
},
|
||||
activeUrl: '140.143.206.120:18081',
|
||||
// 表格数据
|
||||
tableData: [],
|
||||
// 加载状态
|
||||
tableLoading: false,
|
||||
btnLoading: false,
|
||||
// 弹窗状态
|
||||
dialogVisible: false,
|
||||
dialogTitle: '新增停机记录',
|
||||
// 表单数据
|
||||
formData: {
|
||||
stopid: '',
|
||||
coilid: '',
|
||||
shift: '',
|
||||
crew: '',
|
||||
area: '',
|
||||
unit: '',
|
||||
seton: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
duration: 0,
|
||||
insdate: '',
|
||||
stopType: '',
|
||||
remark: ''
|
||||
},
|
||||
// 表单验证规则
|
||||
formRules: {
|
||||
startDate: [
|
||||
{ required: true, message: '请选择开始时间', trigger: 'blur' }
|
||||
],
|
||||
endDate: [
|
||||
{ required: true, message: '请选择结束时间', trigger: 'blur' }
|
||||
],
|
||||
seton: [
|
||||
{ required: true, message: '请输入设备', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
// 保存按钮加载状态
|
||||
saveLoading: false,
|
||||
// 当前操作的行数据
|
||||
currentRow: {},
|
||||
stopApi: undefined,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 页面加载时默认查询一次
|
||||
this.stopApi = createFetch(this.activeUrl);
|
||||
this.getStoppageList();
|
||||
},
|
||||
methods: {
|
||||
// 获取停机记录列表
|
||||
getStoppageList() {
|
||||
this.tableLoading = true;
|
||||
this.stopApi.listStoppage(this.queryForm)
|
||||
.then(response => {
|
||||
this.tableLoading = false;
|
||||
this.btnLoading = false;
|
||||
this.tableData = response.data.map(item => ({
|
||||
...item,
|
||||
deleteLoading: false
|
||||
}));
|
||||
})
|
||||
.catch(error => {
|
||||
this.tableLoading = false;
|
||||
this.btnLoading = false;
|
||||
console.error('获取数据失败:', error);
|
||||
this.$message.error('获取数据失败,请稍后重试');
|
||||
});
|
||||
},
|
||||
|
||||
// 处理查询
|
||||
handleQuery() {
|
||||
// 验证开始时间不能晚于结束时间
|
||||
if (this.queryForm.startDate && this.queryForm.endDate &&
|
||||
new Date(this.queryForm.startDate) > new Date(this.queryForm.endDate)) {
|
||||
this.$message.warning('开始时间不能晚于结束时间');
|
||||
return;
|
||||
}
|
||||
|
||||
this.btnLoading = true;
|
||||
this.getStoppageList();
|
||||
},
|
||||
|
||||
// 处理重置
|
||||
handleReset() {
|
||||
this.$refs.queryForm.resetFields();
|
||||
this.getStoppageList();
|
||||
},
|
||||
|
||||
// 行点击事件
|
||||
handleRowClick(row) {
|
||||
this.currentRow = row;
|
||||
},
|
||||
// 格式化时间
|
||||
formatTime(time) {
|
||||
if (!time) return '-';
|
||||
// 如果是日期时间格式,直接返回
|
||||
if (time.includes(' ')) {
|
||||
return time;
|
||||
}
|
||||
// 如果是日期格式,返回日期
|
||||
return time;
|
||||
},
|
||||
|
||||
// 新增
|
||||
handleAdd() {
|
||||
this.dialogTitle = '新增停机记录';
|
||||
this.formData = {
|
||||
stopid: '',
|
||||
coilid: '',
|
||||
shift: '',
|
||||
crew: '',
|
||||
area: '',
|
||||
unit: '',
|
||||
seton: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
duration: 0,
|
||||
insdate: '',
|
||||
stopType: '',
|
||||
remark: ''
|
||||
};
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
|
||||
// 编辑
|
||||
handleEdit(row) {
|
||||
this.dialogTitle = '编辑停机记录';
|
||||
this.formData = { ...row };
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
|
||||
// 删除
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除ID为 ${row.stopid} 的停机记录吗?`, '确认删除', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'danger'
|
||||
}).then(() => {
|
||||
// 设置当前行的删除按钮为加载状态
|
||||
row.deleteLoading = true;
|
||||
|
||||
this.stopApi.deleteStoppage(row.stopid)
|
||||
.then(response => {
|
||||
row.deleteLoading = false;
|
||||
|
||||
if (response.code === 200) {
|
||||
this.$message.success('删除成功');
|
||||
// 重新查询数据
|
||||
this.getStoppageList();
|
||||
} else {
|
||||
this.$message.error(response.msg || '删除失败');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
row.deleteLoading = false;
|
||||
console.error('删除失败:', error);
|
||||
this.$message.error('删除失败,请稍后重试');
|
||||
});
|
||||
}).catch(() => {
|
||||
// 用户取消删除
|
||||
this.$message.info('已取消删除');
|
||||
});
|
||||
},
|
||||
|
||||
// 保存
|
||||
handleSave() {
|
||||
this.$refs.formData.validate(valid => {
|
||||
if (valid) {
|
||||
// 验证开始时间不能晚于结束时间
|
||||
if (new Date(this.formData.startDate) > new Date(this.formData.endDate)) {
|
||||
this.$message.warning('开始时间不能晚于结束时间');
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算停机时长(分钟)
|
||||
const start = new Date(this.formData.startDate).getTime();
|
||||
const end = new Date(this.formData.endDate).getTime();
|
||||
this.formData.duration = Math.round((end - start) / (1000 * 60) * 10) / 10;
|
||||
|
||||
// 设置当前时间为更新时间
|
||||
const now = new Date();
|
||||
this.formData.insdate = now.toISOString().slice(0, 19).replace('T', ' ');
|
||||
|
||||
this.saveLoading = true;
|
||||
|
||||
// 调用更新接口
|
||||
this.stopApi.updateStoppage(this.formData)
|
||||
.then(response => {
|
||||
this.saveLoading = false;
|
||||
|
||||
if (response.code === 200) {
|
||||
this.$message.success('保存成功');
|
||||
this.dialogVisible = false;
|
||||
// 重新查询数据
|
||||
this.getStoppageList();
|
||||
} else {
|
||||
this.$message.error(response.msg || '保存失败');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
this.saveLoading = false;
|
||||
console.error('保存失败:', error);
|
||||
this.$message.error('保存失败,请稍后重试');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.stoppage-management {
|
||||
height: calc(100vh - 84px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 15px;
|
||||
background: #f5f5f5;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stop-header {
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4d4d4;
|
||||
border-radius: 2px;
|
||||
padding: 15px;
|
||||
margin-bottom: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.card-grid-container {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding-right: 5px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #c0c0c0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
}
|
||||
|
||||
.card-col {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.parameter-card {
|
||||
border: 1px solid #d4d4d4;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
|
||||
&.card-selected {
|
||||
border-color: #999;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
::v-deep .el-card__header {
|
||||
padding: 6px 8px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: #999;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
.card-title {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
margin-bottom: 2px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.card-subtitle {
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
line-height: 1.3;
|
||||
}
|
||||
}
|
||||
|
||||
.card-body {
|
||||
.param-groups-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.param-group {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
.group-title {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
padding: 3px 0;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
margin-bottom: 4px;
|
||||
background: #f5f5f5;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
margin-left: -4px;
|
||||
margin-right: -4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.param-list {
|
||||
.param-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 3px 0;
|
||||
border-bottom: 1px dotted #e8e8e8;
|
||||
|
||||
&.full-width {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
.param-label {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.param-value {
|
||||
text-align: left;
|
||||
word-break: break-word;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.param-label {
|
||||
color: #777;
|
||||
font-size: 11px;
|
||||
flex-shrink: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.param-value {
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
font-size: 11px;
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 6px;
|
||||
padding-top: 6px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
margin-top: 6px;
|
||||
|
||||
.el-button {
|
||||
font-size: 11px;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-data {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user