fix: add product column to test summary
This commit is contained in:
@@ -111,3 +111,27 @@
|
|||||||
### 结论
|
### 结论
|
||||||
|
|
||||||
已按 `修改质检测试任务看板.docx` 完成 `TestTaskDashboard.vue` 修改:顶部统计卡片已调整,左侧新增测试任务汇总并放置已完工任务,右侧放置发货状态列表和测试装配任务列表,缺件明细已移除;加急汇总来自测试装配任务查询中加急总数大于 0 的任务数,滞留汇总来自及时检验报表任务数。`npm run build` 构建通过。work 目录资料已创建并复制原始 docx。
|
已按 `修改质检测试任务看板.docx` 完成 `TestTaskDashboard.vue` 修改:顶部统计卡片已调整,左侧新增测试任务汇总并放置已完工任务,右侧放置发货状态列表和测试装配任务列表,缺件明细已移除;加急汇总来自测试装配任务查询中加急总数大于 0 的任务数,滞留汇总来自及时检验报表任务数。`npm run build` 构建通过。work 目录资料已创建并复制原始 docx。
|
||||||
|
|
||||||
|
## 2026-07-03 测试任务汇总补回产品列
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
|
||||||
|
用户反馈“项目和指标中间的产品怎么没了”,要求将测试任务汇总改成第二张参考图样式,即在“项目”和“指标”之间补回“产品”列,并展示产品图片、产品名称和产品汇总数量。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
|
||||||
|
1. 读取 `src/views/TestTaskDashboard.vue` 当前模板、汇总数据结构和样式。
|
||||||
|
2. 确认当前“测试任务汇总”为三列:项目、指标、数量,确实缺少产品列。
|
||||||
|
3. 修改表头,增加“产品”列。
|
||||||
|
4. 修改汇总行模板:项目列显示项目名称和项目汇总数;产品列显示图片、产品名称和产品汇总数;右侧继续显示指标和数量。
|
||||||
|
5. 导入 `阀.png`、`其他.png`、`电气.png`、`机械.png` 四张产品图片。
|
||||||
|
6. 将测试任务汇总数据结构改为“阀类/系统类”项目下包含“阀/其他/电气/装配”产品,每个产品下展开“加急/滞留”两行。
|
||||||
|
7. 新增 `getTaskProductKey`,按任务内容归类到阀、其他、电气、装配。
|
||||||
|
8. 新增产品合计和项目合计函数,使产品列和项目列都能显示红色汇总数。
|
||||||
|
9. 调整测试任务汇总表样式,使其接近参考图:项目列展示大类及总数,产品列图片在左、名称和数量在右,指标和数量列保持加急红色、滞留橙色。
|
||||||
|
10. 执行 `npm run build`,构建成功。
|
||||||
|
11. 同步更新 work 目录中的推进台账、任务矩阵、验收证据和决策记录。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
已将“测试任务汇总”改为“项目 / 产品 / 指标 / 数量”四列结构,产品列按参考图展示图片、产品名称和产品汇总数;构建验证通过。
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="summary-group-th">项目</th>
|
<th class="summary-group-th">项目</th>
|
||||||
|
<th class="summary-product-th">产品</th>
|
||||||
<th class="summary-metric-th">指标</th>
|
<th class="summary-metric-th">指标</th>
|
||||||
<th class="summary-count-th">数量</th>
|
<th class="summary-count-th">数量</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -47,7 +48,19 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="row in testSummaryRows" :key="`${row.groupKey}-${row.metricKey}`">
|
<tr v-for="row in testSummaryRows" :key="`${row.groupKey}-${row.metricKey}`">
|
||||||
<td v-if="row.groupRowspan" :rowspan="row.groupRowspan" class="summary-group-cell">
|
<td v-if="row.groupRowspan" :rowspan="row.groupRowspan" class="summary-group-cell">
|
||||||
{{ row.group }}
|
<div class="summary-total">
|
||||||
|
<span>{{ row.group }}</span>
|
||||||
|
<strong>{{ row.groupTotal }}</strong>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td v-if="row.productRowspan" :rowspan="row.productRowspan" class="summary-product-cell">
|
||||||
|
<div class="summary-product">
|
||||||
|
<img class="summary-product-image" :src="row.productImage" alt="" />
|
||||||
|
<div class="summary-product-text">
|
||||||
|
<span>{{ row.product }}</span>
|
||||||
|
<strong>{{ row.productTotal }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="summary-metric-cell" :class="`metric-${row.metricKey}`">{{ row.metric }}</td>
|
<td class="summary-metric-cell" :class="`metric-${row.metricKey}`">{{ row.metric }}</td>
|
||||||
<td class="summary-count-cell" :class="`metric-${row.metricKey}`">{{ row.value }}</td>
|
<td class="summary-count-cell" :class="`metric-${row.metricKey}`">{{ row.value }}</td>
|
||||||
@@ -124,6 +137,10 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, inject, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
|
import { computed, inject, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||||
|
import assemblyImage from '@/assets/dashboard/机械.png'
|
||||||
|
import electricImage from '@/assets/dashboard/电气.png'
|
||||||
|
import otherImage from '@/assets/dashboard/其他.png'
|
||||||
|
import valveImage from '@/assets/dashboard/阀.png'
|
||||||
const CreateData = inject('CreateData')
|
const CreateData = inject('CreateData')
|
||||||
const ExecDatabase = inject('ExecDatabase')
|
const ExecDatabase = inject('ExecDatabase')
|
||||||
defineOptions({ name: 'AssemblyCenterTaskDashboard' })
|
defineOptions({ name: 'AssemblyCenterTaskDashboard' })
|
||||||
@@ -184,8 +201,22 @@ const VISIBLE_ROWS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const testSummaryGroups = [
|
const testSummaryGroups = [
|
||||||
{ key: 'valve', label: '阀类' },
|
{
|
||||||
{ key: 'system', label: '系统类' }
|
key: 'valve',
|
||||||
|
label: '阀类',
|
||||||
|
products: [
|
||||||
|
{ key: 'valveMain', label: '阀', image: valveImage },
|
||||||
|
{ key: 'valveOther', label: '其他', image: otherImage }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'system',
|
||||||
|
label: '系统类',
|
||||||
|
products: [
|
||||||
|
{ key: 'systemElectric', label: '电气', image: electricImage },
|
||||||
|
{ key: 'systemAssembly', label: '装配', image: assemblyImage }
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const testSummaryMetrics = [
|
const testSummaryMetrics = [
|
||||||
@@ -212,14 +243,28 @@ const testSummaryRows = computed(() => {
|
|||||||
const rows = []
|
const rows = []
|
||||||
|
|
||||||
testSummaryGroups.forEach(group => {
|
testSummaryGroups.forEach(group => {
|
||||||
testSummaryMetrics.forEach(metric => {
|
const groupTotal = getTestGroupTotal(group)
|
||||||
rows.push({
|
|
||||||
group: group.label,
|
group.products.forEach(product => {
|
||||||
groupKey: group.key,
|
const productTotal = getTestProductTotal(product.key)
|
||||||
groupRowspan: metric.key === testSummaryMetrics[0].key ? testSummaryMetrics.length : 0,
|
|
||||||
metric: metric.label,
|
testSummaryMetrics.forEach(metric => {
|
||||||
metricKey: metric.key,
|
rows.push({
|
||||||
value: countTestSummaryRows(group.key, metric.key)
|
group: group.label,
|
||||||
|
groupKey: group.key,
|
||||||
|
groupTotal,
|
||||||
|
groupRowspan: rows.filter(item => item.groupKey === group.key).length === 0
|
||||||
|
? group.products.length * testSummaryMetrics.length
|
||||||
|
: 0,
|
||||||
|
product: product.label,
|
||||||
|
productKey: product.key,
|
||||||
|
productImage: product.image,
|
||||||
|
productTotal,
|
||||||
|
productRowspan: metric.key === testSummaryMetrics[0].key ? testSummaryMetrics.length : 0,
|
||||||
|
metric: metric.label,
|
||||||
|
metricKey: metric.key,
|
||||||
|
value: countTestSummaryRows(product.key, metric.key)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -437,14 +482,33 @@ const getTaskGroupKey = item => {
|
|||||||
return taskType.includes('系统') || text.includes('系统') ? 'system' : 'valve'
|
return taskType.includes('系统') || text.includes('系统') ? 'system' : 'valve'
|
||||||
}
|
}
|
||||||
|
|
||||||
const countTestSummaryRows = (groupKey, metricKey) => {
|
const getTaskProductKey = item => {
|
||||||
|
const groupKey = getTaskGroupKey(item)
|
||||||
|
const text = String(item.任务类型 || item.自制件属性 || item.物料名称 || item.零件名称 || item.物料描述 || '')
|
||||||
|
|
||||||
|
if (groupKey === 'system') {
|
||||||
|
return text.includes('电气') ? 'systemElectric' : 'systemAssembly'
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.includes('阀') ? 'valveMain' : 'valveOther'
|
||||||
|
}
|
||||||
|
|
||||||
|
const countTestSummaryRows = (productKey, metricKey) => {
|
||||||
const sourceRows = metricKey === 'stagnation' ? stagnationRows.value : rawTestAssemblyRows.value
|
const sourceRows = metricKey === 'stagnation' ? stagnationRows.value : rawTestAssemblyRows.value
|
||||||
return sourceRows
|
return sourceRows
|
||||||
.filter(item => getTaskGroupKey(item) === groupKey)
|
.filter(item => getTaskProductKey(item) === productKey)
|
||||||
.filter(item => metricKey === 'urgent' ? isUrgentTask(item) : true)
|
.filter(item => metricKey === 'urgent' ? isUrgentTask(item) : true)
|
||||||
.length
|
.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getTestProductTotal = productKey => {
|
||||||
|
return testSummaryMetrics.reduce((total, metric) => total + countTestSummaryRows(productKey, metric.key), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTestGroupTotal = group => {
|
||||||
|
return group.products.reduce((total, product) => total + getTestProductTotal(product.key), 0)
|
||||||
|
}
|
||||||
|
|
||||||
const sortTestAssemblyTaskRows = rows => rows.slice().sort((a, b) => {
|
const sortTestAssemblyTaskRows = rows => rows.slice().sort((a, b) => {
|
||||||
const unfinishedA = isInspectionUnfinished(a)
|
const unfinishedA = isInspectionUnfinished(a)
|
||||||
const unfinishedB = isInspectionUnfinished(b)
|
const unfinishedB = isInspectionUnfinished(b)
|
||||||
@@ -934,35 +998,95 @@ th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.test-summary-table td {
|
.test-summary-table td {
|
||||||
height: 110px;
|
height: 55px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-group-th {
|
.summary-group-th {
|
||||||
width: 160px;
|
width: 126px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-product-th {
|
||||||
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-metric-th {
|
.summary-metric-th {
|
||||||
width: 180px;
|
width: 104px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-count-th {
|
.summary-count-th {
|
||||||
width: 160px;
|
width: 94px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-group-cell {
|
.summary-group-cell {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 30px;
|
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
background: rgba(7, 74, 112, 0.58);
|
background: rgba(7, 74, 112, 0.58);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.summary-total {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
justify-items: center;
|
||||||
|
line-height: 1.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-total span {
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-total strong {
|
||||||
|
color: #ff3040;
|
||||||
|
font-size: 38px;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-product-cell {
|
||||||
|
background: rgba(7, 45, 82, 0.58);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-product {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 118px minmax(0, 1fr);
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
min-height: 110px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-product-image {
|
||||||
|
width: 106px;
|
||||||
|
height: 90px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-product-text {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
justify-items: center;
|
||||||
|
line-height: 1.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-product-text span {
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-product-text strong {
|
||||||
|
color: #ff3040;
|
||||||
|
font-size: 34px;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
.summary-metric-cell {
|
.summary-metric-cell {
|
||||||
font-size: 28px;
|
font-size: 26px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-count-cell {
|
.summary-count-cell {
|
||||||
font-size: 44px;
|
font-size: 34px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
| 6 | 新增加急、滞留、测试任务汇总计算 | `src/views/TestTaskDashboard.vue` | 加急和滞留统计可由对应接口结果计算 | 构建验证 |
|
| 6 | 新增加急、滞留、测试任务汇总计算 | `src/views/TestTaskDashboard.vue` | 加急和滞留统计可由对应接口结果计算 | 构建验证 |
|
||||||
| 7 | 执行构建 | 无 | `npm run build` 成功 | 创建 work 文档 |
|
| 7 | 执行构建 | 无 | `npm run build` 成功 | 创建 work 文档 |
|
||||||
| 8 | 创建本任务资料目录和 01-07 文档 | `work/修改质检测试任务看板/*` | 文档齐全,原始 docx 已复制 | 追加总日志 |
|
| 8 | 创建本任务资料目录和 01-07 文档 | `work/修改质检测试任务看板/*` | 文档齐全,原始 docx 已复制 | 追加总日志 |
|
||||||
|
| 9 | 按反馈补回“产品”列并改成图片示例样式 | `src/views/TestTaskDashboard.vue`、`work/修改质检测试任务看板/*`、`gptlog-process/gpdlog.md` | `npm run build` 成功 | 提交并推送远程 |
|
||||||
|
|
||||||
## 下一步建议
|
## 下一步建议
|
||||||
|
|
||||||
|
|||||||
@@ -13,3 +13,4 @@
|
|||||||
| QT-009 | 构建验证 | 已完成 | `npm run build` 成功 |
|
| QT-009 | 构建验证 | 已完成 | `npm run build` 成功 |
|
||||||
| QT-010 | work 文档归档 | 已完成 | README 和 01-07 文档已创建,原始 docx 已复制 |
|
| QT-010 | work 文档归档 | 已完成 | README 和 01-07 文档已创建,原始 docx 已复制 |
|
||||||
| QT-011 | 中文过程日志追加 | 已完成 | 已追加到 `gptlog-process/gpdlog.md` |
|
| QT-011 | 中文过程日志追加 | 已完成 | 已追加到 `gptlog-process/gpdlog.md` |
|
||||||
|
| QT-012 | 汇总表补回产品列 | 已完成 | 测试任务汇总表包含“项目 / 产品 / 指标 / 数量”,产品列展示图片、名称和产品汇总数 |
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ npm run build
|
|||||||
- 顶部无“可执行任务数”和旧“加急任务数”。
|
- 顶部无“可执行任务数”和旧“加急任务数”。
|
||||||
- 顶部有“加急汇总”和“滞留汇总”。
|
- 顶部有“加急汇总”和“滞留汇总”。
|
||||||
- 左侧有“测试任务汇总”,指标仅为“加急”和“滞留”。
|
- 左侧有“测试任务汇总”,指标仅为“加急”和“滞留”。
|
||||||
|
- “测试任务汇总”包含“项目 / 产品 / 指标 / 数量”四列,产品列展示产品图片、产品名称和产品汇总数。
|
||||||
- 左侧汇总下方是“已完工任务”。
|
- 左侧汇总下方是“已完工任务”。
|
||||||
- 右侧上方是“发货状态列表”。
|
- 右侧上方是“发货状态列表”。
|
||||||
- 右侧下方是“测试装配任务列表”。
|
- 右侧下方是“测试装配任务列表”。
|
||||||
|
|||||||
@@ -35,3 +35,9 @@
|
|||||||
决策:将 `summaryCards` 从普通数组改为 `reactive` 数组。
|
决策:将 `summaryCards` 从普通数组改为 `reactive` 数组。
|
||||||
|
|
||||||
原因:接口返回后会直接写入卡片值,响应式数组能确保卡片数字稳定刷新。
|
原因:接口返回后会直接写入卡片值,响应式数组能确保卡片数字稳定刷新。
|
||||||
|
|
||||||
|
## D-007:测试任务汇总补回产品层级
|
||||||
|
|
||||||
|
决策:将“测试任务汇总”从“项目 / 指标 / 数量”三列改为“项目 / 产品 / 指标 / 数量”四列,并在产品列展示图片、产品名称和产品汇总数。
|
||||||
|
|
||||||
|
原因:用户反馈项目和指标中间的产品列缺失,并要求按参考图样式展示;该结构也更接近装配任务汇总的项目-产品-指标层级。
|
||||||
|
|||||||
Reference in New Issue
Block a user