This commit is contained in:
Your Name
2026-08-12 15:22:00 +08:00
parent 6d9fe1bbf8
commit 28cd110dae
2 changed files with 153 additions and 107 deletions
@@ -3963,9 +3963,9 @@ class PrescriptionOrderLogic
}
}
// 药方名称反查:处方库(开方医师 creator_id + 公开模板),按 formula_type + 药材集合匹配
// 复刻前端 resolveSlipAuxLibraryName 口径(主方/辅方均如此;处方记录 prescription_name 仅做兜底)
[$libByDoctor, $libPublic] = self::buildPrescriptionLibraryNameIndexForExport($rxById);
// 药方名称反查:处方库(开方医师 → 公开 → 全库同药材集合兜底),按 formula_type + 药材集合匹配
// 辅方模板额外全量加载,避免「系统代开 / 非模板所属医师」因 creator 范围过窄丢辅方名
[$libByDoctor, $libPublic, $libAny] = self::buildPrescriptionLibraryNameIndexForExport($rxById);
if ($needGuahaoChannel) {
$yejiChannelHighlightByDiag = [];
@@ -4174,11 +4174,12 @@ class PrescriptionOrderLogic
$item['export_medication_form'] = self::formatMedicationFormForExport(\is_array($rx) ? $rx : []);
// 药方名称:主方/辅方均反查处方库取名称(与处方笺一致),带标签;甘草/无匹配留空
// 药方名称:主方/辅方均反查处方库取名称(与处方笺一致),带标签;有辅方药材时即使未匹配到库名也保留「辅方」标记
[$mainRxName, $auxRxName] = self::resolvePrescriptionNamesForExport(
\is_array($rx) ? $rx : [],
$libByDoctor,
$libPublic
$libPublic,
$libAny
);
$rxNameParts = [];
if ($mainRxName !== '') {
@@ -4298,19 +4299,24 @@ class PrescriptionOrderLogic
}
/**
* 导出药方名称反查:批量加载相关开方医师处方库(creator_id 命中 + 公开模板),
* 建立 [creator_id][formula_type][herbKey] => name 与 公开 [formula_type][herbKey] => name 两级索引
* 导出药方名称反查:批量加载相关开方医师处方库(creator_id 命中 + 公开模板 + 全量辅方模板),
* 建立三级索引:医师私有 / 公开 / 任意已加载(跨医师同药材集合兜底)
*
* @param array<int, array> $rxById 处方 id => 处方行(需含 herbs / creator_id
*
* @return array{0: array<int, array<string, array<string, string>>>, 1: array<string, array<string, string>>}
* @return array{
* 0: array<int, array<string, array<string, string>>>,
* 1: array<string, array<string, string>>,
* 2: array<string, array<string, string>>
* }
*/
private static function buildPrescriptionLibraryNameIndexForExport(array $rxById): array
{
$libByDoctor = [];
$libPublic = [];
$libAny = [];
if ($rxById === []) {
return [$libByDoctor, $libPublic];
return [$libByDoctor, $libPublic, $libAny];
}
$doctorIds = [];
@@ -4323,12 +4329,15 @@ class PrescriptionOrderLogic
$doctorIdList = array_keys($doctorIds);
try {
// 开方医师私有 + 公开模板 + 全量辅方模板(辅方常被非模板所有者的「系统代开」处方复用)
$libRows = PrescriptionLibrary::whereNull('delete_time')
->where(function ($q) use ($doctorIdList) {
if ($doctorIdList !== []) {
$q->whereIn('creator_id', $doctorIdList)->whereOr('is_public', 1);
$q->whereIn('creator_id', $doctorIdList)
->whereOr('is_public', 1)
->whereOr('formula_type', '辅方');
} else {
$q->where('is_public', 1);
$q->where('is_public', 1)->whereOr('formula_type', '辅方');
}
})
->field(['prescription_name', 'formula_type', 'herbs', 'creator_id', 'is_public'])
@@ -4337,7 +4346,7 @@ class PrescriptionOrderLogic
} catch (\Throwable $e) {
Log::warning('buildPrescriptionLibraryNameIndexForExport failed: ' . $e->getMessage());
return [$libByDoctor, $libPublic];
return [$libByDoctor, $libPublic, $libAny];
}
foreach ($libRows as $lib) {
@@ -4359,6 +4368,9 @@ class PrescriptionOrderLogic
}
$ft = ((string) ($lib['formula_type'] ?? '')) === '辅方' ? '辅方' : '主方';
// 跨医师兜底:同药材集合优先保留先写入的名称(稳定、可预期)
$libAny[$ft][$key] ??= $name;
if ((int) ($lib['is_public'] ?? 0) === 1) {
$libPublic[$ft][$key] ??= $name;
}
@@ -4368,23 +4380,28 @@ class PrescriptionOrderLogic
}
}
return [$libByDoctor, $libPublic];
return [$libByDoctor, $libPublic, $libAny];
}
/**
* 反查单张处方的主方 / 辅方名称(与处方笺展示一致):
* - 主方:主方药材集合匹配开方医师/公开处方库(formula_type=主方);兜底取处方 prescription_name。
* - 主方:主方药材集合匹配 开方医师 → 公开 → 任意已加载;兜底取处方 prescription_name。
* - 辅方:仅在实际存在辅方药材时,优先 aux_usage.prescription_name / library_name
* 否则按辅方药材集合匹配formula_type=辅方)。
* 否则按辅方药材集合匹配;仍无匹配时回落为「辅方」(保证导出名含辅方标记)。
*
* @param array $rx 处方行(含 herbs / creator_id / prescription_name / aux_usage
* @param array<int, array<string, array<string, string>>> $libByDoctor
* @param array<string, array<string, string>> $libPublic
* @param array<string, array<string, string>> $libAny
*
* @return array{0: string, 1: string} [主方名称, 辅方名称]
*/
private static function resolvePrescriptionNamesForExport(array $rx, array $libByDoctor, array $libPublic): array
{
private static function resolvePrescriptionNamesForExport(
array $rx,
array $libByDoctor,
array $libPublic,
array $libAny = []
): array {
if ($rx === []) {
return ['', ''];
}
@@ -4393,7 +4410,7 @@ class PrescriptionOrderLogic
[$mainHerbs, $auxHerbs] = self::splitPrescriptionHerbsFromRx($rx);
$lookup = static function (string $ft, array $hs) use ($doctorId, $libByDoctor, $libPublic): string {
$lookup = static function (string $ft, array $hs) use ($doctorId, $libByDoctor, $libPublic, $libAny): string {
if ($hs === []) {
return '';
}
@@ -4404,8 +4421,11 @@ class PrescriptionOrderLogic
if ($doctorId > 0 && isset($libByDoctor[$doctorId][$ft][$key])) {
return $libByDoctor[$doctorId][$ft][$key];
}
if (isset($libPublic[$ft][$key])) {
return $libPublic[$ft][$key];
}
return (string) ($libPublic[$ft][$key] ?? '');
return (string) ($libAny[$ft][$key] ?? '');
};
// 主方
@@ -4432,6 +4452,10 @@ class PrescriptionOrderLogic
if ($auxName === '') {
$auxName = $lookup('辅方', $auxHerbs);
}
// 有辅方药材但未匹配到库名/持久化名时,仍输出标记,避免导出名静默丢掉辅方
if ($auxName === '') {
$auxName = '辅方';
}
return [$mainName, $auxName];
}
@@ -85,4 +85,26 @@ $assertSame(
'export must still resolve an auxiliary prescription name from the library when auxiliary herbs exist'
);
$assertSame(
['系统代开', '失眠(辅方)'],
$resolveNames->invoke(null, [
'prescription_name' => '系统代开',
'creator_id' => 99,
'herbs' => [$mainHerb, $auxHerb],
], [], [], [
'辅方' => ['龙骨:15' => '失眠(辅方)'],
]),
'export must resolve auxiliary name via cross-doctor libAny when creator has no private/public hit'
);
$assertSame(
['系统代开', '辅方'],
$resolveNames->invoke(null, [
'prescription_name' => '系统代开',
'creator_id' => 99,
'herbs' => [$mainHerb, $auxHerb],
], [], [], []),
'export must still mark 辅方 when auxiliary herbs exist but no library/persisted name matches'
);
fwrite(STDOUT, sprintf("Prescription order export name regression tests passed: %d\n", $passed));