迁移设备履历报表模块

This commit is contained in:
sheng
2026-06-22 17:40:40 +08:00
parent a1716b0069
commit 6768eb9ead
7 changed files with 196 additions and 3 deletions

View File

@@ -0,0 +1,22 @@
# 功能测试 - 设备履历报表
> 模块:数据中台 / 生产报表 / 设备履历报表 (Equipment History Report)
> 路由:`/data_middleground/produce/report/equipment-history`
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 进入设备履历报表页面 | 页面显示设备编码、状态、时间范围筛选项和列表 |
| 2 | 设备编码查询 | 输入有效设备编码并查询 | 表格展示设备履历记录 |
| 3 | 状态筛选 | 选择运行/空闲/异常状态查询 | 表格仅展示匹配状态数据 |
| 4 | 时间范围筛选 | 选择开始结束时间后查询 | 表格展示时间范围内履历 |
| 5 | 分页切换 | 查询出多页数据后切换分页 | 当前页数据刷新,总数正确 |
| 6 | 重置功能 | 点击重置 | 筛选项、表格和分页状态清空 |
| 7 | 空数据 | 输入无匹配条件查询 | 显示空态,不出现脚本错误 |
| 8 | 国际化检查 | 切换中英文语言 | 页面文案随语言切换 |
## 回归关注点
- 接口必须调用 `report/device/log`method 为 `get.device.status.log`
- 时间范围需要拆分为 `start_time``end_time`

View File

@@ -3,8 +3,8 @@
> 根据 `后台Webman界面截图对照表.md` 生成。状态以当前 V2 项目中已落地的页面目录为准。
- 总功能数79
- 已迁移32
- 未迁移47
- 已迁移33
- 未迁移46
| 状态 | 一级模块 | 二级模块 | 三级模块 | 功能说明 | V2 目标路径 |
|:---:|---|---|---|---|---|
@@ -84,7 +84,7 @@
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池曲线 (Battery Curve) | 电池曲线 | `src/views/data-platform/traceability/battery-curve/` |
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 托盘追溯 (Tray Traceability) | 托盘追溯 | `src/views/data-platform/traceability/tray/` |
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池追溯 (Battery Traceability) | 电池追溯 | `src/views/data-platform/traceability/battery/` |
| | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 设备履历报表 (Equipment History Report) | | 待确认 |
| | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 设备履历报表 (Equipment History Report) | 设备履历报表 | `src/views/data-platform/production-reports/equipment-history/` |
| ⬜ | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 电池详情报表 (Battery Detail Report) | | 待确认 |
| ⬜ | 数据中台 (Data Platform) | 相关性分析 (Correlation Analysis) | 鹰眼 (Hawkeye) | | 待确认 |

View File

@@ -0,0 +1,15 @@
import { request } from '@/api/_service'
const BASE = 'report/'
function apiParams (method, data = {}) {
return { method, platform: 'api', ...data }
}
export function getEquipmentHistoryList (data) {
return request({
url: BASE + 'device/log',
method: 'post',
data: apiParams('get.device.status.log', data)
})
}

View File

@@ -1336,6 +1336,27 @@
"cancel_success": "Cancel active successfully",
"activation_success": "Rework activation successfully"
}
},
"production_reports": {
"equipment_history": {
"query": "Search",
"reset": "Reset",
"device_code": "Device Code",
"enter_device_code": "Enter device code",
"device_name": "Device Name",
"status": "Status",
"select_status": "Select status",
"running": "Running",
"idle": "Idle",
"error": "Error",
"status_name": "Status Name",
"time_range": "Time Range",
"start_time": "Start Time",
"end_time": "End Time",
"duration": "Duration",
"remark": "Remark",
"no_data": "No data"
}
}
}
},

View File

@@ -1336,6 +1336,27 @@
"cancel_success": "取消激活成功",
"activation_success": "复投激活成功"
}
},
"production_reports": {
"equipment_history": {
"query": "查询",
"reset": "重置",
"device_code": "设备编码",
"enter_device_code": "请输入设备编码",
"device_name": "设备名称",
"status": "状态",
"select_status": "请选择状态",
"running": "运行",
"idle": "空闲",
"error": "异常",
"status_name": "状态名称",
"time_range": "时间范围",
"start_time": "开始时间",
"end_time": "结束时间",
"duration": "持续时长",
"remark": "备注",
"no_data": "暂无数据"
}
}
}
},

View File

@@ -43,6 +43,12 @@ export default {
name: `${pre}traceability-battery`,
meta: { ...meta, cache: true, title: '电池追溯' },
component: _import('data-platform/traceability/battery')
},
{
path: 'produce/report/equipment-history',
name: `${pre}report-equipment-history`,
meta: { ...meta, cache: true, title: '设备履历报表' },
component: _import('data-platform/production-reports/equipment-history')
}
])('data_middleground-')
}

