651 [住院医生站-手术申请] 无法检索出已启用的手术项目(如:“血管闭合切割刀”)
This commit is contained in:
@@ -2697,21 +2697,6 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
log.info("getSurgeryPage 开始: orgId={}, page={}/{}, searchKey={}", organizationId, pageNo, pageSize, searchKey);
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
// 无搜索时尝试从 Redis 缓存读取(手术项目变更频率低,适合缓存)
|
||||
String safeOrgId = organizationId != null ? organizationId.toString() : "";
|
||||
String cacheKey = "surgery:page:" + safeOrgId + ":" + pageNo + ":" + pageSize;
|
||||
boolean useCache = (searchKey == null || searchKey.trim().isEmpty());
|
||||
|
||||
if (useCache) {
|
||||
Object cachedObj = redisCache.getCacheObject(cacheKey);
|
||||
if (cachedObj instanceof com.baomidou.mybatisplus.extension.plugins.pagination.Page) {
|
||||
log.info("从 Redis 缓存获取手术项目, key: {}, records: {}", cacheKey,
|
||||
((IPage<?>) cachedObj).getRecords().size());
|
||||
return (IPage<SurgeryItemDto>) cachedObj;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 MyBatis Plus 分页查询
|
||||
IPage<SurgeryItemDto> result = doctorStationAdviceAppMapper.getSurgeryPage(
|
||||
new Page<>(pageNo, pageSize),
|
||||
PublicationStatus.ACTIVE.getValue(),
|
||||
@@ -2720,12 +2705,6 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
|
||||
log.info("getSurgeryPage 完成: {}ms, total={}, records={}", System.currentTimeMillis() - start, result.getTotal(), result.getRecords().size());
|
||||
|
||||
// 无搜索时将结果写入缓存
|
||||
if (useCache && result instanceof com.baomidou.mybatisplus.extension.plugins.pagination.Page) {
|
||||
redisCache.setCacheObject(cacheKey, result, (int) CACHE_EXPIRE_HOURS, java.util.concurrent.TimeUnit.HOURS);
|
||||
log.info("缓存手术项目, key: {}, 过期时间: {} 小时", cacheKey, CACHE_EXPIRE_HOURS);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,12 @@ public class SurgeryItemDto {
|
||||
@JsonProperty("unitCode_dictText")
|
||||
private String unitCodeDictText;
|
||||
|
||||
/** 拼音码(前端穿梭框本地搜索用) */
|
||||
private String pyStr;
|
||||
|
||||
/** 业务编号(前端穿梭框本地搜索用) */
|
||||
private String busNo;
|
||||
|
||||
/** 所需标本编码(来自诊疗目录配置,对应字典 specimen_code 的 dictValue) */
|
||||
private String specimenCode;
|
||||
}
|
||||
|
||||
@@ -903,7 +903,9 @@
|
||||
t2.ID AS charge_item_definition_id,
|
||||
t2.price AS price,
|
||||
t1.permitted_unit_code AS unit_code,
|
||||
COALESCE(sdd.dict_label, t1.permitted_unit_code) AS unit_code_dict_text
|
||||
COALESCE(sdd.dict_label, t1.permitted_unit_code) AS unit_code_dict_text,
|
||||
t1.py_str AS py_str,
|
||||
t1.bus_no AS bus_no
|
||||
FROM wor_activity_definition t1
|
||||
LEFT JOIN adm_charge_item_definition t2
|
||||
ON t2.instance_id = t1.ID
|
||||
@@ -915,6 +917,7 @@
|
||||
AND sdd.dict_type = 'unit_code'
|
||||
AND sdd.status = '0'
|
||||
WHERE t1.delete_flag = '0'
|
||||
AND t1.status_enum = #{statusEnum}
|
||||
AND (t1.category_code = '手术' OR t1.category_code = '24')
|
||||
<if test="searchKey != null and searchKey != ''">
|
||||
AND (t1.name ILIKE '%' || #{searchKey} || '%' OR t1.py_str ILIKE '%' || #{searchKey} || '%')
|
||||
@@ -949,6 +952,7 @@
|
||||
AND sdd.dict_type = 'unit_code'
|
||||
AND sdd.status = '0'
|
||||
WHERE t1.delete_flag = '0'
|
||||
AND t1.status_enum = #{statusEnum}
|
||||
AND t1.category_code = #{categoryCode}
|
||||
<if test="searchKey != null and searchKey != ''">
|
||||
AND (t1.name ILIKE '%' || #{searchKey} || '%' OR t1.py_str ILIKE '%' || #{searchKey} || '%')
|
||||
|
||||
@@ -5,7 +5,20 @@
|
||||
-->
|
||||
<template>
|
||||
<div class="surgery-container">
|
||||
<div class="search-wrapper">
|
||||
<el-input
|
||||
v-model="searchQuery"
|
||||
placeholder="项目代码/名称/拼音码"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
style="width: 480px;"
|
||||
@input="handleSearch"
|
||||
@clear="handleClear"
|
||||
/>
|
||||
<span class="loaded-count">已加载 {{ applicationList.length }} 项</span>
|
||||
</div>
|
||||
<div
|
||||
v-loading="loading"
|
||||
class="transfer-wrapper"
|
||||
style="min-height: 300px;"
|
||||
>
|
||||
@@ -14,10 +27,6 @@
|
||||
v-model="transferValue"
|
||||
:data="applicationList"
|
||||
:titles="['待选择', '已选择']"
|
||||
:format="leftPanelFormat"
|
||||
filterable
|
||||
filter-placeholder="项目代码/名称"
|
||||
:filter-method="filterMethod"
|
||||
/>
|
||||
</div>
|
||||
<div class="bloodTransfusion-form">
|
||||
@@ -356,12 +365,6 @@ let surgeryRecordsCache = null; // 原始 API 记录
|
||||
let surgeryMappedCache = null; // 映射后的 el-transfer 数据
|
||||
let doctorCache = null; // 医生列表(含默认主刀医生 ID)
|
||||
const transferRef = ref(null);
|
||||
const dbTotal = ref(0); // 数据库中的手术项目总数
|
||||
const checkedCount = computed(() => transferValue.value.length);
|
||||
const leftPanelFormat = computed(() => ({
|
||||
noChecked: ` 0/${dbTotal.value}`,
|
||||
hasChecked: ` ${checkedCount.value}/${dbTotal.value}`,
|
||||
}));
|
||||
// 递归查找树形科室节点
|
||||
const findTreeItem = (list, id) => {
|
||||
if (!list || list.length === 0 || id == null || id === '') return null;
|
||||
@@ -393,6 +396,23 @@ const loading = ref(false);
|
||||
const applicationList = ref([]);
|
||||
const applicationListAll = ref([]);
|
||||
const allLoading = ref(false);
|
||||
// 搜索关键字(远程搜索用)
|
||||
const searchQuery = ref('');
|
||||
let searchTimer = null;
|
||||
|
||||
/** 远程搜索:输入关键字后 300ms 防抖,调后端 API 搜索 */
|
||||
const handleSearch = () => {
|
||||
if (searchTimer) clearTimeout(searchTimer);
|
||||
searchTimer = setTimeout(() => {
|
||||
getList(searchQuery.value || '');
|
||||
}, 300);
|
||||
};
|
||||
|
||||
/** 清除搜索:恢复完整缓存列表 */
|
||||
const handleClear = () => {
|
||||
searchQuery.value = '';
|
||||
getList();
|
||||
};
|
||||
// 递归查找默认科室
|
||||
const findTargetDepartment = (selectProjectIds) => {
|
||||
if (!selectProjectIds || selectProjectIds.length === 0) return '';
|
||||
@@ -416,13 +436,12 @@ const getList = async (key) => {
|
||||
if (!key && surgeryRecordsCache && surgeryMappedCache) {
|
||||
applicationList.value = surgeryMappedCache;
|
||||
applicationListAll.value = surgeryRecordsCache;
|
||||
dbTotal.value = surgeryRecordsCache.length;
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
return getSurgeryPage({
|
||||
pageSize: 1000,
|
||||
keyword: key || undefined,
|
||||
pageSize: key ? 500 : 100,
|
||||
searchKey: key || undefined,
|
||||
})
|
||||
.then((res) => {
|
||||
const records = res.data.records;
|
||||
@@ -440,25 +459,15 @@ const getList = async (key) => {
|
||||
.catch((e) => {
|
||||
console.error('手术项目加载失败:', e);
|
||||
applicationList.value = [];
|
||||
dbTotal.value = 0;
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* el-transfer 内置过滤方法:支持任意字符即时过滤
|
||||
* 按项目名称/代码进行前端模糊匹配
|
||||
*/
|
||||
const filterMethod = (query, item) => {
|
||||
const q = query.toLowerCase();
|
||||
const label = (item.label || '').toLowerCase();
|
||||
const key = String(item.key || '');
|
||||
return label.includes(q) || key.includes(q);
|
||||
};
|
||||
|
||||
const mapToTransferItem = (item) => ({
|
||||
key: String(item.adviceDefinitionId),
|
||||
label: `${item.adviceName} - ${item.unitCode_dictText || item.unitCode || ''}`,
|
||||
pyStr: item.pyStr || '',
|
||||
busNo: item.busNo || '',
|
||||
disabled: false,
|
||||
});
|
||||
|
||||
@@ -727,6 +736,19 @@ defineExpose({ state, submit, fillForm, getLocationInfo, getDiagnosisList, getLi
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.search-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.loaded-count {
|
||||
font-size: 13px;
|
||||
color: #64748B;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-wrapper {
|
||||
position: relative;
|
||||
min-height: 300px;
|
||||
|
||||
Reference in New Issue
Block a user