6.5 KiB
6.5 KiB
药材名称拼音首字母功能说明
概述
系统使用 overtrue/pinyin 包自动生成中文药材名称的拼音首字母缩写,存储在 name_pinyin_abbr 字段中,用于快速检索。
核心实现
1. 依赖包
"overtrue/pinyin": "^6.0"
已在 server/composer.json 中配置。
2. 服务类:MedicineNameAbbrService
文件位置: server/app/common/service/doctor/MedicineNameAbbrService.php
<?php
namespace app\common\service\doctor;
use Overtrue\Pinyin\Pinyin;
class MedicineNameAbbrService
{
public static function build(string $name): string
{
$name = trim($name);
if ($name === '') {
return '';
}
if (!class_exists(Pinyin::class)) {
return '';
}
$abbr = (string) Pinyin::abbr($name)->join('');
return strtolower($abbr);
}
}
功能说明:
- 输入:中文药材名称(如 "当归")
- 输出:拼音首字母小写连写(如 "dg")
- 自动处理:去除空格、转小写
- 容错:如果 Pinyin 类不存在,返回空字符串
3. 使用示例
示例 1:当归
MedicineNameAbbrService::build('当归');
// 输出: "dg"
示例 2:黄芪
MedicineNameAbbrService::build('黄芪');
// 输出: "hq"
示例 3:党参
MedicineNameAbbrService::build('党参');
// 输出: "ds"
示例 4:白术
MedicineNameAbbrService::build('白术');
// 输出: "bs"
自动生成时机
1. 创建药材时
文件: server/app/adminapi/logic/doctor/MedicineLogic.php
Medicine::create([
'name' => $params['name'],
'name_pinyin_abbr' => MedicineNameAbbrService::build($params['name']),
// ... 其他字段
]);
2. 编辑药材时
Medicine::update([
'id' => $params['id'],
'name' => $params['name'],
'name_pinyin_abbr' => MedicineNameAbbrService::build($params['name']),
// ... 其他字段
]);
批量回填命令
命令:sync_medicine_pinyin_abbr
文件: server/app/common/command/SyncMedicinePinyinAbbr.php
用于批量生成或更新已有药材的拼音首字母。
使用方法
1. 仅更新空字段(默认)
cd server
php think sync_medicine_pinyin_abbr
只处理 name_pinyin_abbr 为空的记录。
2. 重算全部记录
php think sync_medicine_pinyin_abbr --all
重新计算所有药材的拼音首字母(覆盖现有值)。
3. 预览模式(不写入数据库)
php think sync_medicine_pinyin_abbr --dry
只统计将更新多少条,不实际写入。
4. 组合使用
php think sync_medicine_pinyin_abbr --all --dry
预览全部重算的结果。
命令输出示例
模式: 仅空 abbr,待处理 150 条
完成: 已更新 145 条,跳过 5 条。
检索功能
列表搜索
文件: server/app/adminapi/lists/doctor/MedicineLists.php
$query->where(function ($q) use ($kw, $keyword) {
$q->where('name_pinyin_abbr', 'like', '%' . $kw . '%')
->whereOr('name', 'like', '%' . $keyword . '%');
});
功能说明:
- 用户输入 "dg" 可以搜索到 "当归"
- 用户输入 "当归" 也可以搜索到
- 支持模糊匹配(LIKE 查询)
搜索示例
| 用户输入 | 匹配药材 |
|---|---|
| dg | 当归 |
| hq | 黄芪 |
| ds | 党参、丹参 |
| bs | 白术、白芍 |
| 当归 | 当归 |
数据库字段
表:zyt_doctor_medicine
`name_pinyin_abbr` varchar(64) DEFAULT NULL COMMENT '名称拼音首字母缩写(小写连写)'
索引建议
如果药材数量很大(>10000条),建议添加索引:
ALTER TABLE `zyt_doctor_medicine`
ADD INDEX `idx_name_pinyin_abbr` (`name_pinyin_abbr`);
常见问题
Q1: 如何安装 overtrue/pinyin?
cd server
composer require overtrue/pinyin
(已在项目中安装,无需手动执行)
Q2: 多音字如何处理?
overtrue/pinyin 会自动选择最常用的读音。例如:
- "重" → "z" (重量) 或 "c" (重复)
- 默认使用最常见的读音
Q3: 如何处理英文或数字?
- 英文字母:保留原样并转小写
- 数字:保留原样
- 示例:
"维生素B12"→"wssbB12"→"wssbb12"
Q4: 为什么有些药材搜索不到?
可能原因:
name_pinyin_abbr字段为空 → 运行批量回填命令- 药材名称包含特殊字符 → 检查数据质量
- 索引未生效 → 检查数据库索引
Q5: 如何在其他模块使用?
use app\common\service\doctor\MedicineNameAbbrService;
// 生成拼音首字母
$abbr = MedicineNameAbbrService::build('当归');
echo $abbr; // 输出: dg
性能优化建议
1. 批量处理
命令使用 chunk(200) 分批处理,避免内存溢出:
$makeQuery()->chunk(200, function ($rows) {
// 每次处理 200 条
});
2. 异步生成
对于大量数据,建议:
- 使用队列异步处理
- 在低峰期运行批量命令
- 使用
--dry先预览再执行
3. 缓存策略
如果药材数据不常变动,可以:
- 缓存常用药材的拼音首字母
- 使用 Redis 存储热门搜索词
相关文件
| 文件 | 说明 |
|---|---|
server/app/common/service/doctor/MedicineNameAbbrService.php |
拼音首字母生成服务 |
server/app/common/command/SyncMedicinePinyinAbbr.php |
批量回填命令 |
server/app/adminapi/logic/doctor/MedicineLogic.php |
药材增删改逻辑 |
server/app/adminapi/lists/doctor/MedicineLists.php |
药材列表搜索 |
server/app/common/model/doctor/Medicine.php |
药材模型 |
扩展应用
此功能可以扩展到其他需要中文检索的模块:
1. 患者姓名检索
use app\common\service\doctor\MedicineNameAbbrService;
$patientName = '张三';
$abbr = MedicineNameAbbrService::build($patientName); // "zs"
2. 医生姓名检索
$doctorName = '李医生';
$abbr = MedicineNameAbbrService::build($doctorName); // "lys"
3. 诊断名称检索
$diagnosis = '感冒';
$abbr = MedicineNameAbbrService::build($diagnosis); // "gm"
总结
- 核心类:
MedicineNameAbbrService::build() - 依赖包:
overtrue/pinyin - 存储字段:
name_pinyin_abbr - 批量命令:
php think sync_medicine_pinyin_abbr - 应用场景: 药材快速检索、模糊搜索
这个功能大大提升了中文药材名称的搜索体验,用户可以通过拼音首字母快速找到目标药材。