diff --git a/healthlink-his-ui/src/views/charge/cliniccharge/index.vue b/healthlink-his-ui/src/views/charge/cliniccharge/index.vue
index d5d7c2f9d..aeff9cdb5 100755
--- a/healthlink-his-ui/src/views/charge/cliniccharge/index.vue
+++ b/healthlink-his-ui/src/views/charge/cliniccharge/index.vue
@@ -449,10 +449,17 @@ function checkSelectable(row, index) {
*/
function clickRow(params) {
const row = params.row || params;
- patientInfo.value = row;
+ const encId = row.encounterId ?? row.id;
+ if (encId === undefined || encId === null || encId === '') {
+ proxy.$modal.msgError('患者记录缺少就诊ID,无法加载收费详情');
+ chargeList.value = [];
+ patientInfo.value = row;
+ return;
+ }
+ patientInfo.value = { ...row, encounterId: encId };
chargeLoading.value = true;
- encounterId.value = row.encounterId;
- getChargeList(row.encounterId).then((res) => {
+ encounterId.value = encId;
+ getChargeList(encId).then((res) => {
chargeList.value = res.data;
setTimeout(() => {
chargeLoading.value = false;
diff --git a/healthlink-his-ui/src/views/inpatientDoctor/home/index.vue b/healthlink-his-ui/src/views/inpatientDoctor/home/index.vue
index a4992d0df..a5ec3cb6b 100755
--- a/healthlink-his-ui/src/views/inpatientDoctor/home/index.vue
+++ b/healthlink-his-ui/src/views/inpatientDoctor/home/index.vue
@@ -34,7 +34,7 @@
label="临床医嘱"
name="prescription"
>
-
+
{
+ let undefinedRequests: string[] = [];
+ let jsErrors: string[] = [];
+
+ test.beforeEach(async ({ page }) => {
+ undefinedRequests = [];
+ jsErrors = [];
+
+ page.on('pageerror', (err) => jsErrors.push(err.message));
+ page.on('request', (req) => {
+ const url = req.url();
+ if (url.includes('encounterId=undefined') ||
+ url.includes('encounterId=null') ||
+ url.includes('encounterId=NaN') ||
+ /encounterId=$/.test(url)) {
+ undefinedRequests.push(url);
+ }
+ });
+ });
+
+ test('#681 模拟 clickRow 三种场景:有encounterId / 仅id / 全无', async ({ page }) => {
+ await page.goto('about:blank');
+
+ // 注入测试脚本:模拟前端 clickRow 中请求构造的关键逻辑
+ // 这正是我修复后的代码(从 index.vue 提取):
+ const result = await page.evaluate(() => {
+ const calls: string[] = [];
+ const errors: string[] = [];
+ const mockProxy = { $modal: { msgError: (m: string) => errors.push(m) } };
+
+ // 模拟修复后的 clickRow 核心逻辑
+ function clickRowFixed(row: any): { called: string | null; errorMsg: string | null } {
+ const encId = row.encounterId ?? row.id;
+ if (encId === undefined || encId === null || encId === '') {
+ mockProxy.$modal.msgError('患者记录缺少就诊ID,无法加载收费详情');
+ return { called: null, errorMsg: '患者记录缺少就诊ID,无法加载收费详情' };
+ }
+ const url = '/charge-manage/charge/patient-prescription?encounterId=' + encId;
+ calls.push(url);
+ return { called: url, errorMsg: null };
+ }
+
+ // 场景 1:有 encounterId
+ const r1 = clickRowFixed({ encounterId: 1001, patientName: '张三' });
+ // 场景 2:无 encounterId 但有 id(兜底)
+ const r2 = clickRowFixed({ id: 2002, patientName: '李四' });
+ // 场景 3:encounterId 和 id 都缺(错误提示)
+ const r3 = clickRowFixed({ patientName: '王五' });
+ // 场景 4:encounterId 是 undefined
+ const r4 = clickRowFixed({ encounterId: undefined, patientName: '赵六' });
+ // 场景 5:encounterId 是 null
+ const r5 = clickRowFixed({ encounterId: null, patientName: '孙七' });
+ // 场景 6:encounterId 是空字符串
+ const r6 = clickRowFixed({ encounterId: '', patientName: '周八' });
+
+ return {
+ calls,
+ errors,
+ scenarios: [r1, r2, r3, r4, r5, r6],
+ };
+ });
+
+ console.log('calls:', result.calls);
+ console.log('errors:', result.errors);
+ console.log('scenarios:', JSON.stringify(result.scenarios, null, 2));
+
+ // 断言 1:只有场景 1 和 2 发出请求,且 URL 中不含 undefined
+ expect(result.calls.length).toBe(2);
+ expect(result.calls[0]).toContain('encounterId=1001');
+ expect(result.calls[1]).toContain('encounterId=2002');
+ result.calls.forEach((url) => {
+ expect(url).not.toContain('undefined');
+ expect(url).not.toContain('null');
+ expect(url).not.toContain('NaN');
+ });
+
+ // 断言 2:场景 3-6 都触发了 msgError,且没发请求
+ expect(result.errors.length).toBe(4);
+ result.errors.forEach((msg) => {
+ expect(msg).toContain('患者记录缺少就诊ID');
+ });
+
+ // 断言 3:场景 1 没报错、场景 3-6 报错了
+ expect(result.scenarios[0].errorMsg).toBeNull();
+ expect(result.scenarios[1].errorMsg).toBeNull();
+ expect(result.scenarios[2].errorMsg).not.toBeNull();
+ expect(result.scenarios[3].errorMsg).not.toBeNull();
+ expect(result.scenarios[4].errorMsg).not.toBeNull();
+ expect(result.scenarios[5].errorMsg).not.toBeNull();
+ });
+
+ test('#681 对比修复前:无兜底时会发出 encounterId=undefined 请求', async ({ page }) => {
+ await page.goto('about:blank');
+
+ // 模拟修复前的 clickRow 行为(旧代码)
+ const result = await page.evaluate(() => {
+ const calls: string[] = [];
+ // 旧代码:直接 row.encounterId 拼接
+ function clickRowOld(row: any): string {
+ const url = '/charge-manage/charge/patient-prescription?encounterId=' + row.encounterId;
+ calls.push(url);
+ return url;
+ }
+ // 场景:encounterId 缺失(这正是 bug 的触发条件)
+ const url = clickRowOld({ patientName: '王五' });
+ return { calls, lastUrl: url };
+ });
+
+ console.log('OLD calls:', result.calls);
+
+ // 修复前的代码会发出 encounterId=undefined 请求
+ expect(result.lastUrl).toContain('encounterId=undefined');
+
+ // 这正是 bug 的表现 → 我修复后不会发生
+ });
+});