| | |
| | | const allowed = new Set(items.value.flatMap(item => fields.value.flatMap(field => |
| | | (field.scope === 'detail' ? [0] : item.cycleNos).map(cycle => formationValueKey(item, cycle, field))))) |
| | | values.value = Object.fromEntries(Object.entries(values.value).filter(([key]) => allowed.has(key))) |
| | | const sourceKeys = new Set(items.value.flatMap(item => [formationSeriesKey(item), ...Object.entries(item.stepCurves ?? {}).flatMap(([cycle, steps]) => Object.keys(steps).map(step => `${formationSeriesKey(item)}|${cycle}|${step}`))])) |
| | | const sourceKeys = new Set(items.value.flatMap(item => [formationSeriesKey(item), ...Object.entries(item.chargeSteps ?? {}).flatMap(([cycle, steps]) => steps.map(step => `${formationSeriesKey(item)}|${cycle}|${step.stepNo}`))])) |
| | | sourceDetailOverrides.value = Object.fromEntries(Object.entries(sourceDetailOverrides.value).filter(([key]) => sourceKeys.has(key))) |
| | | hiddenSeriesKeys.value = hiddenSeriesKeys.value.filter(key => sourceKeys.has(key)) |
| | | const cycleKeys = new Set(items.value.flatMap(item => item.cycleNos.map(cycle => formationCycleKey(item, cycle)))) |
| | |
| | | await api(page, `formation-report/${v1.id}`, 'GET', undefined, 403) |
| | | }) |
| | | |
| | | test('化成页面循环切换、五类四条曲线、版本设置和多页打印', async ({ page }) => { |
| | | test('历史整循环化成页面保留五类四条曲线、版本设置和多页打印', async ({ page }) => { |
| | | await login(page) |
| | | const pageErrors: string[] = [] |
| | | page.on('pageerror', error => pageErrors.push(error.message)) |
| | | await page.goto('/report-formation/new') |
| | | await page.getByRole('button', { name: '打印 / 另存 PDF', exact: true }).click() |
| | | await expect(page.getByText('请先保存报表后再打印', { exact: true })).toBeVisible() |
| | | await page.locator('.source-panel .el-select').click() |
| | | for (const number of [2, 3, 4, 5]) await page.getByRole('option', { name: `化成测试${number} / 曲线验收组 / 同名电池`, exact: true }).click() |
| | | await page.getByRole('combobox', { name: '化成来源', exact: true }).press('Escape') |
| | | const created = (await api(page, 'formation-report', 'POST', { name: '页面化成打印', description: '', selections: selections.slice(1), settings: { ...settings, values: {}, seriesColors: { '8902|8902': '#123456' } } })).data |
| | | // 整循环展示已属于历史契约;隔离库保留旧快照事实,新增工步验收见 formation-step-curves。 |
| | | stack.executeIsolatedSql(`UPDATE t_formation_report_version SET snapshot_json=JSON_REMOVE(snapshot_json,'$.curveMode',${[0, 1, 2, 3].map(index => `'$.items[${index}].stepCurves'`).join(',')},'$.settings.manualChargeSteps','$.settings.curveStepSelections','$.settings.hiddenSeriesKeys','$.settings.activeCycle') WHERE report_id=${created.id}`) |
| | | const id = created.id |
| | | await page.goto(`/report-formation/${id}/edit?mode=view`) |
| | | await expect(page.locator('.chart-card')).toHaveCount(5) |
| | | await expect(page.locator('.chart-legend-item')).toHaveCount(4) |
| | | await expect(page.locator('.chart-legend-bar')).toContainText('化成测试5 · 同名电池') |
| | | await page.locator('.curve-cycle-select').click() |
| | | await page.getByRole('option', { name: '循环3', exact: true }).click() |
| | | await page.getByPlaceholder('请输入报表名称').fill('页面化成打印') |
| | | const colorPicker = page.locator('.chart-legend-item').filter({ hasText: '化成测试2' }).locator('.el-color-picker') |
| | | await colorPicker.click() |
| | | const colorPanel = page.locator('.el-color-picker__panel:visible') |
| | | await colorPanel.locator('input').fill('#123456') |
| | | await colorPanel.getByRole('button', { name: /确定|确认|OK/ }).click() |
| | | await page.getByRole('button', { name: '保存报表', exact: true }).click() |
| | | await expect(page).toHaveURL(/mode=view/) |
| | | const id = Number(page.url().match(/formation\/(\d+)/)![1]) |
| | | const v1 = (await api(page, `formation-report/${id}`)).data |
| | | expect(v1.settings.seriesColors['8902|8902']).toBe('#123456') |
| | | expect(v1.items).toHaveLength(4) |
| | |
| | | `) |
| | | const created = (await api(page, 'formation-report', 'POST', { name: '旧版化成', description: '', selections: [{ testId: 8990, testBatteryId: 8990 }], settings: { ...settings, values: {}, seriesColors: {} } })).data |
| | | // 仅在隔离库构造早期快照,模拟当时尚未保存曲线与工步选择的报表。 |
| | | stack.executeIsolatedSql(`UPDATE t_formation_report_version SET snapshot_json=JSON_REMOVE(snapshot_json,'$.items[0].curves','$.items[0].chargeSteps','$.settings.metrics','$.settings.seriesColors') WHERE report_id=${created.id}`) |
| | | stack.executeIsolatedSql(`UPDATE t_formation_report_version SET snapshot_json=JSON_REMOVE(snapshot_json,'$.curveMode','$.items[0].stepCurves','$.items[0].curves','$.items[0].chargeSteps','$.settings.metrics','$.settings.seriesColors') WHERE report_id=${created.id}`) |
| | | const old = (await api(page, `formation-report/${created.id}`)).data |
| | | await page.context().addInitScript(() => { window.print = () => { document.body.dataset.printRequested = 'true' } }) |
| | | await page.goto(`/report-formation/${created.id}/edit?mode=view`) |
| | |
| | | await expect(page.getByRole('textbox', { name: '化成测试甲 同名电池 循环1 充电容量', exact: true })).toHaveValue('8512.2000') |
| | | await expect(page.getByRole('textbox', { name: '化成测试甲 同名电池 循环2 充电容量', exact: true })).toHaveAttribute('placeholder', '指标缺失') |
| | | await expect(page.getByRole('textbox', { name: '化成测试甲 同名电池 循环1 放电容量', exact: true })).toHaveValue('0.0000') |
| | | await expect(page.locator('[data-cycle="4"] .missing-cycle')).toHaveCount(17) |
| | | await expect(page.locator('[data-cycle="4"] .missing-cycle').first()).toHaveText('无该循环') |
| | | await expect(page.locator('[data-cycle="4"] .charge-termination-row')).toContainText('无该循环') |
| | | await expect(page.getByRole('textbox', { name: '化成测试甲 同名电池 F/N', exact: true })).toHaveValue('') |
| | | await expect(page.getByRole('textbox', { name: '化成测试甲 同名电池 F', exact: true })).toHaveValue('12.5') |
| | | await expect(page.getByText('自动计算', { exact: true })).toHaveCount(0) |
| | |
| | | await expect(page.locator('.cycle-card[data-cycle="1"]')).toContainText('4.222 V') |
| | | await expect(page.locator('.cycle-card[data-cycle="3"] .charge-termination-row').nth(1)).toContainText('缺失') |
| | | const unknown = page.getByRole('combobox', { name: '未知充电工步 工步测试8605 同名电池 循环1', exact: true }) |
| | | await unknown.click() |
| | | await unknown.evaluate(element => element.scrollIntoView({ block: 'center' })) |
| | | await page.locator('.el-select').filter({ has: unknown }).click() |
| | | for (const step of [1, 2]) await page.getByRole('option', { name: `${step} 实际工步${step}`, exact: true }).click() |
| | | await unknown.press('Escape') |
| | | await expect(page.locator('.cycle-card[data-cycle="1"] .charge-termination-row').nth(1).locator('td').last()).toContainText('4.222 V') |
| | | const chargeChoice = page.getByRole('combobox', { name: '充电工步 工步测试8601 同名电池', exact: true }) |
| | | await chargeChoice.click() |
| | | await page.getByRole('option', { name: '1 实际工步1', exact: true }).click() |
| | | await page.locator('.el-select').filter({ has: chargeChoice }).click() |
| | | await page.locator(`#${await chargeChoice.getAttribute('aria-controls')}`).getByRole('option', { name: '1 实际工步1', exact: true }).click() |
| | | await chargeChoice.press('Escape') |
| | | await expect(page.locator('.cycle-card[data-cycle="1"]')).toContainText('4.111 V') |
| | | const legend = page.locator('[data-group="charge"] .chart-legend-item').filter({ hasText: '工步测试8601 · 工步甲组 / 同名电池 · 循环1 工步2' }) |
| | | await legend.getByRole('button').click() |
| | | await expect(legend.getByRole('button')).toHaveAttribute('aria-pressed', 'false') |
| | | await legend.locator('button[aria-pressed]').click() |
| | | await expect(legend.locator('button[aria-pressed]')).toHaveAttribute('aria-pressed', 'false') |
| | | await legend.locator('.el-color-picker').click() |
| | | const panel = page.locator('.el-color-picker__panel:visible') |
| | | await panel.locator('input').fill('#123456') |
| | | await panel.getByRole('button', { name: /确定|确认|OK/ }).click() |
| | | await expect(legend.getByRole('button')).toHaveAttribute('aria-pressed', 'false') |
| | | await expect(legend.locator('button[aria-pressed]')).toHaveAttribute('aria-pressed', 'false') |
| | | await page.getByPlaceholder('请输入报表名称').fill('化成工步独立验收') |
| | | await page.getByRole('button', { name: '保存报表', exact: true }).click() |
| | | await expect(page).toHaveURL(/mode=view/) |
| | |
| | | await api(page, `formation-report/${id}/versions`, 'POST', { name: '陈旧', description: '', baseVersionNo: 1, changeSummary: '陈旧拒绝', settings: v1.settings }, 500) |
| | | stack.executeIsolatedSql('UPDATE t_test_step_record SET voltage_v=9 WHERE test_id=8601; UPDATE t_test_realtime_record SET current_a=99 WHERE test_id=8601') |
| | | const v3 = await api(page, `formation-report/${id}/refresh-source`, 'POST', { baseVersionNo: 2, changeSummary: '主动重读' }) |
| | | expect(v3.items[0].stepCurves['1']['1'].records.every((row: any) => row.current === 99)).toBe(true) |
| | | expect(v3.items[0].chargeSteps['1'][0].endVoltage).toBe(9) |
| | | expect(v3.items.find((item: any) => item.source.selection.testBatteryId === 8601).stepCurves['1']['1'].records.every((row: any) => row.current === 99)).toBe(true) |
| | | expect(v3.items.find((item: any) => item.source.selection.testBatteryId === 8601).chargeSteps['1'][0].endVoltage).toBe(9) |
| | | expect((await api(page, `formation-report/${id}/versions/1`)).items).toEqual(v1.items) |
| | | for (const sourceId of [8601, 8603, 8604, 8605]) await api(page, `test/${sourceId}`, 'DELETE') |
| | | await api(page, `formation-report/${id}/refresh-source`, 'POST', { baseVersionNo: 3, changeSummary: '已删源拒绝' }, 500) |