借款材料区按需显示并前置缺项提示(09-17-company-loan-principal-repayment)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

- 材料区只为仍缺的材料提供上传:原件已存显示可查看,在线确认后收起协议框,历史还款依据仅在登记期初小于原本金时出现
- 余额材料改中性文案(公司银行流水或代账明细账),确认字段改为“余额依据说明”,按钮改为“确认借款余额”并前置列出缺项
- 确认弹窗跟随最新列表状态:刷新中、刷新失败、版本变化、已确认或缺项时禁用按钮与提交
- 浏览器测试覆盖显隐、缺项、材料失效、在线确认失效、刷新与弹窗打开后状态变化;同步操作手册
- 只读复核 P2 已修复关闭;不改后端、接口与数据库

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
2026-10-12 15:58:10 +08:00
共同撰写人 Claude Opus 5.5
父节点 3a4a5969bb
当前提交 c251729267
共修改 8 个文件,包含 274 行新增和 35 行删除
+10 -2
查看文件
@@ -76,15 +76,23 @@ module.exports = async function runBrowser({ app, finance, manager, ordinary, pa
const card = page.locator('section').filter({ has: page.getByRole('heading', { name: `${lenderName} · ${loan.loan_no}`, exact: true }) });
await findOnPages(page, card, 'company-loans');
await card.locator('summary').click();
// No online statement for an external lender: the agreement is offered as
// one of two options, and every gap is named before confirmation.
await expect(card).toContainText('有效在线确认或协议/借款确认书,任选一种');
await expect(card.getByRole('button', { name: '去出借人确认查看或办理', exact: true })).toHaveCount(0);
await expect(card.locator(`[id="${loan.id}-missing"]`)).toHaveText('还缺:原借入凭据、余额核对材料、协议或借款确认书');
await expect(card.getByRole('button', { name: '确认借款余额', exact: true })).toBeDisabled();
for (const kind of ['agreement', 'incoming', 'accounting_confirmation']) {
const received = page.waitForResponse(r => r.url().endsWith(`/company-loans/${loan.id}/evidences/${kind}`) && r.request().method() === 'POST');
await page.locator(`[id="${loan.id}-${kind}"]`).setInputFiles({ name: 'synthetic.pdf', mimeType: 'application/pdf',
buffer: Buffer.from(`%PDF-1.4\n% synthetic-${kind}-${loan.id}\n1 0 obj << /Type /Catalog >> endobj\n%%EOF\n`) });
assert.equal((await received).status(), 200);
}
await card.getByRole('button', { name: '确认期初余额' }).click();
await expect(card.locator(`[id="${loan.id}-incoming"]`)).toHaveCount(0);
await expect(card).toContainText('已保存,可查看');
await card.getByRole('button', { name: '确认借款余额' }).click();
dialog = page.getByRole('dialog');
await dialog.getByLabel('代账余额确认引用').fill('合成代账核对');
await dialog.getByLabel('余额依据说明').fill('合成银行流水核对');
await dialog.getByRole('button', { name: '确认', exact: true }).click();
await expect(dialog).not.toBeVisible();
await expect(card).toContainText('余额已确认');