diff --git a/openhis-server-new/core-framework/src/main/java/com/core/framework/config/MybatisPlusConfig.java b/openhis-server-new/core-framework/src/main/java/com/core/framework/config/MybatisPlusConfig.java
index 16b55543..278374e4 100644
--- a/openhis-server-new/core-framework/src/main/java/com/core/framework/config/MybatisPlusConfig.java
+++ b/openhis-server-new/core-framework/src/main/java/com/core/framework/config/MybatisPlusConfig.java
@@ -1,22 +1,29 @@
package com.core.framework.config;
import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.core.common.utils.SecurityUtils;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
+import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -149,4 +156,41 @@ public class MybatisPlusConfig {
return result != null ? result : 1; // 默认租户ID
}
+
+ /**
+ * 配置 SqlSessionFactory
+ * 由于排除了 DataSourceAutoConfiguration,需要手动配置
+ */
+ @Bean
+ @Primary
+ public SqlSessionFactory sqlSessionFactory(
+ @Qualifier("dynamicDataSource") DataSource dataSource,
+ MybatisPlusInterceptor mybatisPlusInterceptor) throws Exception {
+ MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
+ sessionFactory.setDataSource(dataSource);
+ // 设置 mapper 文件位置
+ sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
+ .getResources("classpath*:mapper/**/*Mapper.xml"));
+ // 设置 typeAliases 包路径
+ sessionFactory.setTypeAliasesPackage("com.core.**.domain,com.openhis.**.domain");
+
+ // 配置 MyBatis-Plus
+ MybatisConfiguration configuration = new MybatisConfiguration();
+ // 使用驼峰命名法转换字段
+ configuration.setMapUnderscoreToCamelCase(true);
+ // 开启缓存
+ configuration.setCacheEnabled(true);
+ // 允许JDBC支持自动生成主键
+ configuration.setUseGeneratedKeys(true);
+ // 配置默认的执行器
+ configuration.setDefaultExecutorType(org.apache.ibatis.session.ExecutorType.SIMPLE);
+ // 配置日志实现
+ configuration.setLogImpl(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
+ sessionFactory.setConfiguration(configuration);
+
+ // 设置拦截器(通过参数注入避免循环依赖)
+ sessionFactory.setPlugins(mybatisPlusInterceptor);
+
+ return sessionFactory.getObject();
+ }
}
diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientPricingAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientPricingAppServiceImpl.java
index 2216b1d4..a349312b 100644
--- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientPricingAppServiceImpl.java
+++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientPricingAppServiceImpl.java
@@ -73,8 +73,10 @@ public class OutpatientPricingAppServiceImpl implements IOutpatientPricingAppSer
} else {
adviceTypes = List.of(1, 2, 3);
}
+ // 门诊划价:不要强制 pricingFlag=1 参与过滤(wor_activity_definition.pricing_flag 可能为 0),
+ // 否则会导致诊疗项目(adviceType=3)查询结果为空 records=[]
return iDoctorStationAdviceAppService.getAdviceBaseInfo(adviceBaseDto, searchKey, locationId, null,
- organizationId, pageNo, pageSize, Whether.YES.getValue(), adviceTypes, null);
+ organizationId, pageNo, pageSize, null, adviceTypes, null);
}
}
diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java
index 78f0b1d6..43449e7f 100644
--- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java
+++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java
@@ -127,8 +127,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
log.info("从数据库查询医嘱基础信息");
- // 设置默认科室 (不取前端传的了)
- organizationId = SecurityUtils.getLoginUser().getOrgId();
+ // 设置默认科室:仅当前端/调用方未传 organizationId 时才回退到登录人科室
+ // 否则会导致门诊划价等场景(按患者挂号科室查询)返回空
+ if (organizationId == null) {
+ organizationId = SecurityUtils.getLoginUser().getOrgId();
+ }
// 医嘱定价来源
String orderPricingSource = TenantOptionUtil.getOptionContent(TenantOptionDict.ORDER_PRICING_SOURCE);
diff --git a/openhis-server-new/openhis-application/src/main/resources/mapper/chargemanage/OutpatientChargeAppMapper.xml b/openhis-server-new/openhis-application/src/main/resources/mapper/chargemanage/OutpatientChargeAppMapper.xml
index a14229d4..59923679 100644
--- a/openhis-server-new/openhis-application/src/main/resources/mapper/chargemanage/OutpatientChargeAppMapper.xml
+++ b/openhis-server-new/openhis-application/src/main/resources/mapper/chargemanage/OutpatientChargeAppMapper.xml
@@ -112,6 +112,7 @@
ON T1.context_enum = #{activity}
AND T1.product_id = T2.id
AND T2.delete_flag = '0'
+ AND T2.status_enum = 1
LEFT JOIN med_medication_definition AS T3
ON T1.context_enum = #{medication}
AND T1.product_id = T3.id
@@ -205,6 +206,7 @@
ON T1.context_enum = #{activity}
AND T1.product_id = T2.id
AND T2.delete_flag = '0'
+ AND T2.status_enum = 1
LEFT JOIN med_medication_definition AS T3
ON T1.context_enum = #{medication}
AND T1.product_id = T3.id
diff --git a/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml b/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml
index 6c3d5c7d..c1b16c22 100644
--- a/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml
+++ b/openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml
@@ -227,8 +227,11 @@
AND T2.instance_table = #{activityTableName}
LEFT JOIN adm_organization_location AS T3 ON T3.activity_definition_id = T1.ID
AND T3.delete_flag = '0' AND (CURRENT_TIME :: time (6) BETWEEN T3.start_time AND T3.end_time)
+
+ AND T3.organization_id = #{organizationId}
+
WHERE T1.delete_flag = '0'
-
+
AND (T1.pricing_flag = #{pricingFlag} OR T1.pricing_flag IS NULL)
diff --git a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/DictAspect.java b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/DictAspect.java
index 59b0d269..074343d7 100644
--- a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/DictAspect.java
+++ b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/DictAspect.java
@@ -117,10 +117,15 @@ public class DictAspect {
private String queryDictLabel(String dictTable, String dictCode, String dictText, String dictValue) {
if (!StringUtils.hasText(dictTable)) {
- // 场景 1:默认字典走DictUtils缓存
+ // 场景 1:默认字典走DictUtils缓存(dictTable 为空时)
return DictUtils.getDictLabel(dictCode, dictValue);
} else {
- // 场景 2:查询指定表
+ // 场景 2:查询指定表(dictTable 有值时)
+ // 必须同时有 dictTable 和 dictText 才能执行 SQL 查询
+ if (!StringUtils.hasText(dictText)) {
+ // 如果 dictText 为空,回退到字典缓存查询
+ return DictUtils.getDictLabel(dictCode, dictValue);
+ }
String sql = String.format("SELECT %s FROM %s WHERE %s::varchar = ? LIMIT 1", dictText, dictTable, dictCode);
try {
return jdbcTemplate.queryForObject(sql, String.class, dictValue);
diff --git a/openhis-server-new/sql/check_outpatient_charge_activity_data.sql b/openhis-server-new/sql/check_outpatient_charge_activity_data.sql
new file mode 100644
index 00000000..a1b3a3cb
--- /dev/null
+++ b/openhis-server-new/sql/check_outpatient_charge_activity_data.sql
@@ -0,0 +1,94 @@
+-- ============================================
+-- 检查门诊划价"诊疗判断"下没有数据的原因
+-- ============================================
+
+-- 1. 检查是否有诊疗类型的收费项目(context_enum = 3)
+SELECT
+ COUNT(*) AS total_activity_charge_items,
+ COUNT(CASE WHEN delete_flag = '0' THEN 1 END) AS active_charge_items
+FROM adm_charge_item
+WHERE context_enum = 3; -- ACTIVITY = 3
+
+-- 2. 检查诊疗类型的收费项目是否能关联到 wor_activity_definition
+SELECT
+ T1.id AS charge_item_id,
+ T1.encounter_id,
+ T1.context_enum,
+ T1.product_id,
+ T1.status_enum AS charge_status,
+ T2.id AS activity_def_id,
+ T2.name AS activity_name,
+ T2.status_enum AS activity_status,
+ T2.delete_flag AS activity_delete_flag,
+ CASE
+ WHEN T2.id IS NULL THEN '❌ 无法关联到诊疗项目定义'
+ WHEN T2.delete_flag != '0' THEN '❌ 诊疗项目定义已删除'
+ WHEN T2.status_enum != 1 THEN '❌ 诊疗项目定义未激活(status_enum != 1)'
+ ELSE '✅ 正常'
+ END AS match_status
+FROM adm_charge_item AS T1
+LEFT JOIN wor_activity_definition AS T2
+ ON T1.context_enum = 3
+ AND T1.product_id = T2.id
+ AND T2.delete_flag = '0'
+ AND T2.status_enum = 1 -- 当前查询条件
+WHERE T1.context_enum = 3
+ AND T1.delete_flag = '0'
+LIMIT 20;
+
+-- 3. 检查如果移除 status_enum = 1 条件,能关联多少条
+SELECT
+ COUNT(*) AS total_count,
+ COUNT(CASE WHEN T2.id IS NOT NULL AND T2.delete_flag = '0' AND T2.status_enum = 1 THEN 1 END) AS matched_active,
+ COUNT(CASE WHEN T2.id IS NOT NULL AND T2.delete_flag = '0' AND T2.status_enum != 1 THEN 1 END) AS matched_inactive,
+ COUNT(CASE WHEN T2.id IS NULL THEN 1 END) AS unmatched
+FROM adm_charge_item AS T1
+LEFT JOIN wor_activity_definition AS T2
+ ON T1.context_enum = 3
+ AND T1.product_id = T2.id
+ AND T2.delete_flag = '0'
+WHERE T1.context_enum = 3
+ AND T1.delete_flag = '0';
+
+-- 4. 检查具体某个就诊的诊疗项目(替换 encounterId 为实际值)
+-- SELECT
+-- T1.id AS charge_item_id,
+-- T1.encounter_id,
+-- T1.product_id,
+-- T1.status_enum AS charge_status,
+-- T2.id AS activity_def_id,
+-- T2.name AS activity_name,
+-- T2.status_enum AS activity_status,
+-- CASE
+-- WHEN T2.id IS NULL THEN '无法关联'
+-- WHEN T2.status_enum != 1 THEN '诊疗项目未激活'
+-- ELSE '正常'
+-- END AS status
+-- FROM adm_charge_item AS T1
+-- LEFT JOIN wor_activity_definition AS T2
+-- ON T1.context_enum = 3
+-- AND T1.product_id = T2.id
+-- AND T2.delete_flag = '0'
+-- AND T2.status_enum = 1
+-- WHERE T1.encounter_id = :encounterId -- 替换为实际的encounterId
+-- AND T1.context_enum = 3
+-- AND T1.delete_flag = '0';
+
+-- 5. 如果诊疗项目 status_enum != 1,查看这些项目
+SELECT
+ T1.id AS charge_item_id,
+ T1.encounter_id,
+ T1.product_id,
+ T2.name AS activity_name,
+ T2.status_enum AS activity_status,
+ '诊疗项目未激活,导致无法显示' AS issue
+FROM adm_charge_item AS T1
+INNER JOIN wor_activity_definition AS T2
+ ON T1.context_enum = 3
+ AND T1.product_id = T2.id
+ AND T2.delete_flag = '0'
+ AND T2.status_enum != 1 -- 未激活
+WHERE T1.context_enum = 3
+ AND T1.delete_flag = '0'
+LIMIT 20;
+
diff --git a/openhis-server-new/sql/check_pricing_flag_zero_data.sql b/openhis-server-new/sql/check_pricing_flag_zero_data.sql
new file mode 100644
index 00000000..5e9e63a7
--- /dev/null
+++ b/openhis-server-new/sql/check_pricing_flag_zero_data.sql
@@ -0,0 +1,142 @@
+-- ============================================
+-- 检查 wor_activity_definition 表中 pricing_flag = 0 的数据
+-- 用途:分析哪些项目被标记为"不允许划价",是否符合业务预期
+-- ============================================
+
+-- 1. 查看所有 pricing_flag = 0 的项目详情
+SELECT
+ id,
+ bus_no,
+ name AS activity_name,
+ category_code,
+ type_enum,
+ pricing_flag,
+ status_enum,
+ org_id,
+ location_id,
+ description_text,
+ create_time,
+ update_time
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND pricing_flag = '0' -- 注意:字段类型是 char(1),所以是字符串 '0'
+ORDER BY id;
+
+-- 2. 统计 pricing_flag = 0 的项目数量(按状态)
+SELECT
+ status_enum,
+ COUNT(*) AS count,
+ CASE
+ WHEN status_enum = 1 THEN '激活'
+ WHEN status_enum = 2 THEN '停用'
+ ELSE '其他'
+ END AS status_desc
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND pricing_flag = '0'
+GROUP BY status_enum
+ORDER BY status_enum;
+
+-- 3. 检查 pricing_flag = 0 的项目是否有关联的费用定价
+SELECT
+ T1.id,
+ T1.bus_no,
+ T1.name AS activity_name,
+ T1.pricing_flag,
+ T1.status_enum,
+ T2.id AS charge_item_definition_id,
+ T2.charge_name,
+ T2.price,
+ T2.status_enum AS charge_status,
+ CASE
+ WHEN T2.id IS NOT NULL THEN '有费用定价但不允许划价(可能异常)'
+ ELSE '无费用定价,不允许划价(正常)'
+ END AS analysis
+FROM wor_activity_definition AS T1
+LEFT JOIN adm_charge_item_definition AS T2
+ ON T2.instance_id = T1.id
+ AND T2.delete_flag = '0'
+ AND T2.status_enum = 1
+ AND T2.instance_table = 'wor_activity_definition'
+WHERE T1.delete_flag = '0'
+ AND T1.pricing_flag = '0'
+ORDER BY T1.id;
+
+-- 4. 检查 pricing_flag = 0 的项目是否在收费项目表中被使用
+SELECT
+ T1.id AS activity_id,
+ T1.bus_no,
+ T1.name AS activity_name,
+ T1.pricing_flag,
+ COUNT(T3.id) AS charge_item_count,
+ CASE
+ WHEN COUNT(T3.id) > 0 THEN '已被使用(可能异常:不允许划价但已有收费记录)'
+ ELSE '未被使用(正常)'
+ END AS analysis
+FROM wor_activity_definition AS T1
+LEFT JOIN adm_charge_item AS T3
+ ON T3.product_id = T1.id
+ AND T3.context_enum = 3 -- ACTIVITY
+ AND T3.delete_flag = '0'
+WHERE T1.delete_flag = '0'
+ AND T1.pricing_flag = '0'
+GROUP BY T1.id, T1.bus_no, T1.name, T1.pricing_flag
+HAVING COUNT(T3.id) > 0 -- 只显示已被使用的
+ORDER BY charge_item_count DESC;
+
+-- 5. 按类别统计 pricing_flag = 0 的项目
+SELECT
+ category_code,
+ COUNT(*) AS count,
+ STRING_AGG(name, ', ') AS activity_names -- 列出项目名称
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND pricing_flag = '0'
+ AND status_enum = 1 -- 只统计激活的
+GROUP BY category_code
+ORDER BY category_code;
+
+-- 6. 对比:pricing_flag = 0 和 pricing_flag = 1 的项目特征
+SELECT
+ pricing_flag,
+ COUNT(*) AS count,
+ COUNT(DISTINCT category_code) AS category_count,
+ COUNT(DISTINCT org_id) AS org_count,
+ STRING_AGG(DISTINCT category_code::text, ', ') AS categories
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1
+ AND pricing_flag IN ('0', '1')
+GROUP BY pricing_flag
+ORDER BY pricing_flag;
+
+-- 7. 检查是否有子项的项目(childrenJson 不为空)被标记为 pricing_flag = 0
+SELECT
+ id,
+ bus_no,
+ name AS activity_name,
+ pricing_flag,
+ children_json,
+ CASE
+ WHEN children_json IS NOT NULL AND children_json != '' THEN '有子项但不允许划价(可能是套餐子项)'
+ ELSE '无子项'
+ END AS analysis
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND pricing_flag = '0'
+ AND children_json IS NOT NULL
+ AND children_json != ''
+ORDER BY id;
+
+-- 8. 查看 pricing_flag 字段的所有可能值(包括 NULL)
+SELECT
+ COALESCE(pricing_flag::text, 'NULL') AS pricing_flag_value,
+ COUNT(*) AS count,
+ ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 2) AS percentage
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1
+GROUP BY pricing_flag
+ORDER BY pricing_flag NULLS LAST;
+
+
diff --git a/openhis-server-new/sql/check_treatment_items_detailed.sql b/openhis-server-new/sql/check_treatment_items_detailed.sql
new file mode 100644
index 00000000..8513779d
--- /dev/null
+++ b/openhis-server-new/sql/check_treatment_items_detailed.sql
@@ -0,0 +1,116 @@
+-- 详细检查诊疗项目检索问题
+-- 已知:wor_activity_definition 表中有4条数据
+
+-- 1. 检查这4条诊疗项目定义的详细信息
+SELECT
+ id,
+ name,
+ bus_no,
+ delete_flag,
+ tenant_id,
+ create_time
+FROM wor_activity_definition
+ORDER BY id;
+
+-- 2. 检查收费项目中是否有诊疗项目类型的记录
+-- 注意:ChargeItemContext.ACTIVITY.getValue() 返回的是 Integer 3
+-- 但数据库中 context_enum 可能是字符串类型,需要检查是 '3' 还是 3
+SELECT
+ COUNT(*) as total_activity_charge_items,
+ COUNT(CASE WHEN delete_flag = '0' THEN 1 END) as active_activity_charge_items,
+ COUNT(CASE WHEN delete_flag != '0' THEN 1 END) as deleted_activity_charge_items
+FROM adm_charge_item
+WHERE context_enum::text = '3' OR context_enum = 3; -- 诊疗项目类型是3
+
+-- 3. 检查收费项目中的product_id是否能匹配到诊疗项目定义
+-- 注意:诊疗项目类型的 context_enum = 3(ChargeItemContext.ACTIVITY.getValue())
+SELECT
+ aci.id as charge_item_id,
+ aci.encounter_id,
+ aci.context_enum,
+ aci.product_id as charge_product_id,
+ aci.status_enum,
+ aci.delete_flag as charge_delete_flag,
+ wad.id as activity_def_id,
+ wad.name as activity_name,
+ wad.delete_flag as activity_delete_flag,
+ CASE
+ WHEN wad.id IS NULL THEN '❌ 诊疗项目定义不存在'
+ WHEN wad.delete_flag != '0' THEN '❌ 诊疗项目定义已删除'
+ WHEN aci.delete_flag != '0' THEN '❌ 收费项目已删除'
+ ELSE '✅ 正常'
+ END as match_status
+FROM adm_charge_item aci
+LEFT JOIN wor_activity_definition wad
+ ON aci.product_id = wad.id
+WHERE (aci.context_enum::text = '3' OR aci.context_enum = 3) -- 诊疗项目类型是3
+LIMIT 20;
+
+-- 4. 检查context_enum的所有可能值(确认诊疗项目的枚举值是什么)
+SELECT DISTINCT
+ context_enum,
+ COUNT(*) as count
+FROM adm_charge_item
+WHERE delete_flag = '0'
+GROUP BY context_enum
+ORDER BY context_enum;
+
+-- 5. 检查是否有收费项目,但无法匹配到诊疗项目定义
+SELECT
+ COUNT(*) as unmatched_count,
+ STRING_AGG(DISTINCT CAST(product_id AS VARCHAR), ', ') as unmatched_product_ids,
+ STRING_AGG(DISTINCT CAST(id AS VARCHAR), ', ') as unmatched_charge_item_ids
+FROM adm_charge_item aci
+WHERE (aci.context_enum::text = '3' OR aci.context_enum = 3) -- 诊疗项目类型是3
+ AND aci.delete_flag = '0'
+ AND NOT EXISTS (
+ SELECT 1
+ FROM wor_activity_definition wad
+ WHERE wad.id = aci.product_id
+ AND wad.delete_flag = '0'
+ );
+
+-- 6. 检查具体某个就诊的诊疗项目(如果有具体的encounterId)
+-- SELECT
+-- T1.encounter_id,
+-- T1.id as charge_item_id,
+-- T1.context_enum,
+-- T1.product_id,
+-- T1.status_enum,
+-- T1.delete_flag,
+-- T2.id as activity_def_id,
+-- T2.name as activity_name,
+-- T2.delete_flag as activity_delete_flag
+-- FROM adm_charge_item AS T1
+-- LEFT JOIN wor_activity_definition AS T2
+-- ON T1.product_id = T2.id
+-- WHERE T1.encounter_id = :encounterId -- 替换为实际的encounterId
+-- AND T1.context_enum IN ('ACTIVITY', '1', 'ACTIVITY_CODE') -- 尝试多种可能的值
+-- AND T1.delete_flag = '0';
+
+-- 7. 检查后端代码中使用的context_enum值
+-- ChargeItemContext.ACTIVITY.getValue() 的实际返回值需要查看枚举类
+-- 可能是:'ACTIVITY', '1', 'ACTIVITY_CODE', 或其他值
+-- 建议先运行查询4,查看数据库中实际使用的context_enum值
+
+-- 8. 检查status_enum的值(查询条件中需要匹配的状态)
+-- SQL查询中要求 status_enum IN (1, 2, 3, 4, 5, 6)
+-- 检查收费项目中的状态值是否在这个范围内
+SELECT
+ status_enum,
+ COUNT(*) as count,
+ CASE
+ WHEN status_enum IN (1, 2, 3, 4, 5, 6) THEN '✅ 在查询范围内'
+ ELSE '❌ 不在查询范围内'
+ END as status_check
+FROM adm_charge_item
+WHERE context_enum IN (
+ SELECT DISTINCT context_enum
+ FROM adm_charge_item
+ WHERE delete_flag = '0'
+ LIMIT 10
+)
+AND delete_flag = '0'
+GROUP BY status_enum
+ORDER BY status_enum;
+
diff --git a/openhis-server-new/sql/diagnose_treatment_items_issue.sql b/openhis-server-new/sql/diagnose_treatment_items_issue.sql
new file mode 100644
index 00000000..a3670c28
--- /dev/null
+++ b/openhis-server-new/sql/diagnose_treatment_items_issue.sql
@@ -0,0 +1,92 @@
+-- 诊断:门诊划价检索不出诊疗项目的问题
+-- 问题描述:在门诊划价页面,检索不出诊疗项目
+
+-- 1. 检查是否有诊疗项目定义数据
+SELECT
+ COUNT(*) as total_count,
+ COUNT(CASE WHEN delete_flag = '0' THEN 1 END) as active_count,
+ COUNT(CASE WHEN delete_flag != '0' THEN 1 END) as deleted_count
+FROM wor_activity_definition;
+
+-- 2. 检查是否有收费项目(诊疗项目类型)
+SELECT
+ T1.id,
+ T1.encounter_id,
+ T1.context_enum,
+ T1.product_id,
+ T1.status_enum,
+ T1.delete_flag,
+ T2.id as activity_def_id,
+ T2.name as activity_name,
+ T2.delete_flag as activity_delete_flag
+FROM adm_charge_item AS T1
+LEFT JOIN wor_activity_definition AS T2
+ ON T1.context_enum = 'ACTIVITY' -- 诊疗项目类型
+ AND T1.product_id = T2.id
+ AND T2.delete_flag = '0'
+WHERE T1.context_enum = 'ACTIVITY'
+ AND T1.delete_flag = '0'
+LIMIT 20;
+
+-- 3. 检查是否有诊疗项目定义,但收费项目中的product_id无法匹配
+SELECT
+ '诊疗项目定义存在,但收费项目无法匹配' as issue_type,
+ COUNT(*) as count
+FROM wor_activity_definition wad
+WHERE wad.delete_flag = '0'
+ AND NOT EXISTS (
+ SELECT 1
+ FROM adm_charge_item aci
+ WHERE aci.context_enum = 'ACTIVITY'
+ AND aci.product_id = wad.id
+ AND aci.delete_flag = '0'
+ );
+
+-- 4. 检查收费项目中的诊疗项目,但定义表中没有对应数据
+SELECT
+ '收费项目存在,但诊疗项目定义缺失' as issue_type,
+ COUNT(*) as count
+FROM adm_charge_item aci
+WHERE aci.context_enum = 'ACTIVITY'
+ AND aci.delete_flag = '0'
+ AND NOT EXISTS (
+ SELECT 1
+ FROM wor_activity_definition wad
+ WHERE wad.id = aci.product_id
+ AND wad.delete_flag = '0'
+ );
+
+-- 5. 检查某个具体就诊的诊疗项目(替换encounterId为实际值)
+-- SELECT
+-- T1.encounter_id,
+-- T1.id as charge_item_id,
+-- T1.context_enum,
+-- T1.product_id,
+-- T1.status_enum,
+-- T2.id as activity_def_id,
+-- T2.name as activity_name,
+-- T2.delete_flag as activity_delete_flag,
+-- CASE
+-- WHEN T2.id IS NULL THEN '诊疗项目定义不存在或已删除'
+-- WHEN T2.delete_flag != '0' THEN '诊疗项目定义已删除'
+-- ELSE '正常'
+-- END as status
+-- FROM adm_charge_item AS T1
+-- LEFT JOIN wor_activity_definition AS T2
+-- ON T1.context_enum = 'ACTIVITY'
+-- AND T1.product_id = T2.id
+-- WHERE T1.encounter_id = :encounterId -- 替换为实际的encounterId
+-- AND T1.context_enum = 'ACTIVITY'
+-- AND T1.delete_flag = '0'
+-- AND T1.status_enum IN (1, 2, 3, 4, 5, 6); -- PLANNED, BILLABLE, BILLED, REFUNDING, REFUNDED, PART_REFUND
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openhis-server-new/sql/query_pricing_flag_distribution.sql b/openhis-server-new/sql/query_pricing_flag_distribution.sql
new file mode 100644
index 00000000..79220e0d
--- /dev/null
+++ b/openhis-server-new/sql/query_pricing_flag_distribution.sql
@@ -0,0 +1,144 @@
+-- ============================================
+-- 查询诊疗项目 pricing_flag 字段分布情况
+-- 用途:了解哪些项目允许划价,哪些不允许
+-- ============================================
+
+-- 1. 统计 pricing_flag 字段的分布情况
+SELECT
+ COUNT(*) AS total_count,
+ COUNT(CASE WHEN pricing_flag = 1 THEN 1 END) AS pricing_flag_1_count, -- 允许划价
+ COUNT(CASE WHEN pricing_flag = 0 THEN 1 END) AS pricing_flag_0_count, -- 不允许划价
+ COUNT(CASE WHEN pricing_flag IS NULL THEN 1 END) AS pricing_flag_null_count, -- 未设置
+ ROUND(COUNT(CASE WHEN pricing_flag = 1 THEN 1 END) * 100.0 / COUNT(*), 2) AS flag_1_percent,
+ ROUND(COUNT(CASE WHEN pricing_flag = 0 THEN 1 END) * 100.0 / COUNT(*), 2) AS flag_0_percent,
+ ROUND(COUNT(CASE WHEN pricing_flag IS NULL THEN 1 END) * 100.0 / COUNT(*), 2) AS flag_null_percent
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1; -- 只统计激活状态的项目
+
+-- 2. 查看所有允许划价的项目(pricing_flag = 1 或 NULL)
+SELECT
+ id,
+ bus_no,
+ name AS activity_name,
+ pricing_flag,
+ status_enum,
+ org_id,
+ category_code,
+ type_enum,
+ CASE
+ WHEN pricing_flag = 1 THEN '允许划价'
+ WHEN pricing_flag = 0 THEN '不允许划价'
+ WHEN pricing_flag IS NULL THEN '未设置(默认允许)'
+ ELSE '未知'
+ END AS pricing_flag_desc
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1
+ AND (pricing_flag = 1 OR pricing_flag IS NULL) -- 之前过滤条件
+ORDER BY id;
+
+-- 3. 查看不允许划价的项目(pricing_flag = 0)
+SELECT
+ id,
+ bus_no,
+ name AS activity_name,
+ pricing_flag,
+ status_enum,
+ org_id,
+ category_code,
+ type_enum,
+ description_text,
+ '不允许划价' AS pricing_flag_desc
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1
+ AND pricing_flag = 0 -- 这些项目之前不会显示
+ORDER BY id;
+
+-- 4. 查看未设置 pricing_flag 的项目(NULL)
+SELECT
+ id,
+ bus_no,
+ name AS activity_name,
+ pricing_flag,
+ status_enum,
+ org_id,
+ category_code,
+ type_enum,
+ '未设置(默认允许)' AS pricing_flag_desc
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1
+ AND pricing_flag IS NULL
+ORDER BY id;
+
+-- 5. 按科室统计 pricing_flag 分布
+SELECT
+ org_id,
+ COUNT(*) AS total_count,
+ COUNT(CASE WHEN pricing_flag = 1 THEN 1 END) AS flag_1_count,
+ COUNT(CASE WHEN pricing_flag = 0 THEN 1 END) AS flag_0_count,
+ COUNT(CASE WHEN pricing_flag IS NULL THEN 1 END) AS flag_null_count
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1
+GROUP BY org_id
+ORDER BY org_id;
+
+-- 6. 按类别统计 pricing_flag 分布
+SELECT
+ category_code,
+ COUNT(*) AS total_count,
+ COUNT(CASE WHEN pricing_flag = 1 THEN 1 END) AS flag_1_count,
+ COUNT(CASE WHEN pricing_flag = 0 THEN 1 END) AS flag_0_count,
+ COUNT(CASE WHEN pricing_flag IS NULL THEN 1 END) AS flag_null_count
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND status_enum = 1
+GROUP BY category_code
+ORDER BY category_code;
+
+-- 7. 检查是否有费用定价关联的项目,但 pricing_flag = 0
+SELECT
+ T1.id,
+ T1.bus_no,
+ T1.name AS activity_name,
+ T1.pricing_flag,
+ T2.id AS charge_item_definition_id,
+ T2.charge_name,
+ T2.price,
+ '有费用定价但不允许划价' AS issue_desc
+FROM wor_activity_definition AS T1
+LEFT JOIN adm_charge_item_definition AS T2
+ ON T2.instance_id = T1.id
+ AND T2.delete_flag = '0'
+ AND T2.status_enum = 1
+ AND T2.instance_table = 'wor_activity_definition'
+WHERE T1.delete_flag = '0'
+ AND T1.status_enum = 1
+ AND T1.pricing_flag = 0
+ AND T2.id IS NOT NULL -- 有关联的费用定价
+ORDER BY T1.id;
+
+-- 8. 检查没有费用定价关联的项目,但 pricing_flag = 1
+SELECT
+ T1.id,
+ T1.bus_no,
+ T1.name AS activity_name,
+ T1.pricing_flag,
+ T2.id AS charge_item_definition_id,
+ '允许划价但没有费用定价' AS issue_desc
+FROM wor_activity_definition AS T1
+LEFT JOIN adm_charge_item_definition AS T2
+ ON T2.instance_id = T1.id
+ AND T2.delete_flag = '0'
+ AND T2.status_enum = 1
+ AND T2.instance_table = 'wor_activity_definition'
+WHERE T1.delete_flag = '0'
+ AND T1.status_enum = 1
+ AND (T1.pricing_flag = 1 OR T1.pricing_flag IS NULL)
+ AND T2.id IS NULL -- 没有关联的费用定价
+ORDER BY T1.id;
+
+
diff --git a/openhis-server-new/sql/quick_check_pricing_flag_issue.sql b/openhis-server-new/sql/quick_check_pricing_flag_issue.sql
new file mode 100644
index 00000000..e6a1240f
--- /dev/null
+++ b/openhis-server-new/sql/quick_check_pricing_flag_issue.sql
@@ -0,0 +1,86 @@
+-- ============================================
+-- 快速检查 pricing_flag = '0' 的数据问题
+-- 注意:pricing_flag 是 char(1) 类型,所以要用字符串 '0'
+-- ============================================
+
+-- 问题1:检查是否有费用定价但 pricing_flag = '0' 的项目(可能异常)
+SELECT
+ '异常:有费用定价但不允许划价' AS issue_type,
+ T1.id,
+ T1.bus_no,
+ T1.name AS activity_name,
+ T1.pricing_flag,
+ T2.charge_name,
+ T2.price
+FROM wor_activity_definition AS T1
+INNER JOIN adm_charge_item_definition AS T2
+ ON T2.instance_id = T1.id
+ AND T2.delete_flag = '0'
+ AND T2.status_enum = 1
+ AND T2.instance_table = 'wor_activity_definition'
+WHERE T1.delete_flag = '0'
+ AND T1.status_enum = 1
+ AND T1.pricing_flag = '0' -- 不允许划价,但有费用定价(矛盾)
+ORDER BY T1.id;
+
+-- 问题2:检查是否已被使用但 pricing_flag = '0' 的项目(可能异常)
+SELECT
+ '异常:已有收费记录但不允许划价' AS issue_type,
+ T1.id,
+ T1.bus_no,
+ T1.name AS activity_name,
+ T1.pricing_flag,
+ COUNT(DISTINCT T3.encounter_id) AS encounter_count,
+ COUNT(T3.id) AS charge_item_count
+FROM wor_activity_definition AS T1
+INNER JOIN adm_charge_item AS T3
+ ON T3.product_id = T1.id
+ AND T3.context_enum = 3 -- ACTIVITY
+ AND T3.delete_flag = '0'
+WHERE T1.delete_flag = '0'
+ AND T1.pricing_flag = '0'
+GROUP BY T1.id, T1.bus_no, T1.name, T1.pricing_flag
+ORDER BY charge_item_count DESC;
+
+-- 问题3:查看所有 pricing_flag = '0' 的项目,判断哪些可能应该改为 '1'
+SELECT
+ T1.id,
+ T1.bus_no,
+ T1.name AS activity_name,
+ T1.category_code,
+ T1.pricing_flag,
+ T1.status_enum,
+ CASE
+ WHEN T2.id IS NOT NULL THEN '有费用定价'
+ ELSE '无费用定价'
+ END AS has_charge_definition,
+ CASE
+ WHEN EXISTS (
+ SELECT 1 FROM adm_charge_item
+ WHERE product_id = T1.id
+ AND context_enum = 3
+ AND delete_flag = '0'
+ ) THEN '已被使用'
+ ELSE '未使用'
+ END AS usage_status,
+ CASE
+ WHEN T2.id IS NOT NULL OR EXISTS (
+ SELECT 1 FROM adm_charge_item
+ WHERE product_id = T1.id
+ AND context_enum = 3
+ AND delete_flag = '0'
+ ) THEN '建议改为 pricing_flag = ''1'''
+ ELSE '保持 pricing_flag = ''0''(可能正常)'
+ END AS suggestion
+FROM wor_activity_definition AS T1
+LEFT JOIN adm_charge_item_definition AS T2
+ ON T2.instance_id = T1.id
+ AND T2.delete_flag = '0'
+ AND T2.status_enum = 1
+ AND T2.instance_table = 'wor_activity_definition'
+WHERE T1.delete_flag = '0'
+ AND T1.status_enum = 1
+ AND T1.pricing_flag = '0'
+ORDER BY T1.id;
+
+
diff --git a/openhis-server-new/sql/update_pricing_flag_to_one.sql b/openhis-server-new/sql/update_pricing_flag_to_one.sql
new file mode 100644
index 00000000..2c99c5f7
--- /dev/null
+++ b/openhis-server-new/sql/update_pricing_flag_to_one.sql
@@ -0,0 +1,123 @@
+-- ============================================
+-- 将 wor_activity_definition 表中的一两条记录的 pricing_flag 改成 '1'
+-- 注意:pricing_flag 是 char(1) 类型,所以要用字符串 '1'
+-- ============================================
+
+-- 方式1:更新前两条 pricing_flag = '0' 的记录(推荐)
+UPDATE wor_activity_definition
+SET pricing_flag = '1',
+ update_time = CURRENT_TIMESTAMP
+WHERE id IN (
+ SELECT id
+ FROM wor_activity_definition
+ WHERE delete_flag = '0'
+ AND pricing_flag = '0'
+ AND status_enum = 1 -- 只更新激活状态的项目
+ ORDER BY id
+ LIMIT 2
+);
+
+-- 方式2:更新指定 ID 的记录(更精确,推荐使用)
+-- 请将下面的 ID 替换为实际要更新的记录 ID
+UPDATE wor_activity_definition
+SET pricing_flag = '1',
+ update_time = CURRENT_TIMESTAMP
+WHERE id IN (1906532604116348929, 1906544768434053121) -- 替换为实际的 ID
+ AND delete_flag = '0';
+
+-- 方式3:更新前两条记录(不管当前 pricing_flag 值是什么)
+UPDATE wor_activity_definition
+SET pricing_flag = '1',
+ update_time = CURRENT_TIMESTAMP
+WHERE id IN (
+ SELECT id
+ FROM wor_activity_definition
+ WHERE delete_flag = '0'
+ AND status_enum = 1
+ ORDER BY id
+ LIMIT 2
+);
+
+-- 方式4:更新有费用定价但 pricing_flag = '0' 的前两条记录(业务逻辑更合理)
+UPDATE wor_activity_definition
+SET pricing_flag = '1',
+ update_time = CURRENT_TIMESTAMP
+WHERE id IN (
+ SELECT wad.id
+ FROM wor_activity_definition wad
+ INNER JOIN adm_charge_item_definition acid
+ ON acid.instance_id = wad.id
+ AND acid.delete_flag = '0'
+ AND acid.status_enum = 1
+ AND acid.instance_table = 'wor_activity_definition'
+ WHERE wad.delete_flag = '0'
+ AND wad.status_enum = 1
+ AND wad.pricing_flag = '0'
+ ORDER BY wad.id
+ LIMIT 2
+);
+
+-- ============================================
+-- 执行前可以先查询要更新的记录(验证用)
+-- ============================================
+
+-- 查询前两条 pricing_flag = '0' 的记录
+SELECT
+ id,
+ bus_no,
+ name AS activity_name,
+ pricing_flag,
+ status_enum,
+ create_time,
+ update_time
+FROM wor_activity_definition
+WHERE delete_flag = '0'
+ AND pricing_flag = '0'
+ AND status_enum = 1
+ORDER BY id
+LIMIT 2;
+
+-- 查询有费用定价但 pricing_flag = '0' 的记录
+SELECT
+ wad.id,
+ wad.bus_no,
+ wad.name AS activity_name,
+ wad.pricing_flag,
+ acid.charge_name,
+ acid.price
+FROM wor_activity_definition wad
+INNER JOIN adm_charge_item_definition acid
+ ON acid.instance_id = wad.id
+ AND acid.delete_flag = '0'
+ AND acid.status_enum = 1
+ AND acid.instance_table = 'wor_activity_definition'
+WHERE wad.delete_flag = '0'
+ AND wad.status_enum = 1
+ AND wad.pricing_flag = '0'
+ORDER BY wad.id
+LIMIT 2;
+
+-- ============================================
+-- 执行后验证更新结果
+-- ============================================
+
+-- 验证更新是否成功
+SELECT
+ id,
+ bus_no,
+ name AS activity_name,
+ pricing_flag,
+ update_time
+FROM wor_activity_definition
+WHERE id IN (
+ -- 这里放刚才更新的 ID,或者用子查询
+ SELECT id
+ FROM wor_activity_definition
+ WHERE delete_flag = '0'
+ AND pricing_flag = '1'
+ AND status_enum = 1
+ ORDER BY update_time DESC
+ LIMIT 2
+);
+
+
diff --git a/openhis-server-new/sql/快速诊断诊疗项目问题.sql b/openhis-server-new/sql/快速诊断诊疗项目问题.sql
new file mode 100644
index 00000000..f461827e
--- /dev/null
+++ b/openhis-server-new/sql/快速诊断诊疗项目问题.sql
@@ -0,0 +1,86 @@
+-- 快速诊断诊疗项目检索问题
+-- 已知:wor_activity_definition 表中有4条数据
+-- 关键:ChargeItemContext.ACTIVITY.getValue() = 3(整数)
+
+-- 步骤1:检查这4条诊疗项目定义的delete_flag状态
+SELECT
+ id,
+ name,
+ delete_flag,
+ CASE WHEN delete_flag = '0' THEN '✅ 可用' ELSE '❌ 已删除' END as status
+FROM wor_activity_definition
+ORDER BY id;
+
+-- 步骤2:检查收费项目中是否有诊疗项目类型(context_enum = 3)的记录
+SELECT
+ COUNT(*) as total_count,
+ COUNT(CASE WHEN delete_flag = '0' THEN 1 END) as active_count
+FROM adm_charge_item
+WHERE (context_enum::text = '3' OR context_enum = 3);
+
+-- 步骤3:检查收费项目能否匹配到诊疗项目定义(最关键!)
+SELECT
+ aci.id as charge_item_id,
+ aci.encounter_id,
+ aci.product_id,
+ aci.status_enum,
+ wad.id as activity_def_id,
+ wad.name as activity_name,
+ CASE
+ WHEN wad.id IS NULL THEN '❌ 无法匹配:product_id=' || aci.product_id || ' 在诊疗项目定义表中不存在'
+ WHEN wad.delete_flag != '0' THEN '❌ 无法匹配:诊疗项目定义已删除'
+ WHEN aci.delete_flag != '0' THEN '❌ 无法匹配:收费项目已删除'
+ WHEN aci.status_enum NOT IN (1,2,3,4,5,6) THEN '❌ 无法匹配:状态不在查询范围内 status=' || aci.status_enum
+ ELSE '✅ 可以匹配'
+ END as match_result
+FROM adm_charge_item aci
+LEFT JOIN wor_activity_definition wad
+ ON aci.product_id = wad.id AND wad.delete_flag = '0'
+WHERE (aci.context_enum::text = '3' OR aci.context_enum = 3)
+ AND aci.delete_flag = '0'
+LIMIT 50;
+
+-- 步骤4:统计匹配情况
+SELECT
+ COUNT(*) as total_charge_items,
+ COUNT(CASE WHEN wad.id IS NOT NULL AND wad.delete_flag = '0' THEN 1 END) as matched_count,
+ COUNT(CASE WHEN wad.id IS NULL THEN 1 END) as unmatched_def_count,
+ COUNT(CASE WHEN wad.delete_flag != '0' THEN 1 END) as deleted_def_count,
+ COUNT(CASE WHEN wad.id IS NOT NULL AND wad.delete_flag = '0' AND aci.status_enum IN (1,2,3,4,5,6) THEN 1 END) as final_matched_count
+FROM adm_charge_item aci
+LEFT JOIN wor_activity_definition wad
+ ON aci.product_id = wad.id
+WHERE (aci.context_enum::text = '3' OR aci.context_enum = 3)
+ AND aci.delete_flag = '0';
+
+-- 步骤5:检查具体就诊的诊疗项目(如果有encounterId,取消注释并替换)
+-- SELECT
+-- T1.encounter_id,
+-- T1.id as charge_item_id,
+-- T1.product_id,
+-- T1.status_enum,
+-- T2.id as activity_def_id,
+-- T2.name as activity_name,
+-- CASE
+-- WHEN T2.id IS NULL THEN '❌ 无法匹配'
+-- WHEN T2.delete_flag != '0' THEN '❌ 定义已删除'
+-- WHEN T1.status_enum NOT IN (1,2,3,4,5,6) THEN '❌ 状态不符合'
+-- ELSE '✅ 正常'
+-- END as status
+-- FROM adm_charge_item AS T1
+-- LEFT JOIN wor_activity_definition AS T2
+-- ON T1.product_id = T2.id AND T2.delete_flag = '0'
+-- WHERE T1.encounter_id = :encounterId -- 替换为实际的encounterId
+-- AND (T1.context_enum::text = '3' OR T1.context_enum = 3)
+-- AND T1.delete_flag = '0';
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openhis-server-new/sql/诊断门诊划价检索不出诊疗项目问题.md b/openhis-server-new/sql/诊断门诊划价检索不出诊疗项目问题.md
new file mode 100644
index 00000000..d754dd7c
--- /dev/null
+++ b/openhis-server-new/sql/诊断门诊划价检索不出诊疗项目问题.md
@@ -0,0 +1,165 @@
+# 诊断:门诊划价检索不出诊疗项目问题
+
+## 问题描述
+在门诊划价页面,检索不出诊疗项目,显示"暂无数据"。
+
+## 问题分析
+
+### SQL查询逻辑
+根据 `OutpatientChargeAppMapper.xml` 中的 `selectEncounterPatientPrescription` 查询:
+
+1. **查询主表**:`adm_charge_item`(收费项目表)
+2. **关联诊疗项目定义表**:`wor_activity_definition`
+ - 关联条件:`T1.context_enum = #{activity}` AND `T1.product_id = T2.id` AND `T2.delete_flag = '0'`
+3. **返回字段**:`item_name` 来自 `wor_activity_definition.name`
+
+### 可能的原因
+
+#### 1. 数据库中没有诊疗项目定义数据
+- **检查**:`wor_activity_definition` 表中是否有数据
+- **SQL**:
+```sql
+SELECT COUNT(*) FROM wor_activity_definition WHERE delete_flag = '0';
+```
+
+#### 2. 收费项目中的product_id无法匹配到诊疗项目定义
+- **检查**:`adm_charge_item` 表中的 `product_id` 是否存在于 `wor_activity_definition` 表中
+- **SQL**:
+```sql
+SELECT
+ aci.id,
+ aci.encounter_id,
+ aci.product_id,
+ aci.context_enum,
+ wad.id as activity_def_id,
+ wad.name as activity_name
+FROM adm_charge_item aci
+LEFT JOIN wor_activity_definition wad ON aci.product_id = wad.id AND wad.delete_flag = '0'
+WHERE aci.context_enum = 'ACTIVITY'
+ AND aci.delete_flag = '0'
+ AND wad.id IS NULL; -- 无法匹配的记录
+```
+
+#### 3. 诊疗项目定义被标记为删除
+- **检查**:`wor_activity_definition` 表中的 `delete_flag` 是否为 '0'
+- **SQL**:
+```sql
+SELECT
+ id,
+ name,
+ delete_flag
+FROM wor_activity_definition
+WHERE delete_flag != '0';
+```
+
+#### 4. context_enum 值不匹配
+- **检查**:`adm_charge_item` 表中的 `context_enum` 值是否正确
+- **SQL**:
+```sql
+SELECT DISTINCT context_enum FROM adm_charge_item WHERE delete_flag = '0';
+```
+- **注意**:后端代码中传入的 `#{activity}` 参数值应该是 `ChargeItemContext.ACTIVITY.getValue()`
+
+## 诊断步骤
+
+### 步骤1:检查诊疗项目定义表是否有数据
+```sql
+SELECT
+ COUNT(*) as total_count,
+ COUNT(CASE WHEN delete_flag = '0' THEN 1 END) as active_count,
+ COUNT(CASE WHEN delete_flag != '0' THEN 1 END) as deleted_count
+FROM wor_activity_definition;
+```
+
+**预期结果**:`active_count` 应该 > 0
+
+### 步骤2:检查收费项目中的诊疗项目是否能匹配到定义
+```sql
+SELECT
+ COUNT(*) as total_charge_items,
+ COUNT(CASE WHEN wad.id IS NOT NULL THEN 1 END) as matched_count,
+ COUNT(CASE WHEN wad.id IS NULL THEN 1 END) as unmatched_count
+FROM adm_charge_item aci
+LEFT JOIN wor_activity_definition wad
+ ON aci.context_enum = 'ACTIVITY'
+ AND aci.product_id = wad.id
+ AND wad.delete_flag = '0'
+WHERE aci.context_enum = 'ACTIVITY'
+ AND aci.delete_flag = '0';
+```
+
+**预期结果**:`matched_count` 应该 > 0,`unmatched_count` 应该 = 0
+
+### 步骤3:检查具体就诊的诊疗项目
+```sql
+-- 替换 :encounterId 为实际的就诊ID
+SELECT
+ T1.encounter_id,
+ T1.id as charge_item_id,
+ T1.context_enum,
+ T1.product_id,
+ T1.status_enum,
+ T2.id as activity_def_id,
+ T2.name as activity_name,
+ T2.delete_flag as activity_delete_flag,
+ CASE
+ WHEN T2.id IS NULL THEN '诊疗项目定义不存在或已删除'
+ WHEN T2.delete_flag != '0' THEN '诊疗项目定义已删除'
+ ELSE '正常'
+ END as status
+FROM adm_charge_item AS T1
+LEFT JOIN wor_activity_definition AS T2
+ ON T1.context_enum = 'ACTIVITY'
+ AND T1.product_id = T2.id
+WHERE T1.encounter_id = :encounterId -- 替换为实际的encounterId
+ AND T1.context_enum = 'ACTIVITY'
+ AND T1.delete_flag = '0'
+ AND T1.status_enum IN (1, 2, 3, 4, 5, 6);
+```
+
+### 步骤4:检查后端传入的参数值
+检查 `OutpatientChargeAppServiceImpl.java` 中:
+```java
+ChargeItemContext.ACTIVITY.getValue()
+```
+确认这个值是什么(应该是 'ACTIVITY' 或对应的枚举值)
+
+## 解决方案
+
+### 如果是数据问题:
+1. **缺少诊疗项目定义数据**:
+ - 需要在 `wor_activity_definition` 表中添加诊疗项目数据
+ - 或者在系统管理-目录管理-诊疗项目中添加
+
+2. **product_id无法匹配**:
+ - 检查 `adm_charge_item` 表中的 `product_id` 是否正确
+ - 检查 `wor_activity_definition` 表中的 `id` 是否与 `product_id` 匹配
+
+3. **delete_flag不正确**:
+ - 将 `wor_activity_definition` 表中需要使用的记录的 `delete_flag` 设置为 '0'
+
+### 如果是代码问题:
+1. **context_enum值不匹配**:
+ - 检查后端代码中 `ChargeItemContext.ACTIVITY.getValue()` 返回的值
+ - 确保与数据库中的 `context_enum` 值一致
+
+2. **SQL查询条件错误**:
+ - 检查 SQL 中的关联条件是否正确
+ - 检查是否有其他过滤条件导致数据被过滤掉
+
+## 快速诊断SQL
+运行以下SQL可以快速诊断问题:
+```sql
+-- 见 diagnose_treatment_items_issue.sql 文件
+```
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openhis-ui-vue3/src/views/catalog/diagnosistreatment/index.vue b/openhis-ui-vue3/src/views/catalog/diagnosistreatment/index.vue
index 888ad59b..c6a384bd 100644
--- a/openhis-ui-vue3/src/views/catalog/diagnosistreatment/index.vue
+++ b/openhis-ui-vue3/src/views/catalog/diagnosistreatment/index.vue
@@ -183,6 +183,23 @@
prop="statusEnum_enumText"
:show-overflow-tooltip="true"
/>
+
+
+
+ {{ scope.row.pricingFlag_enumText || (scope.row.pricingFlag === 1 ? '允许' : scope.row.pricingFlag === 0 ? '不允许' : '未设置') }}
+
+
+
@@ -38,6 +39,10 @@ const props = defineProps({
type: Object,
required: true,
},
+ popoverVisible: {
+ type: Boolean,
+ default: false,
+ },
});
const emit = defineEmits(['selectAdviceBase']);
const total = ref(0);
@@ -61,30 +66,80 @@ const throttledGetList = throttle(
watch(
() => props.adviceQueryParams,
(newValue) => {
- queryParams.value.searchKey = newValue.searchKey;
- queryParams.value.adviceType = newValue.adviceType;
+ // 只有在弹窗打开时才响应 adviceQueryParams 的变化,避免选择项目后弹窗关闭时触发不必要的请求
+ if (!props.popoverVisible) {
+ return;
+ }
+ queryParams.value.searchKey = newValue?.searchKey;
+ queryParams.value.adviceType = newValue?.adviceType;
throttledGetList();
},
{ deep: true }
);
-getList();
+// 监听弹窗打开状态,当弹窗打开时主动加载数据
+watch(
+ () => props.popoverVisible,
+ (visible) => {
+ if (visible) {
+ // 弹窗打开时,确保 adviceQueryParams 同步到 queryParams
+ if (props.adviceQueryParams) {
+ queryParams.value.searchKey = props.adviceQueryParams.searchKey;
+ queryParams.value.adviceType = props.adviceQueryParams.adviceType;
+ }
+ // 主动触发数据加载
+ getList();
+ } else {
+ // 弹窗关闭时,清空列表数据,避免显示错误的数据
+ adviceBaseList.value = [];
+ total.value = 0;
+ }
+ }
+);
+
+// 移除组件初始化时的 getList() 调用,避免在没有 adviceType 时查询所有类型的数据
+// getList();
function getList() {
// 验证是否已选择患者
if (!props.patientInfo || Object.keys(props.patientInfo).length === 0) {
+ console.log('[adviceBaseList] getList() 跳过:未选择患者');
return; // 不执行API调用
}
+ // 只有在弹窗打开时才执行查询
+ if (!props.popoverVisible) {
+ console.log('[adviceBaseList] getList() 跳过:弹窗未打开');
+ return;
+ }
+
+ // 必须有 adviceType 才查询,避免查询所有类型的数据
+ if (!queryParams.value.adviceType) {
+ console.log('[adviceBaseList] getList() 跳过:adviceType 未设置,当前值:', queryParams.value.adviceType);
+ return;
+ }
+
queryParams.value.organizationId = props.patientInfo.orgId;
+ console.log('[adviceBaseList] getList() 请求参数:', JSON.stringify(queryParams.value));
+
getAdviceBaseInfo(queryParams.value).then((res) => {
- adviceBaseList.value = res.data.records;
- total.value = res.data.total;
+ console.log('[adviceBaseList] getList() 响应数据:', {
+ total: res.data?.total,
+ recordsCount: res.data?.records?.length || 0,
+ firstRecord: res.data?.records?.[0]?.adviceName || '无数据',
+ adviceType: queryParams.value.adviceType
+ });
+ adviceBaseList.value = res.data.records || [];
+ total.value = res.data.total || 0;
nextTick(() => {
currentIndex.value = 0;
if (adviceBaseList.value.length > 0) {
- adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
+ adviceBaseRef.value?.setCurrentRow(adviceBaseList.value[0]);
}
});
+ }).catch((err) => {
+ console.error('[adviceBaseList] getList() 请求失败:', err);
+ adviceBaseList.value = [];
+ total.value = 0;
});
}
@@ -136,8 +191,12 @@ const handleCurrentChange = (currentRow) => {
currentSelectRow.value = currentRow;
};
-function clickRow(row) {
- emit('selectAdviceBase', row);
+function clickRow(row, column, cell, event) {
+ // cell-click 事件会传递 row, column, cell, event 四个参数
+ // 确保传递的是完整的行数据
+ if (row) {
+ emit('selectAdviceBase', row);
+ }
}
defineExpose({
diff --git a/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue b/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue
index e7efd7e9..2c37b3c1 100644
--- a/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue
+++ b/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue
@@ -301,6 +301,7 @@ const nextId = ref(1);
const unitCodeList = ref([]);
const adviceTableRef = ref([]);
const organization = ref([]);
+const orgTreeLoaded = ref(false);
const rowRules = ref({
conditionDefinitionId: [{ required: true, message: '请选择诊断', trigger: 'change' }],
dose: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
@@ -449,6 +450,10 @@ function handleDiagnosisChange(item, row) {
function handleFocus(row, index) {
rowIndex.value = index;
+ // 打开当前行弹窗前,先关闭其它行,避免多个弹窗同时存在
+ prescriptionList.value.forEach((r, i) => {
+ if (i !== index) r.showPopover = false;
+ });
// 如果当前行已选择adviceType,同步到adviceQueryParams
if (row.adviceType !== undefined) {
adviceQueryParams.value.adviceType = row.adviceType;
@@ -457,7 +462,9 @@ function handleFocus(row, index) {
}
function handleBlur(row) {
- row.showPopover = false;
+ // 不能在 input blur 时立刻关闭弹窗:
+ // 点击弹窗里的表格会先触发 blur,导致弹窗瞬间关闭,从而“点了项目没反应”
+ // 弹窗关闭交给 selectAdviceBase()(选中后关闭)以及 handleFocus()(切行时关闭其他行)
}
function handleChange(value) {
@@ -465,10 +472,37 @@ function handleChange(value) {
}
/**
- * 选择药品回调
+ * 选择药品/诊疗项目回调
+ * 这里恢复为之前“能正常工作”的简单逻辑,只做最小必要的修正
*/
function selectAdviceBase(key, row) {
- getOrgList();
+ if (!row) {
+ console.error('[selectAdviceBase] row 为空');
+ return;
+ }
+
+ // rowIndex 理论上由 handleFocus 设置;防御一下越界
+ if (rowIndex.value < 0 || rowIndex.value >= prescriptionList.value.length) {
+ const foundIndex = prescriptionList.value.findIndex((item) => item.uniqueKey === key);
+ if (foundIndex === -1) {
+ console.error('[selectAdviceBase] 找不到对应行,key =', key);
+ return;
+ }
+ rowIndex.value = foundIndex;
+ }
+
+ // 关闭当前行弹窗
+ const currentRow = prescriptionList.value[rowIndex.value];
+ if (currentRow) {
+ currentRow.showPopover = false;
+ }
+
+ // 诊疗(adviceType=3) 才需要加载执行科室树,且只加载一次
+ if (row.adviceType === 3) {
+ ensureOrgTreeLoaded();
+ }
+
+ // 构建单位列表(保持原有逻辑)
unitCodeList.value = [];
unitCodeList.value.push({ value: row.unitCode, label: row.unitCode_dictText, type: 'unit' });
if (row.doseUnitCode != row.minUnitCode) {
@@ -488,10 +522,14 @@ function selectAdviceBase(key, row) {
type: 'minUnit',
});
}
+
+ // 将选中的基础项“覆盖”到当前处方行(这是之前正常工作的核心逻辑)
prescriptionList.value[rowIndex.value] = {
...prescriptionList.value[rowIndex.value],
...JSON.parse(JSON.stringify(row)),
};
+
+ // 后续字段处理保持原样
prescriptionList.value[rowIndex.value].orgId = undefined;
prescriptionList.value[rowIndex.value].dose = undefined;
prescriptionList.value[rowIndex.value].unitCodeList = unitCodeList.value;
@@ -500,12 +538,11 @@ function selectAdviceBase(key, row) {
prescriptionList.value[rowIndex.value].minUnitCode = JSON.parse(JSON.stringify(row.doseUnitCode));
prescriptionList.value[rowIndex.value].unitCode =
row.partAttributeEnum == 1 ? row.minUnitCode : row.unitCode;
- // prescriptionList.value[rowIndex.value].doseUnitCode_dictText = row.minUnitCode_dictText;
prescriptionList.value[rowIndex.value].definitionId = JSON.parse(
JSON.stringify(row)
).chargeItemDefinitionId;
- // 库存列表 + 价格列表拼成批次号的下拉框
+ // 库存列表 + 价格列表拼成批次号的下拉框(非诊疗)
if (row.adviceType != 3) {
if (row.inventoryList && row.inventoryList.length == 0) {
expandOrder.value = [];
@@ -532,9 +569,15 @@ function selectAdviceBase(key, row) {
prescriptionList.value[rowIndex.value].positionName = stock.locationName;
}
} else {
+ // 诊疗:设置执行科室和价格
prescriptionList.value[rowIndex.value].orgId = JSON.parse(JSON.stringify(row)).positionId;
- prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
+ if (row.priceList && row.priceList.length > 0) {
+ prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
+ } else {
+ prescriptionList.value[rowIndex.value].unitPrice = 0;
+ }
}
+
expandOrder.value = [key];
nextTick(() => {
if (row.adviceType == 1) {
@@ -549,11 +592,18 @@ function selectAdviceBase(key, row) {
});
}
-function getOrgList() {
- getOrgTree().then((res) => {
- organization.value = res.data.records;
- console.log(organization.value,"organization.value")
- });
+function ensureOrgTreeLoaded() {
+ if (orgTreeLoaded.value) return;
+ orgTreeLoaded.value = true;
+ getOrgTree()
+ .then((res) => {
+ // 组织机构树接口通常返回分页 records,这里做兼容兜底
+ organization.value = res?.data?.records ?? res?.data ?? [];
+ })
+ .catch(() => {
+ // 加载失败时允许重试
+ orgTreeLoaded.value = false;
+ });
}
function handleDelete() {
diff --git a/排查指南-字段查询问题.md b/排查指南-字段查询问题.md
index ddebfb9e..06bb3eeb 100644
--- a/排查指南-字段查询问题.md
+++ b/排查指南-字段查询问题.md
@@ -282,3 +282,13 @@ public Long saveEncounterByRegister(Encounter encounter) {
**记住**:查询条件使用的字段,必须在数据插入/更新时被设置!
+
+
+
+
+
+
+
+
+
+