View File

@@ -0,0 +1,108 @@
<template>
<d2-container>
<template #header>
<div class="search-bar">
<el-form ref="searchForm" :inline="true" :model="search" size="mini">
<el-form-item :label="$t(key('device_code'))" prop="device_code">
<el-input v-model.trim="search.device_code" :placeholder="$t(key('enter_device_code'))" clearable style="width:200px" @keyup.enter.native="onSearch" />
</el-form-item>
<el-form-item :label="$t(key('status'))" prop="status">
<el-select v-model="search.status" :placeholder="$t(key('select_status'))" clearable style="width:160px">
<el-option :label="$t(key('running'))" value="running" />
<el-option :label="$t(key('idle'))" value="idle" />
<el-option :label="$t(key('error'))" value="error" />
</el-select>
</el-form-item>
<el-form-item :label="$t(key('time_range'))" prop="time">
<el-date-picker v-model="search.time" type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss" range-separator="-" :start-placeholder="$t(key('start_time'))" :end-placeholder="$t(key('end_time'))" style="width:330px" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" :disabled="loading" @click="onSearch">{{ $t(key('query')) }}</el-button>
<el-button icon="el-icon-refresh" :disabled="loading" @click="onReset">{{ $t(key('reset')) }}</el-button>
</el-form-item>
</el-form>
</div>
</template>
<page-table :columns="columns" :data="tableData" :loading="loading" :toolbar-buttons="[]" :row-buttons="[]" :pagination="pagination" :table-attrs="{ size: 'mini', rowKey: rowKey, highlightCurrentRow: true }" auto-height @page-change="onPageChange">
<template #empty><el-empty :description="$t(key('no_data'))" :image-size="80" /></template>
</page-table>
</d2-container>
</template>
<script>
import { useTableColumns } from '@/composables/useTableColumns'
import { i18nMixin } from '@/composables/useI18n'
import PageTable from '@/components/page-table'
import { getEquipmentHistoryList } from '@/api/data-platform/production-reports/equipment-history'
export default {
name: 'data-platform-production-reports-equipment-history',
components: { PageTable },
mixins: [i18nMixin('page.data_platform.production_reports.equipment_history')],
data () {
return {
loading: false,
search: { device_code: '', status: '', time: [] },
tableData: [],
pagination: { current: 1, size: 10, total: 0 }
}
},
computed: {
columns () {
return useTableColumns([
{ prop: 'device_code', label: this.key('device_code'), minWidth: 160, showOverflowTooltip: true },
{ prop: 'device_name', label: this.key('device_name'), minWidth: 160, showOverflowTooltip: true },
{ prop: 'status', label: this.key('status'), minWidth: 120, showOverflowTooltip: true },
{ prop: 'status_name', label: this.key('status_name'), minWidth: 140, showOverflowTooltip: true },
{ prop: 'start_time', label: this.key('start_time'), minWidth: 170, showOverflowTooltip: true },
{ prop: 'end_time', label: this.key('end_time'), minWidth: 170, showOverflowTooltip: true },
{ prop: 'duration', label: this.key('duration'), minWidth: 120, showOverflowTooltip: true },
{ prop: 'remark', label: this.key('remark'), minWidth: 220, showOverflowTooltip: true }
], { selectionWidth: 0, indexWidth: 55 })
}
},
methods: {
rowKey (row) {
return row.id || [row.device_code, row.start_time, row.end_time].filter(Boolean).join('-')
},
responseData (res) {
return res && res.data !== undefined ? res.data : res
},
buildParams () {
const time = Array.isArray(this.search.time) ? this.search.time : []
return { ...this.search, start_time: time[0], end_time: time[1], page_no: this.pagination.current, page_size: this.pagination.size }
},
async fetchData () {
this.loading = true
try {
const res = await getEquipmentHistoryList(this.buildParams())
const data = this.responseData(res)
const list = Array.isArray(data) ? data : (Array.isArray(data && data.data) ? data.data : [])
this.tableData = list
this.pagination.total = Number(data && data.count) || list.length
} finally {
this.loading = false
}
},
onSearch () {
this.pagination.current = 1
this.fetchData()
},
onReset () {
this.search = { device_code: '', status: '', time: [] }
this.pagination.current = 1
this.tableData = []
this.pagination.total = 0
},
onPageChange (page) {
this.pagination = { ...this.pagination, ...page }
this.fetchData()
}
}
}
</script>
<style lang="scss" scoped>
.search-bar { margin-bottom: -18px; }
</style>