feat(i18n): 实现多语言支持并更新相关组件

refactor: 重构组件以使用i18n动态文本
style: 调整代码格式和结构
docs: 更新多语言翻译文件
This commit is contained in:
砂糖
2025-12-29 11:16:35 +08:00
parent 4fa6a1f59a
commit fa37b697e6
20 changed files with 1645 additions and 619 deletions

View File

@@ -8,8 +8,8 @@
</div>
<div class="main-title">
<p>探索生产与信息的无限可能</p>
<p class="subtitle">创新 · 科技 · 未来</p>
<p>{{ $t('dashboard.explorePossibilities') }}</p>
<p class="subtitle">{{ $t('dashboard.innovationTechFuture') }}</p>
</div>
</div>

View File

@@ -14,7 +14,7 @@
<el-row :gutter="5" style="padding: 0 20px 20px;">
<el-col :span="10">
<el-card>
<div slot="header"><span>系统告警信息</span></div>
<div slot="header"><span>{{ $t('dashboard.alarmInfo') }}</span></div>
<!-- 第一个表格绑定API获取的数据和列配置 -->
<MiniTable
v-loading="tableLoading"
@@ -27,7 +27,7 @@
</el-col>
<el-col :span="14">
<el-card>
<div slot="header"><span>换辊信息</span></div>
<div slot="header"><span>{{ $t('dashboard.rollChangeInfo') }}</span></div>
<MiniTable
v-loading="rollHistoryLoading"
:columns="rollHistoryColumns"
@@ -38,7 +38,7 @@
</el-col>
<el-col :span="24">
<el-card>
<div slot="header"><span>生产计划</span></div>
<div slot="header"><span>{{ $t('dashboard.productionPlan') }}</span></div>
<MiniTable
v-loading="planLoading"
:columns="planColumns"
@@ -49,7 +49,7 @@
</el-col>
<el-col :span="24">
<el-card>
<div slot="header"><span>过程跟踪</span></div>
<div slot="header"><span>{{ $t('dashboard.processTracking') }}</span></div>
<TrackMeasure
v-loading="measureLoading"
:columns="measureColumns"
@@ -77,47 +77,6 @@ export default {
components: { CurrentTime, HomeMain, MiniTable, TrackMeasure },
data() {
return {
featureCards: [
{ title: "生产计划", desc: "生产计划管理...", icon: "table", path: "/plan" },
{ title: "日志记录", desc: "日志记录管理...", icon: "log", path: "/log" },
{ title: "轧辊管理", desc: "轧辊管理...", icon: "redis", path: "/roller" },
{ title: "停机管理", desc: "停机管理...", icon: "bug", path: "/stop" },
],
// 表格列配置(与日志字段对应)
alarmColumns: [
{ label: "发生时间", prop: "timestamp", width: "200px" },
{ label: "报警模块", prop: "module", width: "60px" },
{ label: "报警类型", prop: "logtype" },
],
rollHistoryColumns: [
{ label: "换辊号", prop: "changeid" },
{ label: "轧辊号", prop: "rollid" },
{ label: "机组", prop: "seton", width: "80px" },
{ label: "班次", prop: "shift", width: "60px" },
{ label: "班组", prop: "crew", width: "60px" },
{ label: "机架号", prop: "standid", width: "80px" },
{ label: "位置", prop: "position", width: "50px" },
{ label: '直径', prop: 'diameter', width: '100px' },
{ label: '粗糙度', prop: 'rough', width: '100px' },
{ label: '凸度', prop: 'crown', width: '100px' },
{ label: '成分', prop: 'composition', width: '100px' },
],
planColumns: [
{ label: '顺序号', prop: 'seqid', width: '80px' },
{ label: '钢卷号', prop: 'coilid', width: '120px' },
{ label: '机组号', prop: 'unitCode', width: '100px' },
{ label: '计划号', prop: 'planid', width: '120px' },
{ label: '计划类型', prop: 'planType', width: '80px' },
{ label: '钢种', prop: 'steelGrade', width: '120px' },
{ label: '出口卷号', prop: 'exitCoilid', width: '100px' },
{ label: '订单号', prop: 'orderNo', width: '100px' },
{ label: '客户代码', prop: 'custommerCode', width: '100px' },
{ label: '上线时间', prop: 'onlineDate' },
{ label: '开始时间', prop: 'startDate' },
{ label: '结束时间', prop: 'endDate' },
{ label: '进炉时间', prop: 'furInDate' },
{ label: '出炉时间', prop: 'furOutDate' },
],
alarmData: [], // 表格数据从API获取
queryForm: { pageNum: 1, pageSize: 10 }, // 分页参数
tableLoading: false, // 加载状态
@@ -127,6 +86,58 @@ export default {
planLoading: false, // 生产计划数据加载状态
};
},
computed: {
// 功能卡片配置
featureCards() {
return [
{ title: this.$t('dashboard.productionPlan'), desc: this.$t('dashboard.productionPlanDesc'), icon: "table", path: "/plan" },
{ title: this.$t('dashboard.logRecord'), desc: this.$t('dashboard.logRecordDesc'), icon: "log", path: "/log" },
{ title: this.$t('dashboard.rollManagement'), desc: this.$t('dashboard.rollManagementDesc'), icon: "redis", path: "/roller" },
{ title: this.$t('dashboard.shutdownManagement'), desc: this.$t('dashboard.shutdownManagementDesc'), icon: "bug", path: "/stop" },
];
},
// 表格列配置(与日志字段对应)
alarmColumns() {
return [
{ label: this.$t('dashboard.occurTime'), prop: "timestamp", width: "200px" },
{ label: this.$t('dashboard.alarmModule'), prop: "module", width: "60px" },
{ label: this.$t('dashboard.alarmType'), prop: "logtype" },
];
},
rollHistoryColumns() {
return [
{ label: this.$t('dashboard.rollChangeId'), prop: "changeid" },
{ label: this.$t('dashboard.rollId'), prop: "rollid" },
{ label: this.$t('dashboard.unit'), prop: "seton", width: "80px" },
{ label: this.$t('dashboard.shift'), prop: "shift", width: "60px" },
{ label: this.$t('dashboard.crew'), prop: "crew", width: "60px" },
{ label: this.$t('dashboard.standId'), prop: "standid", width: "80px" },
{ label: this.$t('dashboard.position'), prop: "position", width: "50px" },
{ label: this.$t('dashboard.diameter'), prop: 'diameter', width: '100px' },
{ label: this.$t('dashboard.roughness'), prop: 'rough', width: '100px' },
{ label: this.$t('dashboard.crown'), prop: 'crown', width: '100px' },
{ label: this.$t('dashboard.composition'), prop: 'composition', width: '100px' },
];
},
planColumns() {
return [
{ label: this.$t('dashboard.seqId'), prop: 'seqid', width: '80px' },
{ label: this.$t('dashboard.coilId'), prop: 'coilid', width: '120px' },
{ label: this.$t('dashboard.unitCode'), prop: 'unitCode', width: '100px' },
{ label: this.$t('dashboard.planId'), prop: 'planid', width: '120px' },
{ label: this.$t('dashboard.planType'), prop: 'planType', width: '80px' },
{ label: this.$t('dashboard.steelGrade'), prop: 'steelGrade', width: '120px' },
{ label: this.$t('dashboard.exitCoilId'), prop: 'exitCoilid', width: '100px' },
{ label: this.$t('dashboard.orderNo'), prop: 'orderNo', width: '100px' },
{ label: this.$t('dashboard.customerCode'), prop: 'custommerCode', width: '100px' },
{ label: this.$t('dashboard.onlineDate'), prop: 'onlineDate' },
{ label: this.$t('dashboard.startDate'), prop: 'startDate' },
{ label: this.$t('dashboard.endDate'), prop: 'endDate' },
{ label: this.$t('dashboard.furInDate'), prop: 'furInDate' },
{ label: this.$t('dashboard.furOutDate'), prop: 'furOutDate' },
];
},
},
created() {
// 页面加载时调用API获取数据
this.getLogData();
@@ -144,7 +155,7 @@ export default {
.catch((error) => {
this.tableLoading = false;
console.error("获取日志数据失败:", error);
this.$message.error("获取日志数据失败,请稍后重试");
this.$message.error(this.$t('dashboard.getLogDataFailed'));
});
},
getRollHistorytList() {

View File

@@ -3,52 +3,52 @@
<el-card>
<!-- 查询表单 -->
<el-form :inline="true" :model="queryForm" ref="queryForm" label-width="80px">
<el-form-item label="开始时间" prop="startTime">
<el-form-item :label="$t('log.startTime')" prop="startTime">
<el-date-picker v-model="queryForm.startTime" type="datetime" placeholder="选择开始时间"
value-format="yyyy-MM-dd HH:mm:ss" :clearable="true"></el-date-picker>
value-format="yyyy-MM-dd HH:mm:ss" :clearable="true" :placeholder="$t('log.chooseStartTime')"></el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-form-item :label="$t('log.endTime')" prop="endTime">
<el-date-picker v-model="queryForm.endTime" type="datetime" placeholder="选择结束时间"
value-format="yyyy-MM-dd HH:mm:ss" :clearable="true"></el-date-picker>
value-format="yyyy-MM-dd HH:mm:ss" :clearable="true" :placeholder="$t('log.chooseEndTime')"></el-date-picker>
</el-form-item>
<el-form-item label="报警类型" prop="logtype">
<el-select v-model="queryForm.logtype" placeholder="请选择报警类型" clearable>
<el-option label="系统报警" value="system"></el-option>
<el-option label="设备报警" value="device"></el-option>
<el-option label="网络报警" value="network"></el-option>
<el-option label="安全报警" value="security"></el-option>
<el-form-item :label="$t('log.alarmType')" prop="logtype">
<el-select v-model="queryForm.logtype" :placeholder="$t('log.chooseAlarmType')" clearable>
<el-option :label="$t('log.systemAlarm')" value="system"></el-option>
<el-option :label="$t('log.deviceAlarm')" value="device"></el-option>
<el-option :label="$t('log.networkAlarm')" value="network"></el-option>
<el-option :label="$t('log.securityAlarm')" value="security"></el-option>
</el-select>
</el-form-item>
<el-form-item label="报警模块" prop="module">
<el-select v-model="queryForm.module" placeholder="请选择报警模块" clearable>
<el-option label="监控模块" value="monitor"></el-option>
<el-option label="管理模块" value="admin"></el-option>
<el-option label="分析模块" value="analysis"></el-option>
<el-option label="存储模块" value="storage"></el-option>
<el-form-item :label="$t('log.alarmModule')" prop="module">
<el-select v-model="queryForm.module" :placeholder="$t('log.chooseAlarmModule')" clearable>
<el-option :label="$t('log.monitorModule')" value="monitor"></el-option>
<el-option :label="$t('log.adminModule')" value="admin"></el-option>
<el-option :label="$t('log.analysisModule')" value="analysis"></el-option>
<el-option :label="$t('log.storageModule')" value="storage"></el-option>
</el-select>
</el-form-item>
<el-form-item label="警报内容" prop="logtext">
<el-input v-model="queryForm.logtext" placeholder="请输入警报内容" clearable style="width: 200px;"></el-input>
<el-form-item :label="$t('log.alarmContent')" prop="logtext">
<el-input v-model="queryForm.logtext" :placeholder="$t('log.enterAlarmContent')" clearable style="width: 200px;"></el-input>
</el-form-item>
<el-form-item label="报警状态" prop="status">
<el-select v-model="queryForm.status" placeholder="请选择报警状态" clearable>
<el-option label="未处理" value="0"></el-option>
<el-option label="已处理" value="1"></el-option>
<el-option label="已忽略" value="2"></el-option>
<el-form-item :label="$t('log.alarmStatus')" prop="status">
<el-select v-model="queryForm.status" :placeholder="$t('log.chooseAlarmStatus')" clearable>
<el-option :label="$t('log.untreated')" value="0"></el-option>
<el-option :label="$t('log.processed')" value="1"></el-option>
<el-option :label="$t('log.ignored')" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery" :loading="btnLoading">
<i class="el-icon-search"></i> 查询
<i class="el-icon-search"></i> {{ $t('common.search') }}
</el-button>
<el-button @click="handleReset">
<i class="el-icon-refresh"></i> 重置
<i class="el-icon-refresh"></i> {{ $t('common.reset') }}
</el-button>
</el-form-item>
</el-form>
@@ -56,21 +56,21 @@
<!-- 数据表格 -->
<el-table v-loading="tableLoading" :data="tableData" border style="width: 100%; margin-top: 20px;"
@row-click="handleRowClick" highlight-current-row>
<el-table-column prop="seqid" label="序号" width="80" align="center"></el-table-column>
<el-table-column prop="timestamp" label="发生时间" width="180" align="center"></el-table-column>
<el-table-column prop="module" label="报警模块" align="center">
<el-table-column prop="seqid" :label="$t('log.serialNumber')" width="80" align="center"></el-table-column>
<el-table-column prop="timestamp" :label="$t('log.occurTime')" width="180" align="center"></el-table-column>
<el-table-column prop="module" :label="$t('log.alarmModule')" align="center">
<template slot-scope="scope">
<!-- <el-tag>{{ formatModule(scope.row.module) }}</el-tag> -->
<dict-tag :options="dict.type.main_log_module" :value="scope.row.module" />
</template>
</el-table-column>
<el-table-column prop="logtype" label="报警类型" align="center">
<el-table-column prop="logtype" :label="$t('log.alarmType')" align="center">
<template slot-scope="scope">
<!-- <el-tag :type="getLogTypeTagType(scope.row.logtype)">{{ formatLogType(scope.row.logtype) }}</el-tag> -->
<dict-tag :options="dict.type.main_log_type" :value="scope.row.logtype" />
</template>
</el-table-column>
<el-table-column prop="logtext" label="警报内容" min-width="200"></el-table-column>
<el-table-column prop="logtext" :label="$t('log.alarmContent')" min-width="200"></el-table-column>
<!-- <el-table-column prop="status" label="状态" align="center">
<template slot-scope="scope">
<el-tag :type="getStatusTagType(scope.row.status)">
@@ -103,22 +103,22 @@
</el-card>
<!-- 详情弹窗 -->
<el-dialog title="历史记录详情" :visible.sync="detailDialogVisible" width="60%" :close-on-click-modal="false">
<el-dialog :title="$t('log.historyDetail')" :visible.sync="detailDialogVisible" width="60%" :close-on-click-modal="false">
<el-descriptions column="1" border>
<el-descriptions-item label="序号">{{ currentRow.seqid }}</el-descriptions-item>
<el-descriptions-item label="发生时间">{{ currentRow.timestamp }}</el-descriptions-item>
<el-descriptions-item label="报警模块">{{ formatModule(currentRow.module) }}</el-descriptions-item>
<el-descriptions-item label="报警类型">{{ formatLogType(currentRow.logtype) }}</el-descriptions-item>
<el-descriptions-item label="警报内容">{{ currentRow.logtext }}</el-descriptions-item>
<el-descriptions-item label="状态">
<el-descriptions-item :label="$t('log.serialNumber')">{{ currentRow.seqid }}</el-descriptions-item>
<el-descriptions-item :label="$t('log.occurTime')">{{ currentRow.timestamp }}</el-descriptions-item>
<el-descriptions-item :label="$t('log.alarmModule')">{{ formatModule(currentRow.module) }}</el-descriptions-item>
<el-descriptions-item :label="$t('log.alarmType')">{{ formatLogType(currentRow.logtype) }}</el-descriptions-item>
<el-descriptions-item :label="$t('log.alarmContent')">{{ currentRow.logtext }}</el-descriptions-item>
<el-descriptions-item :label="$t('log.status')">
<el-tag :type="getStatusTagType(currentRow.status)">
{{ formatStatus(currentRow.status) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="确认时间">{{ currentRow.confirmTime || '未确认' }}</el-descriptions-item>
<el-descriptions-item :label="$t('log.confirmTime')">{{ currentRow.confirmTime || $t('log.notConfirmed') }}</el-descriptions-item>
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button @click="detailDialogVisible = false">关闭</el-button>
<el-button @click="detailDialogVisible = false">{{ $t('common.close') }}</el-button>
</div>
</el-dialog>
</div>
@@ -175,7 +175,7 @@ export default {
this.tableLoading = false;
this.btnLoading = false;
console.error('获取数据失败:', error);
this.$message.error('获取数据失败,请稍后重试');
this.$message.error(this.$t('log.getLogDataFailed'));
});
},
@@ -184,7 +184,7 @@ export default {
// 验证开始时间不能晚于结束时间
if (this.queryForm.startTime && this.queryForm.endTime &&
new Date(this.queryForm.startTime) > new Date(this.queryForm.endTime)) {
this.$message.warning('开始时间不能晚于结束时间');
this.$message.warning(this.$t('log.startTimeNotLaterThanEndTime'));
return;
}
@@ -228,23 +228,23 @@ export default {
// 格式化报警模块显示
formatModule(module) {
const moduleMap = {
'monitor': '监控模块',
'admin': '管理模块',
'analysis': '分析模块',
'storage': '存储模块'
'monitor': this.$t('log.monitorModule'),
'admin': this.$t('log.adminModule'),
'analysis': this.$t('log.analysisModule'),
'storage': this.$t('log.storageModule')
};
return moduleMap[module] || module || '未知';
return moduleMap[module] || module || this.$t('common.unknown');
},
// 格式化报警类型显示
formatLogType(logtype) {
const logtypeMap = {
'system': '系统报警',
'device': '设备报警',
'network': '网络报警',
'security': '安全报警'
'system': this.$t('log.systemAlarm'),
'device': this.$t('log.deviceAlarm'),
'network': this.$t('log.networkAlarm'),
'security': this.$t('log.securityAlarm')
};
return logtypeMap[logtype] || logtype || '未知';
return logtypeMap[logtype] || logtype || this.$t('common.unknown');
},
// 获取报警类型标签样式
@@ -261,11 +261,11 @@ export default {
// 格式化状态显示
formatStatus(status) {
const statusMap = {
0: '未处理',
1: '已处理',
2: '已忽略'
0: this.$t('log.untreated'),
1: this.$t('log.processed'),
2: this.$t('log.ignored')
};
return statusMap[status] || '未知';
return statusMap[status] || this.$t('common.unknown');
},
// 获取状态标签样式
@@ -283,7 +283,7 @@ export default {
this.loading = true;
alarmAck(seqid)
.then(response => {
this.$message.success('确认成功');
this.$message.success(this.$t('log.confirmSuccess'));
this.getLogData();
})
}

View File

@@ -3,21 +3,21 @@
<!-- 查询表单区域 -->
<div class="pdo-header">
<el-form :inline="true" :model="queryForm" ref="queryForm" label-width="100px" size="small">
<el-form-item label="钢卷号" prop="coilid">
<el-input v-model="queryForm.coilid" placeholder="请输入钢卷号"></el-input>
<el-form-item :label="$t('pdo.coilid')" prop="coilid">
<el-input v-model="queryForm.coilid" :placeholder="$t('pdo.pleaseInputCoilid')"></el-input>
</el-form-item>
<el-form-item label="开始日期" prop="startDate">
<el-date-picker v-model="queryForm.startDate" type="date" placeholder="选择开始日期" value-format="yyyy-MM-dd"
<el-form-item :label="$t('pdo.startDate')" prop="startDate">
<el-date-picker v-model="queryForm.startDate" type="date" :placeholder="$t('pdo.chooseStartDate')" value-format="yyyy-MM-dd"
clearable></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"
<el-form-item :label="$t('pdo.endDate')" prop="endDate">
<el-date-picker v-model="queryForm.endDate" type="date" :placeholder="$t('pdo.chooseEndDate')" value-format="yyyy-MM-dd"
clearable></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-button type="success" @click="handleAdd" icon="el-icon-plus">补录</el-button>
<el-button type="primary" @click="handleQuery" :loading="btnLoading" icon="el-icon-search">{{ $t('pdo.query') }}</el-button>
<el-button @click="handleReset" icon="el-icon-refresh">{{ $t('pdo.reset') }}</el-button>
<el-button type="success" @click="handleAdd" icon="el-icon-plus">{{ $t('pdo.add') }}</el-button>
</el-form-item>
</el-form>
</div>
@@ -30,29 +30,29 @@
<el-card class="parameter-card" shadow="never" :body-style="{ padding: '8px' }"
:class="{ 'card-selected': currentRow.exitMatId === item.exitMatId }" @click.native="handleRowClick(item)">
<div slot="header" class="card-header">
<div class="card-title">成品卷: {{ item.exitMatId || '-' }}</div>
<div class="card-title">{{ $t('pdo.finishedCoil') }}: {{ item.exitMatId || '-' }}</div>
<div class="card-subtitle">{{ item.entryMatId || '-' }} | {{ item.planNo || '-' }}</div>
</div>
<div class="card-body">
<div class="param-groups-row">
<!-- 基本信息 -->
<div class="param-group">
<div class="group-title">基本信息</div>
<div class="group-title">{{ $t('pdo.basicInfo') }}</div>
<div class="param-list">
<div class="param-line">
<span class="param-label">状态:</span>
<span class="param-label">{{ $t('pdo.status') }}:</span>
<span class="param-value">{{ item.status || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">钢种:</span>
<span class="param-label">{{ $t('pdo.steelGrade') }}:</span>
<span class="param-value">{{ item.steelGrade || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">产品类型:</span>
<span class="param-label">{{ $t('pdo.productType') }}:</span>
<span class="param-value">{{ item.prodCode || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">客户:</span>
<span class="param-label">{{ $t('pdo.customer') }}:</span>
<span class="param-value">{{ item.customer || '-' }}</span>
</div>
</div>
@@ -60,22 +60,22 @@
<!-- 来料信息 -->
<div class="param-group">
<div class="group-title">来料信息</div>
<div class="group-title">{{ $t('pdo.materialInfo') }}</div>
<div class="param-list">
<div class="param-line">
<span class="param-label">厚度:</span>
<span class="param-label">{{ $t('pdo.thickness') }}:</span>
<span class="param-value">{{ item.entryThick || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">宽度:</span>
<span class="param-label">{{ $t('pdo.width') }}:</span>
<span class="param-value">{{ item.entryWidth || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">长度:</span>
<span class="param-label">{{ $t('pdo.length') }}:</span>
<span class="param-value">{{ item.entryLength || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">重量:</span>
<span class="param-label">{{ $t('pdo.weight') }}:</span>
<span class="param-value">{{ item.entryWeight || '-' }}</span>
</div>
</div>
@@ -83,22 +83,22 @@
<!-- 成品信息 -->
<div class="param-group">
<div class="group-title">成品信息</div>
<div class="group-title">{{ $t('pdo.productInfo') }}</div>
<div class="param-list">
<div class="param-line">
<span class="param-label">厚度:</span>
<span class="param-label">{{ $t('pdo.thickness') }}:</span>
<span class="param-value">{{ item.exitThickness || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">宽度:</span>
<span class="param-label">{{ $t('pdo.width') }}:</span>
<span class="param-value">{{ item.exitWidth || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">长度:</span>
<span class="param-label">{{ $t('pdo.length') }}:</span>
<span class="param-value">{{ item.exitLength || '-' }}</span>
</div>
<div class="param-line">
<span class="param-label">重量:</span>
<span class="param-label">{{ $t('pdo.weight') }}:</span>
<span class="param-value">{{ item.exitNetWeight || '-' }}</span>
</div>
</div>
@@ -106,16 +106,16 @@
</div>
</div>
<div class="card-footer">
<el-button size="mini" type="text" icon="el-icon-view" @click.stop="handlePrint(item)">打印</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleEdit(item)">操作</el-button>
<el-button size="mini" type="text" icon="el-icon-view" @click.stop="handlePrint(item)">{{ $t('pdo.print') }}</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleEdit(item)">{{ $t('pdo.operate') }}</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" :loading="item.deleteLoading"
@click.stop="handleDelete(item)">删除</el-button>
@click.stop="handleDelete(item)">{{ $t('pdo.delete') }}</el-button>
</div>
</el-card>
</el-col>
</el-row>
<div v-if="tableData.length === 0 && !tableLoading" class="empty-data">
<el-empty description="暂无数据"></el-empty>
<el-empty :description="$t('pdo.noData')"></el-empty>
</div>
</div>
@@ -124,19 +124,19 @@
<div class="statistics-header">
<div class="selected-info" v-if="currentRow && currentRow.entryMatId">
<i class="el-icon-check"></i>
<span class="selected-label">已选中:</span>
<span class="selected-value">成品卷 {{ currentRow.exitMatId }}</span>
<span class="selected-detail" v-if="currentRow.entryMatId">(来料卷: {{ currentRow.entryMatId }})</span>
<span class="selected-label">{{ $t('pdo.selected') }}</span>
<span class="selected-value">{{ $t('pdo.finishedCoil') }} {{ currentRow.exitMatId }}</span>
<span class="selected-detail" v-if="currentRow.entryMatId">({{ $t('pdo.entryMatId') }}: {{ currentRow.entryMatId }})</span>
</div>
<div class="selected-info empty" v-else>
<i class="el-icon-info"></i>
<span>请选择上方卡片查看详情</span>
<span>{{ $t('pdo.pleaseSelect') }}</span>
</div>
</div>
<el-row :gutter="15" class="statistics-content">
<el-col :span="4" class="summary-col">
<div class="summary-wrapper">
<div class="summary-header">统计汇总</div>
<div class="summary-header">{{ $t('pdo.statisticsSummary') }}</div>
<pdo-summary :table-data="tableData" />
</div>
</el-col>
@@ -168,7 +168,7 @@
</el-tabs> -->
</el-dialog>
<el-dialog title="标签打印" :visible.sync="printOpen" width="600px" :close-on-click-modal="false">
<el-dialog :title="$t('pdo.labelPrint')" :visible.sync="printOpen" width="600px" :close-on-click-modal="false">
<div style="display: flex; justify-content: center; align-items: center;">
<pdo-label-print :detail="formData"></pdo-label-print>
</div>
@@ -202,7 +202,7 @@ export default {
tableLoading: false,
btnLoading: false,
dialogVisible: false,
dialogTitle: '新增实绩',
dialogTitle: '',
// 新增:区分「补录(新增)」和「编辑」的状态标识
isAdd: false,
// 传递给子组件的详情数据(父组件仅做数据中转,不直接修改)
@@ -230,7 +230,7 @@ export default {
this.tableData = res.data.map(item => ({ ...item, deleteLoading: false }))
}).catch(err => {
console.error(err)
this.$message.error('获取数据失败')
this.$message.error(this.$t('pdo.getDataFailed'))
}).finally(() => {
this.tableLoading = false
this.btnLoading = false
@@ -258,7 +258,7 @@ export default {
// 补录新增设置isAdd=true初始化空表单
handleAdd() {
this.isAdd = true; // 标记为「补录」
this.dialogTitle = '新增实绩';
this.dialogTitle = this.$t('pdo.addPdo');
// 初始化空表单数据(传递给子组件)
this.formData = {
subId: 0,
@@ -286,7 +286,7 @@ export default {
// 编辑设置isAdd=false赋值行数据
handleEdit(row) {
this.isAdd = false; // 标记为「编辑」
this.dialogTitle = '编辑实绩';
this.dialogTitle = this.$t('pdo.editPdo');
// 深拷贝行数据(避免直接修改表格数据)
this.formData = JSON.parse(JSON.stringify(row));
this.dialogVisible = true
@@ -298,13 +298,13 @@ export default {
},
// 删除(保持不变)
handleDelete(row) {
this.$confirm(`确定删除成品卷 ${row.exitMatId}?`, '确认删除', { type: 'danger' }).then(() => {
this.$confirm(`${this.$t('common.confirm')}${this.$t('pdo.delete')}${this.$t('pdo.finishedCoil')} ${row.exitMatId}?`, this.$t('pdo.confirmDelete'), { type: 'danger' }).then(() => {
row.deleteLoading = true
deletePdo(row.exitMatId, row.planId).then(res => {
if (res.code === 200) {
this.$message.success('删除成功');
this.$message.success(this.$t('pdo.deleteSuccess'));
this.getPdoList()
} else this.$message.error(res.msg || '删除失败')
} else this.$message.error(res.msg || this.$t('pdo.deleteFailed'))
}).finally(() => row.deleteLoading = false)
})
},
@@ -315,10 +315,10 @@ export default {
const request = formData.id ? updatePdo(formData) : addPdo(formData)
request.then(res => {
if (res.code === 200) {
this.$message.success('保存成功');
this.$message.success(this.$t('pdo.saveSuccess'));
this.dialogVisible = false;
this.getPdoList() // 刷新列表
} else this.$message.error(res.msg || '保存失败')
} else this.$message.error(res.msg || this.$t('pdo.saveFailed'))
}).finally(() => {
this.saveLoading = false
})

View File

@@ -3,10 +3,10 @@
<!-- 顶部工具栏 -->
<div class="toolbar">
<el-button type="primary" @click="handleAdd" icon="el-icon-plus" size="small">
新增计划
{{ $t('plan.addPlan') }}
</el-button>
<el-button @click="getList" icon="el-icon-refresh" size="small">
刷新
{{ $t('plan.refresh') }}
</el-button>
</div>
@@ -22,7 +22,7 @@
>
<div class="card-status">
<span class="status-dot status-producing"></span>
<span class="status-text">生产中</span>
<span class="status-text">{{ $t('plan.producing') }}</span>
<!-- 当前位置 -->
<div class="card-position" v-if="getPlanPosition(plan)">
<i class="el-icon-location"></i>
@@ -32,33 +32,33 @@
<div class="card-content">
<div class="card-main">
<div class="plan-id">{{ plan.planid }}</div>
<div class="coil-id">钢卷号: {{ plan.coilid }}</div>
<div class="coil-id">{{ $t('plan.coilid') }}: {{ plan.coilid }}</div>
</div>
<div class="card-details">
<div class="detail-item">
<span class="label">钢种:</span>
<span class="label">{{ $t('plan.steelGrade') }}:</span>
<span class="value">{{ plan.steelGrade }}</span>
</div>
<div class="detail-item">
<span class="label">厚度:</span>
<span class="label">{{ $t('plan.thickness') }}:</span>
<span class="value">{{ plan.entryThick }} mm</span>
</div>
<div class="detail-item">
<span class="label">宽度:</span>
<span class="label">{{ $t('plan.width') }}:</span>
<span class="value">{{ plan.entryWidth }} mm</span>
</div>
<div class="detail-item">
<span class="label">重量:</span>
<span class="label">{{ $t('plan.weight') }}:</span>
<span class="value">{{ plan.entryWeight }} t</span>
</div>
</div>
</div>
<div class="card-actions">
<el-button size="mini" type="text" @click.stop="handleUpdate(plan)" icon="el-icon-edit">
编辑
{{ $t('plan.edit') }}
</el-button>
<el-button size="mini" type="text" @click.stop="handleDelete(plan)" icon="el-icon-delete">
删除
{{ $t('plan.delete') }}
</el-button>
</div>
</el-card>
@@ -75,7 +75,7 @@
<el-tab-pane name="pending">
<span slot="label">
<i class="el-icon-s-order"></i>
生产队列
{{ $t('plan.productionQueue') }}
<el-badge :value="pendingPlans.length" class="tab-badge" />
</span>
<div v-loading="loading" class="plan-list">
@@ -102,9 +102,9 @@
plan.status === 'READY' ? 'primary' : 'info'"
size="mini"
>
{{ plan.status === 'PRODUCING' ? '生产中' :
plan.status === 'ONLINE' ? '在机' :
plan.status === 'READY' ? '就绪' : '新建' }}
{{ plan.status === 'PRODUCING' ? $t('plan.producing') :
plan.status === 'ONLINE' ? $t('plan.online') :
plan.status === 'READY' ? $t('plan.ready') : $t('plan.new') }}
</el-tag>
</div>
<div class="plan-content">
@@ -129,7 +129,7 @@
</div>
</div>
<div v-if="pendingPlans.length === 0" class="empty-text">
暂无生产计划
{{ $t('plan.noProductionPlan') }}
</div>
</div>
</el-tab-pane>
@@ -138,7 +138,7 @@
<el-tab-pane name="history">
<span slot="label">
<i class="el-icon-document-checked"></i>
历史记录
{{ $t('plan.history') }}
<el-badge :value="historyPlans.length" class="tab-badge" />
</span>
<div class="plan-list">
@@ -151,7 +151,7 @@
>
<div class="plan-status">
<span class="status-dot status-history"></span>
<el-tag type="info" size="mini">已完成</el-tag>
<el-tag type="info" size="mini">{{ $t('plan.completed') }}</el-tag>
</div>
<div class="plan-content">
<div class="plan-main">
@@ -174,7 +174,7 @@
</div>
</div>
<div v-if="historyPlans.length === 0" class="empty-text">
暂无历史记录
{{ $t('plan.noHistory') }}
</div>
</div>
</el-tab-pane>
@@ -187,14 +187,14 @@
<div v-if="currentRow" class="detail-section">
<div class="section-header">
<i class="el-icon-data-line"></i>
<span>计划详情与工艺参数</span>
<span>{{ $t('plan.planDetailAndProcessParams') }}</span>
</div>
<!-- 整合的详情卡片 -->
<el-card class="detail-card-unified" shadow="never">
<el-tabs v-model="activeTab" type="border-card">
<!-- 基础信息标签页 -->
<el-tab-pane label="基础信息" name="basic">
<el-tab-pane :label="$t('plan.basicInfo')" name="basic">
<el-descriptions :column="3" border size="small">
<el-descriptions-item label="计划号">{{ currentRow.planid }}</el-descriptions-item>
<el-descriptions-item label="钢卷号">{{ currentRow.coilid }}</el-descriptions-item>
@@ -211,10 +211,10 @@
</el-tab-pane>
<!-- 工艺参数标签页 -->
<el-tab-pane label="工艺参数" name="process" v-loading="setupLoading">
<el-tab-pane :label="$t('plan.processParams')" name="process" v-loading="setupLoading">
<setup-pane v-if="!setupLoading && setupForm" :setup-form="setupForm" />
<div v-if="!setupLoading && !setupForm" class="empty-text">
暂无工艺参数数据
{{ $t('plan.noProcessParams') }}
</div>
</el-tab-pane>
</el-tabs>
@@ -222,7 +222,7 @@
</div>
<div v-else class="empty-section">
<i class="el-icon-info"></i>
<p>请从左侧选择一个计划查看详情</p>
<p>{{ $t('plan.pleaseSelectPlan') }}</p>
</div>
</el-col>
</el-row>
@@ -235,17 +235,17 @@
<el-form :model="form" ref="form" label-width="90px" :rules="rules" size="mini" class="plan-base-form">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="计划ID" prop="planid">
<el-form-item :label="$t('plan.planId')" prop="planid">
<el-input v-model="form.planid" placeholder="请输入计划ID" maxLength="32"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="钢卷号" prop="coilid">
<el-form-item :label="$t('plan.coilid')" prop="coilid">
<el-input v-model="form.coilid" placeholder="请输入钢卷号" maxLength="32"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="钢种" prop="steelGrade">
<el-form-item :label="$t('plan.steelGrade')" prop="steelGrade">
<el-select v-model="form.steelGrade" placeholder="请选择钢种">
<el-option v-for="item in steelGradeList" :key="item.gradeid" :label="item.name"
:value="item.gradeid"></el-option>
@@ -253,59 +253,59 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="厚度(mm)" prop="entryThick">
<el-form-item :label="$t('plan.thickness')" prop="entryThick">
<el-input v-model="form.entryThick" placeholder="请输入入口厚度" type="number" step="0.01" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="宽度(mm)" prop="entryWidth">
<el-form-item :label="$t('plan.width')" prop="entryWidth">
<el-input v-model="form.entryWidth" placeholder="请输入入口宽度" type="number" step="1" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="屈服点" prop="yieldPoint">
<el-form-item :label="$t('plan.yieldPoint')" prop="yieldPoint">
<el-input v-model="form.yieldPoint" placeholder="请输入屈服点" type="number" step="0.01" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="重量(t)" prop="entryWeight">
<el-form-item :label="$t('plan.weight')" prop="entryWeight">
<el-input v-model="form.entryWeight" placeholder="请输入入口重量" type="number" step="0.01" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="长度(mm)" prop="entryLength">
<el-form-item :label="$t('plan.length')" prop="entryLength">
<el-input v-model="form.entryLength" placeholder="请输入入口长度" type="number" step="1" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="外径(mm)" prop="entryOuterDiameter">
<el-form-item :label="$t('plan.outerDiameter')" prop="entryOuterDiameter">
<el-input v-model="form.entryOuterDiameter" placeholder="请输入入口外径" type="number" step="1"
min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="延伸率(%)" prop="spmElongation">
<el-form-item :label="$t('plan.elongation')" prop="spmElongation">
<el-input v-model="form.spmElongation" placeholder="请输入延伸率" type="number" step="0.01" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="轧制力" prop="spmRollforce">
<el-form-item :label="$t('plan.spmRollforce')" prop="spmRollforce">
<el-input v-model="form.spmRollforce" placeholder="请输入SPM轧制力" type="number" step="0.01"
min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出口目标长度" prop="exitLengthTar">
<el-form-item :label="$t('plan.exitLengthTar')" prop="exitLengthTar">
<el-input v-model="form.exitLengthTar" placeholder="请输入出口目标长度(mm)" type="number" step="1" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出口目标厚度" prop="exitThickTar">
<el-form-item :label="$t('plan.exitThickTar')" prop="exitThickTar">
<el-input v-model="form.exitThickTar" placeholder="请输入出口目标厚度(mm)" type="number" step="0.01" min="0"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出口目标宽度" prop="exitWidthTar">
<el-form-item :label="$t('plan.exitWidthTar')" prop="exitWidthTar">
<el-input v-model="form.exitWidthTar" placeholder="请输入出口目标宽度(mm)" type="number" step="1" min="0"></el-input>
</el-form-item>
</el-col>
@@ -314,8 +314,8 @@
<div class="plan-dialog-actions">
<el-checkbox v-if="!form.id" v-model="spmFlag"
label="生成工艺参数(建议先填写完成基础信息再勾选此选项)"></el-checkbox>
<el-divider content-position="left" v-if="spmFlag">工艺参数</el-divider>
:label="$t('plan.generateProcessParams')"></el-checkbox>
<el-divider content-position="left" v-if="spmFlag">{{ $t('plan.processParams') }}</el-divider>
<setup-form v-if="spmFlag" ref="setupFormRef" :income="form" :steel-grade-options="steelGradeList"
:plan-history="planList" :show-recommendation-panel="false" @input="handleSetupInput"
@recommendation-change="handleProcessRecommendation" />
@@ -333,8 +333,8 @@
</div>
<!-- 弹窗底部按钮 -->
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="saveLoading">保存</el-button>
<el-button @click="dialogVisible = false">{{ $t('plan.cancel') }}</el-button>
<el-button type="primary" @click="submitForm" :loading="saveLoading">{{ $t('plan.save') }}</el-button>
</div>
</el-dialog>
</div>
@@ -817,7 +817,7 @@ export default {
// 新增计划(重置表单+打开弹窗)
handleAdd() {
this.dialogTitle = "新增计划"; // 设置弹窗标题
this.dialogTitle = this.$t('plan.addPlan'); // 设置弹窗标题
// 重置表单数据(默认值与接口要求对齐)
this.form = {
dummyCoilFlag: 0,
@@ -932,7 +932,7 @@ export default {
// 编辑计划(回显行数据+打开弹窗)
handleUpdate(row) {
this.dialogTitle = "编辑计划"; // 设置弹窗标题
this.dialogTitle = this.$t('plan.edit'); // 设置弹窗标题
// 深拷贝行数据(避免修改原表格数据)
this.form = JSON.parse(JSON.stringify(row));
this.spmFlag = false
@@ -988,10 +988,10 @@ export default {
// 删除计划(单个删除,支持批量扩展)
handleDelete(row) {
// 弹窗确认(危险操作二次确认)
this.$confirm(`确定删除ID: ${row.id} 的计划?`, "确认删除", {
this.$confirm(`确定删除ID: ${row.id} 的计划?`, this.$t('plan.confirmDelete'), {
type: "danger",
confirmButtonText: "确认",
cancelButtonText: "取消"
confirmButtonText: this.$t('plan.confirm'),
cancelButtonText: this.$t('plan.cancel')
})
.then(() => {
row.deleteLoading = true; // 开启行删除按钮加载
@@ -999,13 +999,13 @@ export default {
delPlan([row.id])
.then((res) => {
row.deleteLoading = false; // 关闭加载
this.$message.success("删除成功");
this.$message.success(this.$t('plan.deleteSuccess'));
this.getList(); // 重新加载列表
})
.catch((err) => {
row.deleteLoading = false; // 关闭加载
console.error("删除计划失败:", err);
this.$message.error("删除失败,请重试");
this.$message.error(this.$t('plan.deleteFailed'));
});
})
},
@@ -1024,7 +1024,7 @@ export default {
const start = new Date(formData.startDate);
const end = new Date(formData.endDate);
if (start > end) {
this.$message.warning("开始时间不能晚于结束时间");
this.$message.warning(this.$t('plan.startTimeNotLaterThanEndTime'));
return;
}
}
@@ -1041,11 +1041,11 @@ export default {
this.saveLoading = false; // 关闭加载
console.log("服务器响应:", res);
if (res.code === 200) {
this.$message.success(formData.id ? "更新计划成功" : "新增计划成功");
this.$message.success(formData.id ? this.$t('plan.updateSuccess') : this.$t('plan.addSuccess'));
this.dialogVisible = false; // 关闭弹窗
this.getList(); // 重新加载列表
} else {
this.$message.error(res.msg || (formData.id ? "更新失败" : "新增失败"));
this.$message.error(res.msg || (formData.id ? this.$t('plan.updateFailed') : this.$t('plan.addFailed')));
}
})
.catch((err) => {

View File

@@ -4,35 +4,35 @@
<div class="header-title">
<i class="el-icon-document"></i>
<div class="title-text">
<span>停机报表</span>
<small>请选择时间范围后查看数据</small>
<span>{{ $t('report.stop.title') }}</span>
<small>{{ $t('report.stop.subtitle') }}</small>
</div>
</div>
<el-tag size="small" effect="plain">停机</el-tag>
<el-tag size="small" effect="plain">{{ $t('report.stop.stopTag') }}</el-tag>
</div>
<div class="time-selector-card" v-if="!hasSelectedTime">
<div class="selector-header">
<i class="el-icon-calendar"></i>
<span>请选择查询日期范围</span>
<span>{{ $t('report.stop.pleaseSelectDateRange') }}</span>
</div>
<div class="selector-content">
<el-form :inline="true" size="small">
<el-form-item label="开始日期">
<el-form-item :label="$t('report.stop.startDate')">
<el-date-picker
v-model="timeRange.startTime"
type="date"
placeholder="选择开始日期"
:placeholder="$t('report.stop.chooseStartDate')"
value-format="yyyy-MM-dd"
style="width: 200px;"
:clearable="false"
/>
</el-form-item>
<el-form-item label="结束日期">
<el-form-item :label="$t('report.stop.endDate')">
<el-date-picker
v-model="timeRange.endTime"
type="date"
placeholder="选择结束日期"
:placeholder="$t('report.stop.chooseEndDate')"
value-format="yyyy-MM-dd"
style="width: 200px;"
:clearable="false"
@@ -40,9 +40,9 @@
</el-form-item>
<el-form-item>
<el-button type="primary" :disabled="!canQuery" icon="el-icon-search" @click="handleTimeConfirm">
查询
{{ $t('report.stop.query') }}
</el-button>
<el-button icon="el-icon-refresh" @click="handleTimeReset">重置</el-button>
<el-button icon="el-icon-refresh" @click="handleTimeReset">{{ $t('report.stop.reset') }}</el-button>
</el-form-item>
</el-form>
</div>
@@ -51,18 +51,18 @@
<div class="report-content" v-else>
<div class="content-toolbar">
<div class="toolbar-info">
<span class="info-label">报表类型</span>
<span class="info-value">停机报表</span>
<span class="info-label">{{ $t('report.stop.reportType') }}</span>
<span class="info-value">{{ $t('report.stop.title') }}</span>
<span class="info-divider">|</span>
<span class="info-label">时间范围</span>
<span class="info-label">{{ $t('report.stop.timeRange') }}</span>
<span class="info-range">{{ displayTimeRange }}</span>
</div>
<el-button type="text" icon="el-icon-refresh-left" @click="handleReturn">重新选择时间</el-button>
<el-button type="text" icon="el-icon-refresh-left" @click="handleReturn">{{ $t('report.stop.reselectTime') }}</el-button>
</div>
<ReportBody
v-loading="loading"
title="停机报表"
:title="$t('report.stop.title')"
:summary="reportSummary"
:dataset="reportDetail"
:columns="columns"
@@ -89,16 +89,6 @@ export default {
},
reportSummary: [],
reportDetail: [],
columns: [
{ label: '钢卷号', prop: 'coilid' },
{ label: '班次号', prop: 'shift' },
{ label: '组', prop: 'area' },
{ label: '开始时间', prop: 'startDate' },
{ label: '结束时间', prop: 'endDate' },
{ label: '持续时间[分钟]', prop: 'duration' },
{ label: '停机类型', prop: 'unit' },
{ label: '备注', prop: 'remark' }
]
}
},
computed: {
@@ -109,9 +99,21 @@ export default {
if (!this.canQuery) return '-'
return `${this.timeRange.startTime}${this.timeRange.endTime}`
},
columns() {
return [
{ label: this.$t('report.stop.coilid'), prop: 'coilid' },
{ label: this.$t('report.stop.shift'), prop: 'shift' },
{ label: this.$t('report.stop.area'), prop: 'area' },
{ label: this.$t('report.stop.startTime'), prop: 'startDate' },
{ label: this.$t('report.stop.endTime'), prop: 'endDate' },
{ label: this.$t('report.stop.duration'), prop: 'duration' },
{ label: this.$t('report.stop.stopType'), prop: 'unit' },
{ label: this.$t('report.stop.remark'), prop: 'remark' }
]
},
overviewInfo() {
return {
reportLabel: '停机报表',
reportLabel: this.$t('report.stop.title'),
rangeText: this.displayTimeRange
}
}

View File

@@ -2,39 +2,39 @@
<div class="filter-container">
<div class="filter-panel">
<div class="panel-header">
<h4>历史检索</h4>
<h4>{{ $t('roller.historySearch') }}</h4>
</div>
<div class="filter-item">
<div class="filter-label"> 按时间</div>
<div class="filter-label"> {{ $t('roller.byTime') }}</div>
<div class="filter-content time-range">
<div class="time-label">开始时间</div>
<div class="time-label">{{ $t('roller.startTime') }}</div>
<el-date-picker
v-model="startDate"
type="date"
placeholder="选择日期"
:placeholder="$t('roller.selectDate')"
value-format="yyyy-MM-dd"
style="width: 140px"
></el-date-picker>
<el-time-picker
v-model="startTime"
format="HH:mm"
placeholder="选择时间"
:placeholder="$t('roller.selectTime')"
value-format="HH:mm"
style="width: 140px; margin-left: 5px"
></el-time-picker>
<div class="time-label" style="margin-top: 10px">结束时间</div>
<div class="time-label" style="margin-top: 10px">{{ $t('roller.endTime') }}</div>
<el-date-picker
v-model="endDate"
type="date"
placeholder="选择日期"
:placeholder="$t('roller.selectDate')"
value-format="yyyy-MM-dd"
style="width: 140px"
></el-date-picker>
<el-time-picker
v-model="endTime"
format="HH:mm"
placeholder="选择时间"
:placeholder="$t('roller.selectTime')"
value-format="HH:mm"
style="width: 140px; margin-left: 5px"
></el-time-picker>
@@ -42,10 +42,10 @@
</div>
<div class="filter-item">
<div class="filter-label"> 按换辊号</div>
<div class="filter-label"> {{ $t('roller.byChangeId') }}</div>
<div class="filter-content">
<div class="input-label">换辊号</div>
<el-select filterable v-model="queryParams.changeId" placeholder="请选择" clearable style="width: 240px">
<div class="input-label">{{ $t('roller.changeId') }}</div>
<el-select filterable v-model="queryParams.changeId" :placeholder="$t('roller.pleaseSelect')" clearable style="width: 240px">
<el-option
v-for="item in changeIdOptions"
:key="item"
@@ -57,10 +57,10 @@
</div>
<div class="filter-item">
<div class="filter-label"> 按轧辊号</div>
<div class="filter-label"> {{ $t('roller.byRollId') }}</div>
<div class="filter-content">
<div class="input-label">轧辊号</div>
<el-select filterable v-model="queryParams.rollId" placeholder="请选择" clearable style="width: 240px">
<div class="input-label">{{ $t('roller.rollId') }}</div>
<el-select filterable v-model="queryParams.rollId" :placeholder="$t('roller.pleaseSelect')" clearable style="width: 240px">
<el-option
v-for="item in rollIdOptions"
:key="item"
@@ -72,8 +72,8 @@
</div>
<div class="filter-buttons">
<el-button type="primary" @click="handleSearch"> </el-button>
<el-button @click="resetQuery"> </el-button>
<el-button type="primary" @click="handleSearch">{{ $t('roller.query') }}</el-button>
<el-button @click="resetQuery">{{ $t('roller.reset') }}</el-button>
</div>
</div>
</div>
@@ -116,11 +116,11 @@ export default {
if (res.code === 200 && res.data) {
this.changeIdOptions = res.data
} else {
this.$message.error(res.msg || '获取换辊号列表失败')
this.$message.error(res.msg || this.$t('roller.getChangeIdListFailed'))
}
}).catch(error => {
console.error('获取换辊号列表失败', error)
this.$message.error('获取换辊号列表失败' + (error.message || '未知错误'))
this.$message.error(this.$t('roller.getChangeIdListFailed') + '' + (error.message || '未知错误'))
})
},
@@ -131,11 +131,11 @@ export default {
if (res.code === 200 && res.data) {
this.rollIdOptions = res.data
} else {
this.$message.error(res.msg || '获取轧辊号列表失败')
this.$message.error(res.msg || this.$t('roller.getRollIdListFailed'))
}
}).catch(error => {
console.error('获取轧辊号列表失败', error)
this.$message.error('获取轧辊号列表失败' + (error.message || '未知错误'))
this.$message.error(this.$t('roller.getRollIdListFailed') + '' + (error.message || '未知错误'))
})
},

View File

@@ -12,23 +12,23 @@
@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">
<el-table-column prop="changeid" :label="$t('roller.changeId')" align="center" show-overflow-tooltip />
<el-table-column prop="rollid" :label="$t('roller.rollId')" align="center" show-overflow-tooltip />
<el-table-column prop="standid" :label="$t('roller.standId')" align="center" show-overflow-tooltip />
<el-table-column :label="$t('roller.position')" 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" >
<el-table-column :label="$t('roller.type')" 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-column prop="changeType" :label="$t('roller.changeType')" align="center" show-overflow-tooltip />
<el-table-column prop="changeTime" :label="$t('roller.changeTime')" align="center" show-overflow-tooltip />
<el-table-column prop="instalTime" :label="$t('roller.installTime')" align="center" show-overflow-tooltip />
<el-table-column prop="deinstalTime" :label="$t('roller.dismantleTime')" align="center" show-overflow-tooltip />
</el-table>
<transition name="el-fade-in-linear">
<div
@@ -37,14 +37,14 @@
:style="tooltipStyle"
ref="rowTooltip"
>
<div class="tooltip-title">详细信息</div>
<div class="tooltip-title">{{ $t('roller.detailedInfo') }}</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="label">{{ $t(`roller.${field.i18nKey}`) }}</span>
<span class="value">{{ formatTooltipValue(hoveredRow, field) }}</span>
</div>
</div>
@@ -90,26 +90,26 @@ export default {
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' }
{ i18nKey: 'changeId', prop: 'changeid' },
{ i18nKey: 'rollId', prop: 'rollid' },
{ i18nKey: 'standId', prop: 'standid' },
{ i18nKey: 'position', prop: 'position', dict: 'main_roll_position' },
{ i18nKey: 'type', prop: 'type', dict: 'main_roll_type' },
{ i18nKey: 'changeType', prop: 'changeType' },
{ i18nKey: 'changeTime', prop: 'changeTime' },
{ i18nKey: 'installTime', prop: 'instalTime' },
{ i18nKey: 'dismantleTime', prop: 'deinstalTime' },
{ i18nKey: 'diameter', prop: 'diameter' },
{ i18nKey: 'roughness', prop: 'rough' },
{ i18nKey: 'crown', prop: 'crown' },
{ i18nKey: 'composition', prop: 'composition' },
{ i18nKey: 'grindCount', prop: 'grindCount' },
{ i18nKey: 'rolledWeight', prop: 'rolledWeight' },
{ i18nKey: 'rolledCount', prop: 'rolledCount' },
{ i18nKey: 'rolledLength', prop: 'rolledLength' },
{ i18nKey: 'totalRolledWeight', prop: 'totalRolledWeight' },
{ i18nKey: 'totalRolledLength', prop: 'totalRolledLength' },
{ i18nKey: 'totalRolledCount', prop: 'totalRolledCount' }
]
}
},
@@ -146,7 +146,7 @@ export default {
const loading = this.$loading({
lock: true,
text: '加载中...',
text: this.$t('roller.loading'),
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
@@ -164,14 +164,14 @@ export default {
if (item.deinstalTime) item.deinstalTime = this.formatDate(item.deinstalTime)
})
} else {
this.$message.error(res.msg || '获取数据失败')
this.$message.error(res.msg || this.$t('roller.getDataFailed'))
this.tableData = []
this.pagination.total = 0
}
})
.catch(error => {
console.error('获取轧辊历史数据失败', error)
this.$message.error('获取数据失败' + (error.message || '未知错误'))
this.$message.error(this.$t('roller.getDataFailed') + '' + (error.message || '未知错误'))
this.tableData = []
this.pagination.total = 0
})

View File

@@ -2,7 +2,7 @@
<template>
<div class="online-roll">
<div class="panel-header">
<h4>在线辊</h4>
<h4>{{ $t('roller.onlineRollers') }}</h4>
</div>
<el-table
:data="onlineData"
@@ -14,24 +14,24 @@
:show-overflow-tooltip="true"
style="width: 100%; table-layout: fixed;"
>
<el-table-column prop="rollid" label="轧辊号" show-overflow-tooltip />
<el-table-column label="位置" align="center" prop="position" show-overflow-tooltip>
<el-table-column prop="rollid" :label="$t('roller.rollId')" show-overflow-tooltip />
<el-table-column :label="$t('roller.position')" align="center" prop="position" show-overflow-tooltip>
<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" show-overflow-tooltip>
<el-table-column :label="$t('roller.type')" align="center" prop="type" show-overflow-tooltip>
<template slot-scope="scope">
<dict-tag :options="dict.type.main_roll_type" :value="scope.row.type" />
</template>
</el-table-column>
<el-table-column prop="diameter" label="直径" show-overflow-tooltip />
<el-table-column prop="rough" label="粗糙度"show-overflow-tooltip />
<el-table-column prop="crown" label="凸度" show-overflow-tooltip />
<el-table-column prop="rolledLength" label="长度" show-overflow-tooltip />
<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="diameter" :label="$t('roller.diameter')" show-overflow-tooltip />
<el-table-column prop="rough" :label="$t('roller.roughness')" show-overflow-tooltip />
<el-table-column prop="crown" :label="$t('roller.crown')" show-overflow-tooltip />
<el-table-column prop="rolledLength" :label="$t('roller.rolledLength')" show-overflow-tooltip />
<el-table-column prop="rolledWeight" :label="$t('roller.rolledWeight')" show-overflow-tooltip />
<el-table-column prop="rolledCount" :label="$t('roller.rolledCount')" show-overflow-tooltip />
<el-table-column prop="instalTime" :label="$t('roller.installTime')" 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 />

View File

@@ -2,10 +2,10 @@
<template>
<div class="standby-panel" v-loading="loading">
<div class="panel-header">
<h4>准备辊</h4>
<h4>{{ $t('roller.standbyRollers') }}</h4>
<div class="header-actions">
<el-button type="primary" size="mini" icon="el-icon-box" @click="handleBackup">备辊</el-button>
<el-button type="primary" size="mini" icon="el-icon-upload2" @click="handleOnline">上线</el-button>
<el-button type="primary" size="mini" icon="el-icon-box" @click="handleBackup">{{ $t('roller.backup') }}</el-button>
<el-button type="primary" size="mini" icon="el-icon-upload2" @click="handleOnline">{{ $t('roller.online') }}</el-button>
</div>
</div>
<el-table
@@ -17,12 +17,12 @@
:show-overflow-tooltip="true"
style="width: 100%; table-layout: fixed;"
>
<el-table-column label="位置/类型" show-overflow-tooltip>
<el-table-column :label="$t('roller.positionType')" show-overflow-tooltip>
<template #default="scope">
{{ getRollerTitle(scope.row.type, scope.row.position) }}
</template>
</el-table-column>
<el-table-column prop="rollid" label="轧辊号" show-overflow-tooltip>
<el-table-column prop="rollid" :label="$t('roller.rollId')" show-overflow-tooltip>
<template #default="scope">
<el-select
size="mini"
@@ -31,26 +31,26 @@
allow-create
v-model="scope.row.rollid"
style="width: 100%;"
placeholder="请选择轧辊号"
:placeholder="$t('roller.pleaseSelectRollId')"
@change="handleChange(scope.row)"
>
<el-option v-for="item in scope.row.data" :key="item.rollid" :label="item.rollid" :value="item.rollid" />
</el-select>
</template>
</el-table-column>
<el-table-column prop="diameter" label="直径" show-overflow-tooltip>
<el-table-column prop="diameter" :label="$t('roller.diameter')" show-overflow-tooltip>
<template #default="scope">
<el-input style="width: 100%;" 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="$t('roller.pleaseInputDiameter')" />
</template>
</el-table-column>
<el-table-column prop="rough" label="粗糙度" show-overflow-tooltip>
<el-table-column prop="rough" :label="$t('roller.roughness')" show-overflow-tooltip>
<template #default="scope">
<el-input style="width: 100%;" 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="$t('roller.pleaseInputRoughness')" />
</template>
</el-table-column>
<el-table-column prop="crown" label="凹度" show-overflow-tooltip>
<el-table-column prop="crown" :label="$t('roller.crown')" show-overflow-tooltip>
<template #default="scope">
<el-input style="width: 100%;" 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="$t('roller.pleaseInputCrown')" />
</template>
</el-table-column>
</el-table>
@@ -118,13 +118,13 @@ export default {
methods: {
getRollerTitle(type, position) {
const typeDict = {
WORK: '工作辊',
BACKUP: "支撑辊",
INTERMEDIATE: "中间辊",
WORK: this.$t('roller.workRoll'),
BACKUP: this.$t('roller.backupRoll'),
INTERMEDIATE: this.$t('roller.intermediateRoll'),
}
const positionDict = {
TOP: "上",
BOTTOM: "下",
TOP: this.$t('roller.top'),
BOTTOM: this.$t('roller.bottom'),
}
return positionDict[position] + typeDict[type]
},

View File

@@ -4,13 +4,13 @@
<div class="monitor-header">
<div class="header-left">
<div class="status-indicator" :class="{ active: isConnected }"></div>
<h1 class="main-title">过程跟踪实时监控系统</h1>
<h1 class="main-title">{{ $t('track.title') }}</h1>
</div>
<div class="header-right">
<div class="connection-info">
<span class="label">连接状态</span>
<span class="label">{{ $t('track.connectionStatus') }}</span>
<span class="value" :class="{ connected: isConnected }">
{{ isConnected ? '已连接' : '连接中...' }}
{{ isConnected ? $t('track.connected') : $t('track.connecting') }}
</span>
</div>
<div class="time-display">{{ currentTime }}</div>
@@ -20,7 +20,7 @@
<!-- 数据类型选择器 -->
<div class="type-selector-panel">
<div class="selector-wrapper">
<label class="selector-label">数据类型</label>
<label class="selector-label">{{ $t('track.dataType') }}</label>
<el-select v-model="currentType" @change="handleTypeChange" size="small" class="type-select">
<el-option
v-for="type in types"
@@ -35,11 +35,11 @@
</div>
<div class="stats-info">
<div class="stat-item">
<span class="stat-label">数据包</span>
<span class="stat-label">{{ $t('track.packetCount') }}</span>
<span class="stat-value">{{ messageCount }}</span>
</div>
<div class="stat-item">
<span class="stat-label">刷新率</span>
<span class="stat-label">{{ $t('track.refreshRate') }}</span>
<span class="stat-value">{{ refreshRate }} Hz</span>
</div>
</div>
@@ -52,10 +52,10 @@
<div class="panel-header">
<div class="header-title">
<i class="el-icon-s-data"></i>
<span>入口段数据监控</span>
<span>{{ $t('track.entryData') }}</span>
</div>
<div class="panel-badges">
<span class="badge success" v-if="chartData.entry.time.length > 0">实时</span>
<span class="badge success" v-if="chartData.entry.time.length > 0">{{ $t('track.realTime') }}</span>
<span class="badge info">{{ chartData.entry.time.length }}/{{ maxDataPoints }}</span>
</div>
</div>
@@ -63,22 +63,22 @@
<!-- 实时数据卡片 -->
<div class="data-cards">
<div class="data-card">
<div class="card-label">入口张力1</div>
<div class="card-label">{{ $t('track.entryTension1') }}</div>
<div class="card-value">{{ getLatestValue('entry', 'tensionPorBr1') }}</div>
<div class="card-unit">kN</div>
</div>
<div class="data-card">
<div class="card-label">入口张力2</div>
<div class="card-label">{{ $t('track.entryTension2') }}</div>
<div class="card-value">{{ getLatestValue('entry', 'tensionBr1Br2') }}</div>
<div class="card-unit">kN</div>
</div>
<div class="data-card">
<div class="card-label">入口张力3</div>
<div class="card-label">{{ $t('track.entryTension3') }}</div>
<div class="card-value">{{ getLatestValue('entry', 'tensionBr2Br3') }}</div>
<div class="card-unit">kN</div>
</div>
<div class="data-card highlight">
<div class="card-label">带钢速度</div>
<div class="card-label">{{ $t('track.stripSpeed') }}</div>
<div class="card-value">{{ getLatestValue('entry', 'stripSpeed') }}</div>
<div class="card-unit">m/min</div>
</div>
@@ -93,10 +93,10 @@
<div class="panel-header">
<div class="header-title">
<i class="el-icon-sunny"></i>
<span>炉温数据监控</span>
<span>{{ $t('track.furnaceData') }}</span>
</div>
<div class="panel-badges">
<span class="badge success" v-if="chartData.furnace.time.length > 0">实时</span>
<span class="badge success" v-if="chartData.furnace.time.length > 0">{{ $t('track.realTime') }}</span>
<span class="badge info">{{ chartData.furnace.time.length }}/{{ maxDataPoints }}</span>
</div>
</div>
@@ -104,17 +104,17 @@
<!-- 实时数据卡片 -->
<div class="data-cards">
<div class="data-card temperature">
<div class="card-label">PH炉实际温度</div>
<div class="card-label">{{ $t('track.phFurnaceTempActual') }}</div>
<div class="card-value">{{ getLatestValue('furnace', 'phFurnaceTemperatureActual') }}</div>
<div class="card-unit">°C</div>
</div>
<div class="data-card temperature">
<div class="card-label">NOF1炉实际温度</div>
<div class="card-label">{{ $t('track.nof1FurnaceTempActual') }}</div>
<div class="card-value">{{ getLatestValue('furnace', 'nof1FurnaceTemperatureActual') }}</div>
<div class="card-unit">°C</div>
</div>
<div class="data-card">
<div class="card-label">NOF1炉设定温度</div>
<div class="card-label">{{ $t('track.nof1FurnaceTempSet') }}</div>
<div class="card-value">{{ getLatestValue('furnace', 'nof1FurnaceTemperatureSet') }}</div>
<div class="card-unit">°C</div>
</div>
@@ -129,10 +129,10 @@
<div class="panel-header">
<div class="header-title">
<i class="el-icon-brush"></i>
<span>涂层段数据监控</span>
<span>{{ $t('track.coatData') }}</span>
</div>
<div class="panel-badges">
<span class="badge success" v-if="chartData.coat.time.length > 0">实时</span>
<span class="badge success" v-if="chartData.coat.time.length > 0">{{ $t('track.realTime') }}</span>
<span class="badge info">{{ chartData.coat.time.length }}/{{ maxDataPoints }}</span>
</div>
</div>
@@ -140,22 +140,22 @@
<!-- 实时数据卡片 -->
<div class="data-cards">
<div class="data-card">
<div class="card-label">顶部涂层重量</div>
<div class="card-label">{{ $t('track.topCoatWeight') }}</div>
<div class="card-value">{{ getLatestValue('coat', 'avrCoatingWeightTop') }}</div>
<div class="card-unit">g/</div>
</div>
<div class="data-card">
<div class="card-label">底部涂层重量</div>
<div class="card-label">{{ $t('track.bottomCoatWeight') }}</div>
<div class="card-value">{{ getLatestValue('coat', 'avrCoatingWeightBottom') }}</div>
<div class="card-unit">g/</div>
</div>
<div class="data-card">
<div class="card-label">气刀压力</div>
<div class="card-label">{{ $t('track.airKnifePressure') }}</div>
<div class="card-value">{{ getLatestValue('coat', 'airKnifePressure') }}</div>
<div class="card-unit">kPa</div>
</div>
<div class="data-card highlight">
<div class="card-label">出口速度</div>
<div class="card-label">{{ $t('track.exitSpeed') }}</div>
<div class="card-value">{{ getLatestValue('coat', 'stripSpeedTmExit') }}</div>
<div class="card-unit">m/min</div>
</div>
@@ -170,10 +170,10 @@
<div class="panel-header">
<div class="header-title">
<i class="el-icon-document-checked"></i>
<span>出口段数据监控</span>
<span>{{ $t('track.exitData') }}</span>
</div>
<div class="panel-badges">
<span class="badge success" v-if="chartData.exit.time.length > 0">实时</span>
<span class="badge success" v-if="chartData.exit.time.length > 0">{{ $t('track.realTime') }}</span>
<span class="badge info">{{ chartData.exit.time.length }}/{{ maxDataPoints }}</span>
</div>
</div>
@@ -181,17 +181,17 @@
<!-- 实时数据卡片 -->
<div class="data-cards">
<div class="data-card">
<div class="card-label">出口张力1</div>
<div class="card-label">{{ $t('track.exitTension1') }}</div>
<div class="card-value">{{ getLatestValue('exit', 'tensionBr8Br9') }}</div>
<div class="card-unit">kN</div>
</div>
<div class="data-card">
<div class="card-label">出口张力2</div>
<div class="card-label">{{ $t('track.exitTension2') }}</div>
<div class="card-value">{{ getLatestValue('exit', 'tensionBr9Tr') }}</div>
<div class="card-unit">kN</div>
</div>
<div class="data-card highlight">
<div class="card-label">出口速度</div>
<div class="card-label">{{ $t('track.exitSpeed') }}</div>
<div class="card-value">{{ getLatestValue('exit', 'speedExitSection') }}</div>
<div class="card-unit">m/min</div>
</div>
@@ -209,12 +209,12 @@
<i class="el-icon-view"></i>
</div>
<h3 class="card-title">{{ getCurrentTypeLabel() }}</h3>
<p class="card-desc">当前数据类型不支持图表展示原始数据如下</p>
<p class="card-desc">{{ $t('track.noChartSupport') }}</p>
</div>
<div class="raw-data-display">
<div class="raw-data-header">
<span class="raw-title">原始数据</span>
<el-button size="mini" @click="copyRawData" icon="el-icon-document-copy">复制</el-button>
<span class="raw-title">{{ $t('track.rawData') }}</span>
<el-button size="mini" @click="copyRawData" icon="el-icon-document-copy">{{ $t('track.copy') }}</el-button>
</div>
<pre class="raw-content">{{ formattedRawData }}</pre>
</div>
@@ -231,12 +231,12 @@ export default {
return {
socket: null,
types: [
{ value: 'alarm', label: '告警信息', desc: '系统告警与异常' },
{ value: 'track_position', label: '位置跟踪', desc: '钢卷位置信息' },
{ value: 'calc_setup_result', label: '设定计算', desc: '计算结果数据' },
{ value: 'track_measure', label: '过程测量', desc: '实时测量数据' },
{ value: 'track_signal', label: '信号跟踪', desc: '信号状态数据' },
{ value: 'track_matmap', label: '物料映射', desc: '物料映射关系' }
{ value: 'alarm', label: this.$t('track.alarmInfo'), desc: this.$t('track.alarmDesc') },
{ value: 'track_position', label: this.$t('track.positionTrack'), desc: this.$t('track.positionDesc') },
{ value: 'calc_setup_result', label: this.$t('track.calcSetupResult'), desc: this.$t('track.calcDesc') },
{ value: 'track_measure', label: this.$t('track.processMeasure'), desc: this.$t('track.measureDesc') },
{ value: 'track_signal', label: this.$t('track.signalTrack'), desc: this.$t('track.signalDesc') },
{ value: 'track_matmap', label: this.$t('track.matmap'), desc: this.$t('track.matmapDesc') }
],
currentType: 'track_measure',
isConnected: false,
@@ -284,7 +284,7 @@ export default {
},
computed: {
formattedRawData() {
if (!this.rawData) return '等待接收数据...';
if (!this.rawData) return this.$t('track.waitingData');
try {
return JSON.stringify(JSON.parse(this.rawData), null, 2);
} catch (e) {
@@ -334,9 +334,9 @@ export default {
// 复制原始数据
copyRawData() {
navigator.clipboard.writeText(this.formattedRawData).then(() => {
this.$message.success('已复制到剪贴板');
this.$message.success(this.$t('track.copySuccess'));
}).catch(() => {
this.$message.error('复制失败');
this.$message.error(this.$t('track.copyFailed'));
});
},
@@ -385,7 +385,7 @@ export default {
textStyle: { color: '#fff' }
},
legend: {
data: ['入口张力1', '入口张力2', '入口张力3', '带钢速度'],
data: [$t('track.entryTension1'), $t('track.entryTension2'), $t('track.entryTension3'), $t('track.stripSpeed')],
textStyle: { color: '#b0b0b0', fontSize: 12 },
top: 10
},
@@ -406,7 +406,7 @@ export default {
},
series: [
{
name: '入口张力1',
name: this.$t('track.entryTension1'),
type: 'line',
data: [],
smooth: true,
@@ -415,7 +415,7 @@ export default {
areaStyle: { color: 'rgba(0, 212, 255, 0.1)' }
},
{
name: '入口张力2',
name: this.$t('track.entryTension2'),
type: 'line',
data: [],
smooth: true,
@@ -423,7 +423,7 @@ export default {
itemStyle: { color: '#00ff9d' }
},
{
name: '入口张力3',
name: this.$t('track.entryTension3'),
type: 'line',
data: [],
smooth: true,
@@ -431,7 +431,7 @@ export default {
itemStyle: { color: '#ffa502' }
},
{
name: '带钢速度',
name: this.$t('track.stripSpeed'),
type: 'line',
data: [],
smooth: true,
@@ -454,7 +454,7 @@ export default {
textStyle: { color: '#fff' }
},
legend: {
data: ['PH炉实际温度', 'NOF1炉实际温度', 'NOF1炉设定温度'],
data: [$t('track.phFurnaceTempActual'), $t('track.nof1FurnaceTempActual'), $t('track.nof1FurnaceTempSet')],
textStyle: { color: '#b0b0b0', fontSize: 12 },
top: 10
},
@@ -475,7 +475,7 @@ export default {
},
series: [
{
name: 'PH炉实际温度',
name: this.$t('track.phFurnaceTempActual'),
type: 'line',
data: [],
smooth: true,
@@ -484,7 +484,7 @@ export default {
areaStyle: { color: 'rgba(255, 99, 72, 0.1)' }
},
{
name: 'NOF1炉实际温度',
name: this.$t('track.nof1FurnaceTempActual'),
type: 'line',
data: [],
smooth: true,
@@ -492,7 +492,7 @@ export default {
itemStyle: { color: '#ffa502' }
},
{
name: 'NOF1炉设定温度',
name: this.$t('track.nof1FurnaceTempSet'),
type: 'line',
data: [],
smooth: true,
@@ -515,7 +515,7 @@ export default {
textStyle: { color: '#fff' }
},
legend: {
data: ['顶部平均涂层重量', '底部平均涂层重量', '气刀压力', '出口速度'],
data: [$t('track.avrCoatingWeightTop'), $t('track.avrCoatingWeightBottom'), $t('track.airKnifePressure'), $t('track.exitSpeed')],
textStyle: { color: '#b0b0b0', fontSize: 12 },
top: 10
},
@@ -536,7 +536,7 @@ export default {
},
series: [
{
name: '顶部平均涂层重量',
name: this.$t('track.avrCoatingWeightTop'),
type: 'line',
data: [],
smooth: true,
@@ -545,7 +545,7 @@ export default {
areaStyle: { color: 'rgba(0, 255, 157, 0.1)' }
},
{
name: '底部平均涂层重量',
name: this.$t('track.avrCoatingWeightBottom'),
type: 'line',
data: [],
smooth: true,
@@ -553,7 +553,7 @@ export default {
itemStyle: { color: '#00d4ff' }
},
{
name: '气刀压力',
name: this.$t('track.airKnifePressure'),
type: 'line',
data: [],
smooth: true,
@@ -561,7 +561,7 @@ export default {
itemStyle: { color: '#ffa502' }
},
{
name: '出口速度',
name: this.$t('track.exitSpeed'),
type: 'line',
data: [],
smooth: true,
@@ -584,7 +584,7 @@ export default {
textStyle: { color: '#fff' }
},
legend: {
data: ['出口张力1', '出口张力2', '出口速度'],
data: [$t('track.exitTension1'), $t('track.exitTension2'), $t('track.exitSpeed')],
textStyle: { color: '#b0b0b0', fontSize: 12 },
top: 10
},
@@ -605,7 +605,7 @@ export default {
},
series: [
{
name: '出口张力1',
name: this.$t('track.exitTension1'),
type: 'line',
data: [],
smooth: true,
@@ -614,7 +614,7 @@ export default {
areaStyle: { color: 'rgba(0, 212, 255, 0.1)' }
},
{
name: '出口张力2',
name: this.$t('track.exitTension2'),
type: 'line',
data: [],
smooth: true,
@@ -622,7 +622,7 @@ export default {
itemStyle: { color: '#00ff9d' }
},
{
name: '出口速度',
name: this.$t('track.exitSpeed'),
type: 'line',
data: [],
smooth: true,

View File

@@ -6,32 +6,32 @@
<!-- 加载状态 -->
<div v-if="isLoading" class="loading-container">
<el-icon class="is-loading"><i class="el-icon-loading"></i></el-icon>
<span>加载中...</span>
<span>{{ $t('common.loading') }}</span>
</div>
<!-- WebSocket 连接状态指示 -->
<div v-if="!isLoading" class="ws-status-bar">
<el-tooltip content="测量数据" placement="top">
<el-tooltip :content="$t('track.measureData')" placement="top">
<el-badge :is-dot="true" :type="socketStatus.measure ? 'success' : 'danger'">
<i class="el-icon-data-analysis"></i>
</el-badge>
</el-tooltip>
<el-tooltip content="位置追踪" placement="top">
<el-tooltip :content="$t('track.positionTracking')" placement="top">
<el-badge :is-dot="true" :type="socketStatus.position ? 'success' : 'danger'">
<i class="el-icon-location"></i>
</el-badge>
</el-tooltip>
<el-tooltip content="操作信号" placement="top">
<el-tooltip :content="$t('track.operationSignal')" placement="top">
<el-badge :is-dot="true" :type="socketStatus.signal ? 'success' : 'danger'">
<i class="el-icon-bell"></i>
</el-badge>
</el-tooltip>
<el-tooltip content="物料映射" placement="top">
<el-tooltip :content="$t('track.materialMapping')" placement="top">
<el-badge :is-dot="true" :type="socketStatus.matmap ? 'success' : 'danger'">
<i class="el-icon-map-location"></i>
</el-badge>
</el-tooltip>
<el-tooltip content="计算结果" placement="top">
<el-tooltip :content="$t('track.calculationResult')" placement="top">
<el-badge :is-dot="true" :type="socketStatus.calcSetup ? 'success' : 'danger'">
<i class="el-icon-s-marketing"></i>
</el-badge>
@@ -42,8 +42,8 @@
<!-- 入口段区域 -->
<div class="section-area entry-area">
<div class="section-header">
入口段
<span class="section-info" v-if="positionData.entrySpeed">速度: {{ positionData.entrySpeed.toFixed(1) }} m/min</span>
{{ $t('track.entrySection') }}
<span class="section-info" v-if="positionData.entrySpeed">{{ $t('track.speed') }}: {{ positionData.entrySpeed.toFixed(1) }} m/min</span>
</div>
<div class="section-summary" v-if="entrySectionMetrics.length">
<div class="summary-item" v-for="item in entrySectionMetrics" :key="item.label">
@@ -70,8 +70,8 @@
<!-- 熔炉段区域 -->
<div class="section-area furnace-area">
<div class="section-header">
熔炉段
<span class="section-info" v-if="positionData.technologySpeed">速度: {{ positionData.technologySpeed.toFixed(1) }} m/min</span>
{{ $t('track.furnaceSection') }}
<span class="section-info" v-if="positionData.technologySpeed">{{ $t('track.speed') }}: {{ positionData.technologySpeed.toFixed(1) }} m/min</span>
</div>
<div class="section-summary" v-if="furnaceSectionMetrics.length">
<div class="summary-item" v-for="item in furnaceSectionMetrics" :key="item.label">
@@ -97,7 +97,7 @@
<!-- 涂层段区域 -->
<div class="section-area coat-area">
<div class="section-header">涂层段</div>
<div class="section-header">{{ $t('track.coatSection') }}</div>
<div class="section-summary" v-if="coatSectionMetrics.length">
<div class="summary-item" v-for="item in coatSectionMetrics" :key="item.label">
<span class="summary-label">{{ item.label }}</span>
@@ -123,8 +123,8 @@
<!-- 出口段区域 -->
<div class="section-area exit-area">
<div class="section-header">
出口段
<span class="section-info" v-if="positionData.exitSpeed">速度: {{ positionData.exitSpeed.toFixed(1) }} m/min</span>
{{ $t('track.exitSection') }}
<span class="section-info" v-if="positionData.exitSpeed">{{ $t('track.speed') }}: {{ positionData.exitSpeed.toFixed(1) }} m/min</span>
</div>
<div class="section-summary" v-if="exitSectionMetrics.length">
<div class="summary-item" v-for="item in exitSectionMetrics" :key="item.label">
@@ -150,7 +150,7 @@
<!-- 其他段区域 -->
<div class="section-area" v-if="exitOtherDevicesList.length">
<div class="section-header">其他段</div>
<div class="section-header">{{ $t('track.otherSection') }}</div>
<div class="device-grid other-exit-grid">
<div v-for="device in exitOtherDevicesList" :key="device.positionNameEn" class="device-card" :class="{
active: selectedCard && selectedCard.positionNameEn === device.positionNameEn,
@@ -175,10 +175,10 @@
<!-- 生产计划列表 -->
<div class="panel">
<div class="panel-title">
<i class="el-icon-s-order"></i> 生产计划
<i class="el-icon-s-order"></i> {{ $t('track.productionPlan') }}
</div>
<div class="plan-list-vertical">
<el-empty v-if="planQueue.length === 0" description="暂无生产计划" :image-size="80" />
<el-empty v-if="planQueue.length === 0" :description="$t('track.noProductionPlan')" :image-size="80" />
<div
v-else
v-for="(plan, index) in planQueue"
@@ -190,14 +190,14 @@
<div class="plan-item-top">
<div class="plan-order-dot" :class="getPlanOrderClass(plan.status)">{{ index + 1 }}</div>
<div class="plan-title-text">
<div class="plan-id">计划ID{{ plan.planid || '-' }}</div>
<div class="plan-coil">钢卷号{{ plan.coilid || '-' }}</div>
<div class="plan-id">{{ $t('track.planId') }}{{ plan.planid || '-' }}</div>
<div class="plan-coil">{{ $t('track.coilid') }}{{ plan.coilid || '-' }}</div>
</div>
<el-tag :type="getPlanStatusTagType(plan.status)" size="mini">{{ getPlanStatusText(plan.status) }}</el-tag>
</div>
<div class="plan-item-bottom">
<span>钢种{{ plan.steelGrade || '-' }}</span>
<span>顺序{{ plan.seqid || '-' }}</span>
<span>{{ $t('track.steelGrade') }}{{ plan.steelGrade || '-' }}</span>
<span>{{ $t('track.sequence') }}{{ plan.seqid || '-' }}</span>
</div>
</div>
</div>
@@ -206,21 +206,21 @@
<!-- 生产计划详情 -->
<div class="panel" v-if="selectedPlan">
<div class="panel-title">
<i class="el-icon-document"></i> 生产计划详情
<i class="el-icon-document"></i> {{ $t('track.productionPlanDetail') }}
<el-button size="mini" type="text" icon="el-icon-close" @click="selectedPlan = null"></el-button>
</div>
<div class="plan-detail-content">
<!-- 位置信息如果在产线上 -->
<div v-if="selectedPlanPosition" class="position-alert">
<div class="position-icon">
<i class="el-icon-location"></i>
</div>
<div class="position-info">
<div class="position-label">当前位置</div>
<div class="position-name">{{ selectedPlanPosition.positionNameCn }}</div>
<div class="position-code">{{ selectedPlanPosition.positionNameEn }}</div>
</div>
<div v-if="selectedPlanPosition" class="position-alert">
<div class="position-icon">
<i class="el-icon-location"></i>
</div>
<div class="position-info">
<div class="position-label">{{ $t('track.currentPosition') }}</div>
<div class="position-name">{{ selectedPlanPosition.positionNameCn }}</div>
<div class="position-code">{{ selectedPlanPosition.positionNameEn }}</div>
</div>
</div>
<el-descriptions :column="1" border size="small">
<el-descriptions-item label="计划ID">{{ selectedPlan.planid || '-' }}</el-descriptions-item>
@@ -250,8 +250,8 @@
</el-descriptions>
<!-- 时间信息 -->
<div class="plan-time-info" v-if="selectedPlan.onlineDate || selectedPlan.startDate || selectedPlan.endDate">
<div class="info-subtitle">时间信息</div>
<div class="plan-time-info" v-if="selectedPlan.onlineDate || selectedPlan.startDate || selectedPlan.endDate">
<div class="info-subtitle">{{ $t('track.timeInfo') }}</div>
<el-descriptions :column="1" border size="small">
<el-descriptions-item label="上线时间" v-if="selectedPlan.onlineDate">
{{ formatDateTime(selectedPlan.onlineDate) }}
@@ -270,7 +270,7 @@
<!-- 最近操作信号 -->
<div class="panel" v-if="signalData">
<div class="panel-title">
<i class="el-icon-bell"></i> 最近操作
<i class="el-icon-bell"></i> {{ $t('track.recentOperation') }}
<el-tag
:type="getOperationTagType(signalData.operation)"
size="mini"
@@ -304,39 +304,39 @@
</div>
<!-- 操作按钮 -->
<div class="panel">
<div class="panel-title">操作</div>
<div class="panel-title">{{ $t('track.operation') }}</div>
<div class="btn-list">
<el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'ONLINE')">钢卷上线</el-button>
<el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'UNLOAD')">手动卸卷</el-button>
<el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'ONLINE')">{{ $t('track.coilOnline') }}</el-button>
<el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'UNLOAD')">{{ $t('track.manualUnload') }}</el-button>
<el-button class="action-btn" size="small"
@click="handleOperate(selectedCard, 'ALL_RETURN')">整卷回退</el-button>
@click="handleOperate(selectedCard, 'ALL_RETURN')">{{ $t('track.allReturn') }}</el-button>
<el-button class="action-btn" size="small"
@click="handleOperate(selectedCard, 'HALF_RETURN')">半卷回退</el-button>
<el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'BLOCK')">卸卷并封闭</el-button>
@click="handleOperate(selectedCard, 'HALF_RETURN')">{{ $t('track.halfReturn') }}</el-button>
<el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'BLOCK')">{{ $t('track.unloadAndBlock') }}</el-button>
</div>
</div>
<!-- 设备基本信息 -->
<div class="panel" v-if="selectedCard">
<div class="panel-title">基本信息</div>
<div class="panel-title">{{ $t('track.basicInfo') }}</div>
<table class="info-table">
<tr>
<td>位置名称</td>
<td>{{ $t('track.positionName') }}</td>
<td>{{ selectedCard.positionNameCn || '-' }}</td>
</tr>
<tr>
<td>位置代号</td>
<td>{{ $t('track.positionCode') }}</td>
<td>{{ selectedCard.positionNameEn || '-' }}</td>
</tr>
<tr>
<td>钢卷号</td>
<td>{{ $t('track.coilid') }}</td>
<td>{{ selectedCard.matId || '-' }}</td>
</tr>
<tr>
<td>计划ID</td>
<td>{{ $t('track.planId') }}</td>
<td>{{ selectedCard.planId || '-' }}</td>
</tr>
<tr>
<td>计划号</td>
<td>{{ $t('track.planId') }}</td>
<td>{{ selectedCard.planNo || '-' }}</td>
</tr>
</table>
@@ -349,20 +349,20 @@
<!-- 调整工具选择两个位置两个下拉选分别双向绑定 -->
<el-form :model="adjustForm" ref="adjustForm" label-width="80px">
<el-form-item label="当前位置" prop="current">
<el-select v-model="adjustForm.current" placeholder="请选择当前位置">
<el-select v-model="adjustForm.current" :placeholder="$t('common.pleaseSelect')">
<el-option v-for="item in matMapList" :key="item.positionNameEn" :label="item.positionNameCn"
:value="item.positionNameEn"></el-option>
</el-select>
</el-form-item>
<el-form-item label="目标位置" prop="target">
<el-select v-model="adjustForm.target" placeholder="请选择目标位置">
<el-select v-model="adjustForm.target" :placeholder="$t('common.pleaseSelect')">
<el-option v-for="item in matMapList" :key="item.positionNameEn" :label="item.positionNameCn"
:value="item.positionNameEn"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-button type="primary" :disabled="!adjustForm.current || !adjustForm.target"
@click="handleConfirmAdjust">确认调整</el-button>
@click="handleConfirmAdjust">{{ $t('track.confirmAdjustment') }}</el-button>
</div>
</div>
@@ -371,14 +371,14 @@
<!-- 计算结果对话框 -->
<el-dialog
title="计算设定结果"
:title="$t('track.calculationSetupResult')"
:visible.sync="showCalcResultDialog"
width="80%"
v-if="calcSetupResult"
>
<div class="calc-result-header">
<el-tag :type="calcSetupResult.flag ? 'success' : 'danger'">
{{ calcSetupResult.flag ? '计算成功' : '计算失败' }}
{{ calcSetupResult.flag ? $t('track.calculationSuccess') : $t('track.calculationFailed') }}
</el-tag>
<span>Key: {{ calcSetupResult.key }}</span>
</div>
@@ -389,69 +389,69 @@
stripe
max-height="500"
>
<el-table-column prop="passno" label="道次号" width="80" fixed></el-table-column>
<el-table-column prop="entryThick" label="入口厚度(mm)" width="120"></el-table-column>
<el-table-column prop="exitThick" label="出口厚度(mm)" width="120"></el-table-column>
<el-table-column prop="reduction" label="压下率(%)" width="100"></el-table-column>
<el-table-column prop="rollSpeed" label="轧制速度" width="120"></el-table-column>
<el-table-column prop="rollForce" label="轧制力(kN)" width="120"></el-table-column>
<el-table-column prop="entryTension" label="入口张力" width="120"></el-table-column>
<el-table-column prop="exitTension" label="出口张力" width="120"></el-table-column>
<el-table-column prop="passno" :label="$t('track.passno')" width="80" fixed></el-table-column>
<el-table-column prop="entryThick" :label="$t('track.entryThickness')" width="120"></el-table-column>
<el-table-column prop="exitThick" :label="$t('track.exitThickness')" width="120"></el-table-column>
<el-table-column prop="reduction" :label="$t('track.reduction')" width="100"></el-table-column>
<el-table-column prop="rollSpeed" :label="$t('track.rollSpeed')" width="120"></el-table-column>
<el-table-column prop="rollForce" :label="$t('track.rollForce')" width="120"></el-table-column>
<el-table-column prop="entryTension" :label="$t('track.entryTension')" width="120"></el-table-column>
<el-table-column prop="exitTension" :label="$t('track.exitTension')" width="120"></el-table-column>
</el-table>
<div v-else class="empty-msg">无计算结果数据</div>
<div v-else class="empty-msg">{{ $t('track.noCalculationResult') }}</div>
</el-dialog>
<el-dialog :visible.sync="operateMatStatus" :title="getOperateTitle" width="50%">
<el-form :model="operateMatForm" :rules="operateRules" ref="operateForm" label-width="120px">
<el-form-item label="开卷机编号" prop="porIdx">
<el-form-item :label="$t('track.por')" prop="porIdx">
<el-input v-model="operateMatForm.porIdx"></el-input>
</el-form-item>
<el-form-item label="卷取机编号" prop="trIdx">
<el-form-item :label="$t('track.tr')" prop="trIdx">
<el-input v-model="operateMatForm.trIdx"></el-input>
</el-form-item>
<el-form-item label="计划id" prop="planId">
<el-input v-model="operateMatForm.planId" placeholder="请输入计划ID"></el-input>
<el-form-item :label="$t('track.planId')" prop="planId">
<el-input v-model="operateMatForm.planId" :placeholder="$t('track.pleaseInputPlanId')"></el-input>
</el-form-item>
<el-form-item label="钢卷号" prop="entryMatId">
<el-input v-model="operateMatForm.entryMatId" placeholder="请输入钢卷号"></el-input>
<el-form-item :label="$t('track.coilid')" prop="entryMatId">
<el-input v-model="operateMatForm.entryMatId" :placeholder="$t('track.pleaseInputCoilid')"></el-input>
</el-form-item>
<!-- <el-form-item label="计划号" prop="planNo">
<el-input v-model="operateMatForm.planNo" placeholder="请输入计划号"></el-input>
</el-form-item> -->
<el-form-item label="操作类型" prop="operation">
<el-form-item :label="$t('track.operationType')" prop="operation">
<el-select v-model="operateMatForm.operation" disabled>
<el-option label="钢卷上线" value="ONLINE"></el-option>
<el-option label="手动卸卷" value="UNLOAD"></el-option>
<el-option label="整卷回退" value="ALL_RETURN"></el-option>
<el-option label="半卷回退" value="HALF_RETURN"></el-option>
<el-option label="卸卷并封闭" value="BLOCK"></el-option>
<el-option :label="$t('track.coilOnline')" value="ONLINE"></el-option>
<el-option :label="$t('track.manualUnload')" value="UNLOAD"></el-option>
<el-option :label="$t('track.allReturn')" value="ALL_RETURN"></el-option>
<el-option :label="$t('track.halfReturn')" value="HALF_RETURN"></el-option>
<el-option :label="$t('track.unloadAndBlock')" value="BLOCK"></el-option>
<!-- <el-option label="甩尾" value="THROW_TAIL"></el-option> -->
</el-select>
</el-form-item>
<!-- 回退相关字段 -->
<template v-if="['ALL_RETURN', 'HALF_RETURN'].includes(operateMatForm.operation)">
<el-form-item label="回退卷号" prop="returnMatId">
<el-input v-model="operateMatForm.returnMatId" placeholder="请输入回退卷号"></el-input>
<el-form-item :label="$t('track.returnMatId')" prop="returnMatId">
<el-input v-model="operateMatForm.returnMatId" :placeholder="$t('track.pleaseInputReturnMatId')"></el-input>
</el-form-item>
<el-form-item label="回退重量" prop="returnWeight">
<el-input v-model="operateMatForm.returnWeight" placeholder="请输入回退重量"></el-input>
<el-form-item :label="$t('track.returnWeight')" prop="returnWeight">
<el-input v-model="operateMatForm.returnWeight" :placeholder="$t('track.pleaseInputReturnWeight')"></el-input>
</el-form-item>
<el-form-item label="回退备注" prop="returnRemark">
<el-form-item :label="$t('track.returnRemark')" prop="returnRemark">
<el-input v-model="operateMatForm.returnRemark" rows="3"></el-input>
</el-form-item>
</template>
<!-- 产出长度字段 -->
<template v-if="['PRODUCING', 'PRODUCT'].includes(operateMatForm.operation)">
<el-form-item label="产出钢卷长度" prop="coilLength">
<el-input v-model="operateMatForm.coilLength" type="number" placeholder="请输入产出钢卷长度"></el-input>
<el-form-item :label="$t('track.outputCoilLength')" prop="coilLength">
<el-input v-model="operateMatForm.coilLength" type="number" :placeholder="$t('track.pleaseInputOutputCoilLength')"></el-input>
</el-form-item>
</template>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="operateMatStatus = false">取消</el-button>
<el-button type="primary" @click="submitOperateForm">确定</el-button>
<el-button @click="operateMatStatus = false">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="submitOperateForm">{{ $t('common.confirm') }}</el-button>
</div>
</el-dialog>
</div>
@@ -498,39 +498,39 @@ const DEVICE_META = {
}
const PARAM_LABELS = {
tensionPorBr1: '开卷张力1#',
tensionPorBr2: '开卷张力2#',
stripSpeed: '带钢速度',
weldStatus: '焊机状态',
celLength: '入口活套位置',
celCapacity: '入口活套套量',
tensionCel: '入口活套张力',
cleaningVoltage: '清洗电压',
cleaningCurrent: '清洗电流',
alkaliConcentration: '碱液浓度',
alkaliTemperature: '碱液温度',
phfExitStripTemp: 'PH炉出口温度',
potTemperature: '锌锅温度',
gasConsumption: '燃气消耗',
rtfExitStripTemp: '加热段出口温度',
zincPotPower: '锌锅功率',
jcsExitStripTemp: '冷却段出口温度',
coolingTowerStripTemp: '冷却塔温度',
scsExitStripTemp: '均衡段出口温度',
tensionBr5Tm: 'BR5-TM张力',
stripSpeedTmExit: 'TM出口速度',
tmElongation: '光整延伸率',
tensionTlBr7: 'TL-BR7张力',
tlElongation: '拉矫延伸率',
cxlLength: '出口活套位置',
cxlCapacity: '出口活套套量',
tensionCxl: '出口活套张力',
inspectionStatus: '检查状态',
coilLength: '钢卷长度',
speedExitSection: '出口段速度',
tensionBr9Tr: 'BR9-TR张力',
avrCoatingWeightTop: '顶部涂重',
avrCoatingWeightBottom: '底部涂重'
tensionPorBr1: 'tensionPorBr1',
tensionPorBr2: 'tensionPorBr2',
stripSpeed: 'stripSpeed',
weldStatus: 'weldStatus',
celLength: 'celLength',
celCapacity: 'celCapacity',
tensionCel: 'tensionCel',
cleaningVoltage: 'cleaningVoltage',
cleaningCurrent: 'cleaningCurrent',
alkaliConcentration: 'alkaliConcentration',
alkaliTemperature: 'alkaliTemperature',
phfExitStripTemp: 'phfExitStripTemp',
potTemperature: 'potTemperature',
gasConsumption: 'gasConsumption',
rtfExitStripTemp: 'rtfExitStripTemp',
zincPotPower: 'zincPotPower',
jcsExitStripTemp: 'jcsExitStripTemp',
coolingTowerStripTemp: 'coolingTowerStripTemp',
scsExitStripTemp: 'scsExitStripTemp',
tensionBr5Tm: 'tensionBr5Tm',
stripSpeedTmExit: 'stripSpeedTmExit',
tmElongation: 'tmElongation',
tensionTlBr7: 'tensionTlBr7',
tlElongation: 'tlElongation',
cxlLength: 'cxlLength',
cxlCapacity: 'cxlCapacity',
tensionCxl: 'tensionCxl',
inspectionStatus: 'inspectionStatus',
coilLength: 'coilLength',
speedExitSection: 'speedExitSection',
tensionBr9Tr: 'tensionBr9Tr',
avrCoatingWeightTop: 'avrCoatingWeightTop',
avrCoatingWeightBottom: 'avrCoatingWeightBottom'
}
const FIELD_ALIASES = {
@@ -771,17 +771,17 @@ export default {
if (!source) return []
const data = []
// 通用字段:按 DeviceEnum.paramFields 取值
meta.paramFields.forEach(field => {
const value = this.getFieldValueWithAlias(source, field)
if (value !== null && value !== undefined && value !== '') {
data.push({
label: PARAM_LABELS[field] || field,
value: this.formatValue(value),
unit: this.getFieldUnit(field)
})
}
})
// 通用字段:按 DeviceEnum.paramFields 取值
meta.paramFields.forEach(field => {
const value = this.getFieldValueWithAlias(source, field)
if (value !== null && value !== undefined && value !== '') {
data.push({
label: this.$t(`track.${PARAM_LABELS[field] || field}`),
value: this.formatValue(value),
unit: this.getFieldUnit(field)
})
}
})
return data
}
@@ -868,7 +868,7 @@ export default {
const raw = source ? this.getFieldValueWithAlias(source, f) : null
const unit = this.getFieldUnit(f)
return {
label: PARAM_LABELS[f] || f,
label: this.$t(`track.${PARAM_LABELS[f] || f}`),
value: `${this.formatValue(raw)}${unit ? ' ' + unit : ''}`
}
})
@@ -992,7 +992,7 @@ export default {
this.signalData = data
const operationText = this.getOperationText(data.operation)
const autoFlagText = data.autoFlag === 1 ? '[手动]' : '[自动]'
const autoFlagText = data.autoFlag === 1 ? `[${this.$t('track.manualOperation')}]` : `[${this.$t('track.autoOperation')}]`
const config = this.getOperationConfig(data.operation)
// 检测到上线、生产中、生产完成等关键操作时,刷新生产计划队列
@@ -1005,7 +1005,7 @@ export default {
if(!repeatProducing){
this.$notify({
title: `${config.icon} ${config.title}`,
message: `${autoFlagText} ${operationText}\n钢卷号: ${data.entryMatId}\n计划ID: ${data.planId || '-'}`,
message: `${autoFlagText} ${operationText}\n${this.$t('track.coilid')}: ${data.entryMatId}\n${this.$t('track.planId')}: ${data.planId || '-'}`,
type: config.type,
duration: config.duration,
position: 'top-right',
@@ -1017,10 +1017,10 @@ export default {
// 如果需要弹窗确认(甩尾等重要操作)
if (config.needAlert) {
this.$alert(
`钢卷号: ${data.entryMatId}\n计划ID: ${data.planId || '-'}\n操作类型: ${operationText}\n操作方式: ${autoFlagText}`,
`${this.$t('track.coilid')}: ${data.entryMatId}\n${this.$t('track.planId')}: ${data.planId || '-'}\n${this.$t('track.operationType')}: ${operationText}\n${this.$t('track.operationType')}: ${autoFlagText}`,
`${config.icon} ${config.title}`,
{
confirmButtonText: '知道了',
confirmButtonText: this.$t('common.confirm'),
type: config.type,
center: true
}
@@ -1048,10 +1048,10 @@ export default {
this.calcSetupResult = data
if (data.flag) {
this.$message.success(`计算完成 (Key: ${data.key})`)
this.$message.success(`${this.$t('track.calculationSuccess')} (Key: ${data.key})`)
this.showCalcResultDialog = true
} else {
this.$message.error(`计算失败 (Key: ${data.key})`)
this.$message.error(`${this.$t('track.calculationFailed')} (Key: ${data.key})`)
}
},
@@ -1059,15 +1059,15 @@ export default {
getOperationText(operation) {
const operationMap = {
ONLINE: '钢卷上线',
UNLOAD: '卸卷',
PRODUCING: '生产中',
PRODUCT: '生产完成',
PAY_OVER: '甩尾',
THROW_TAIL: '甩尾',
ALL_RETURN: '整卷回退',
HALF_RETURN: '半卷回退',
BLOCK: '卸卷并封闭'
ONLINE: this.$t('track.coilOnline'),
UNLOAD: this.$t('track.manualUnload'),
PRODUCING: this.$t('track.producing'),
PRODUCT: this.$t('track.product'),
PAY_OVER: this.$t('track.payOver'),
THROW_TAIL: this.$t('track.throwTail'),
ALL_RETURN: this.$t('track.allReturn'),
HALF_RETURN: this.$t('track.halfReturn'),
BLOCK: this.$t('track.unloadAndBlock')
}
return operationMap[operation] || operation
},
@@ -1077,63 +1077,63 @@ export default {
const configs = {
ONLINE: {
icon: '🎬',
title: '钢卷上线通知',
title: this.$t('track.onlineNotice'),
type: 'success',
duration: 4000,
needAlert: false
},
UNLOAD: {
icon: '📤',
title: '卸卷操作通知',
title: this.$t('track.unloadNotice'),
type: 'info',
duration: 3000,
needAlert: false
},
PRODUCING: {
icon: '⚙️',
title: '生产状态变更',
title: this.$t('track.producingNotice'),
type: 'success',
duration: 3000,
needAlert: false
},
PRODUCT: {
icon: '✅',
title: '生产完成通知',
title: this.$t('track.productNotice'),
type: 'success',
duration: 4000,
needAlert: false
},
PAY_OVER: {
icon: '⚠️',
title: '甩尾操作提示',
title: this.$t('track.payOverNotice'),
type: 'warning',
duration: 5000,
needAlert: true
},
THROW_TAIL: {
icon: '⚠️',
title: '甩尾操作提示',
title: this.$t('track.throwTailNotice'),
type: 'warning',
duration: 5000,
needAlert: true
},
ALL_RETURN: {
icon: '↩️',
title: '整卷回退通知',
title: this.$t('track.allReturnNotice'),
type: 'warning',
duration: 4000,
needAlert: false
},
HALF_RETURN: {
icon: '↩️',
title: '半卷回退通知',
title: this.$t('track.halfReturnNotice'),
type: 'warning',
duration: 4000,
needAlert: false
},
BLOCK: {
icon: '🚫',
title: '封闭操作通知',
title: this.$t('track.blockNotice'),
type: 'warning',
duration: 3000,
needAlert: false
@@ -1141,7 +1141,7 @@ export default {
}
return configs[operation] || {
icon: '📢',
title: '操作通知',
title: this.$t('track.operationNotice'),
type: 'info',
duration: 3000,
needAlert: false

View File

@@ -13,12 +13,12 @@
<form @submit.prevent="handleLogin">
<div class="input-group">
<input
type="text"
v-model="loginForm.username"
placeholder="请输入用户名"
class="form-input"
required
>
type="text"
v-model="loginForm.username"
:placeholder="$t('common.usernamePlaceholder')"
class="form-input"
required
>
<i class="fas fa-user input-icon"></i>
</div>
@@ -26,7 +26,7 @@
<input
type="password"
v-model="loginForm.password"
placeholder="请输入密码"
:placeholder="$t('common.passwordPlaceholder')"
class="form-input"
required
>
@@ -36,12 +36,12 @@
<div class="form-options">
<label class="remember-me">
<input type="checkbox" v-model="loginForm.rememberMe">
<span>记住密码</span>
<span>{{ $t('common.rememberPassword') }}</span>
</label>
<a href="#" class="forgot-password"></a>
</div>
<button @click="handleLogin" v-loading="loading" class="login-button"> </button>
<button @click="handleLogin" v-loading="loading" class="login-button">{{ $t('common.login') }}</button>
</form>
</div>
</div>
@@ -66,15 +66,6 @@ export default {
code: "",
uuid: ""
},
loginRules: {
username: [
{ required: true, trigger: "blur", message: "请输入您的账号" }
],
password: [
{ required: true, trigger: "blur", message: "请输入您的密码" }
],
code: [{ required: true, trigger: "change", message: "请输入验证码" }]
},
loading: false,
// 验证码开关
captchaEnabled: true,
@@ -83,6 +74,19 @@ export default {
redirect: undefined
}
},
computed: {
loginRules() {
return {
username: [
{ required: true, trigger: "blur", message: this.$t('common.enterUsername') }
],
password: [
{ required: true, trigger: "blur", message: this.$t('common.enterPassword') }
],
code: [{ required: true, trigger: "change", message: this.$t('common.enterVerificationCode') }]
}
}
},
watch: {
$route: {
handler: function(route) {