276 lines
6.5 KiB
Markdown
276 lines
6.5 KiB
Markdown
# 药材名称拼音首字母功能说明
|
||
|
||
## 概述
|
||
系统使用 `overtrue/pinyin` 包自动生成中文药材名称的拼音首字母缩写,存储在 `name_pinyin_abbr` 字段中,用于快速检索。
|
||
|
||
## 核心实现
|
||
|
||
### 1. 依赖包
|
||
```json
|
||
"overtrue/pinyin": "^6.0"
|
||
```
|
||
已在 `server/composer.json` 中配置。
|
||
|
||
### 2. 服务类:`MedicineNameAbbrService`
|
||
**文件位置:** `server/app/common/service/doctor/MedicineNameAbbrService.php`
|
||
|
||
```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:当归
|
||
```php
|
||
MedicineNameAbbrService::build('当归');
|
||
// 输出: "dg"
|
||
```
|
||
|
||
#### 示例 2:黄芪
|
||
```php
|
||
MedicineNameAbbrService::build('黄芪');
|
||
// 输出: "hq"
|
||
```
|
||
|
||
#### 示例 3:党参
|
||
```php
|
||
MedicineNameAbbrService::build('党参');
|
||
// 输出: "ds"
|
||
```
|
||
|
||
#### 示例 4:白术
|
||
```php
|
||
MedicineNameAbbrService::build('白术');
|
||
// 输出: "bs"
|
||
```
|
||
|
||
## 自动生成时机
|
||
|
||
### 1. 创建药材时
|
||
**文件:** `server/app/adminapi/logic/doctor/MedicineLogic.php`
|
||
|
||
```php
|
||
Medicine::create([
|
||
'name' => $params['name'],
|
||
'name_pinyin_abbr' => MedicineNameAbbrService::build($params['name']),
|
||
// ... 其他字段
|
||
]);
|
||
```
|
||
|
||
### 2. 编辑药材时
|
||
```php
|
||
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. 仅更新空字段(默认)
|
||
```bash
|
||
cd server
|
||
php think sync_medicine_pinyin_abbr
|
||
```
|
||
只处理 `name_pinyin_abbr` 为空的记录。
|
||
|
||
#### 2. 重算全部记录
|
||
```bash
|
||
php think sync_medicine_pinyin_abbr --all
|
||
```
|
||
重新计算所有药材的拼音首字母(覆盖现有值)。
|
||
|
||
#### 3. 预览模式(不写入数据库)
|
||
```bash
|
||
php think sync_medicine_pinyin_abbr --dry
|
||
```
|
||
只统计将更新多少条,不实际写入。
|
||
|
||
#### 4. 组合使用
|
||
```bash
|
||
php think sync_medicine_pinyin_abbr --all --dry
|
||
```
|
||
预览全部重算的结果。
|
||
|
||
### 命令输出示例
|
||
```
|
||
模式: 仅空 abbr,待处理 150 条
|
||
完成: 已更新 145 条,跳过 5 条。
|
||
```
|
||
|
||
## 检索功能
|
||
|
||
### 列表搜索
|
||
**文件:** `server/app/adminapi/lists/doctor/MedicineLists.php`
|
||
|
||
```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`
|
||
```sql
|
||
`name_pinyin_abbr` varchar(64) DEFAULT NULL COMMENT '名称拼音首字母缩写(小写连写)'
|
||
```
|
||
|
||
### 索引建议
|
||
如果药材数量很大(>10000条),建议添加索引:
|
||
```sql
|
||
ALTER TABLE `zyt_doctor_medicine`
|
||
ADD INDEX `idx_name_pinyin_abbr` (`name_pinyin_abbr`);
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 如何安装 overtrue/pinyin?
|
||
```bash
|
||
cd server
|
||
composer require overtrue/pinyin
|
||
```
|
||
(已在项目中安装,无需手动执行)
|
||
|
||
### Q2: 多音字如何处理?
|
||
`overtrue/pinyin` 会自动选择最常用的读音。例如:
|
||
- "重" → "z" (重量) 或 "c" (重复)
|
||
- 默认使用最常见的读音
|
||
|
||
### Q3: 如何处理英文或数字?
|
||
- 英文字母:保留原样并转小写
|
||
- 数字:保留原样
|
||
- 示例:`"维生素B12"` → `"wssbB12"` → `"wssbb12"`
|
||
|
||
### Q4: 为什么有些药材搜索不到?
|
||
可能原因:
|
||
1. `name_pinyin_abbr` 字段为空 → 运行批量回填命令
|
||
2. 药材名称包含特殊字符 → 检查数据质量
|
||
3. 索引未生效 → 检查数据库索引
|
||
|
||
### Q5: 如何在其他模块使用?
|
||
```php
|
||
use app\common\service\doctor\MedicineNameAbbrService;
|
||
|
||
// 生成拼音首字母
|
||
$abbr = MedicineNameAbbrService::build('当归');
|
||
echo $abbr; // 输出: dg
|
||
```
|
||
|
||
## 性能优化建议
|
||
|
||
### 1. 批量处理
|
||
命令使用 `chunk(200)` 分批处理,避免内存溢出:
|
||
```php
|
||
$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. 患者姓名检索
|
||
```php
|
||
use app\common\service\doctor\MedicineNameAbbrService;
|
||
|
||
$patientName = '张三';
|
||
$abbr = MedicineNameAbbrService::build($patientName); // "zs"
|
||
```
|
||
|
||
### 2. 医生姓名检索
|
||
```php
|
||
$doctorName = '李医生';
|
||
$abbr = MedicineNameAbbrService::build($doctorName); // "lys"
|
||
```
|
||
|
||
### 3. 诊断名称检索
|
||
```php
|
||
$diagnosis = '感冒';
|
||
$abbr = MedicineNameAbbrService::build($diagnosis); // "gm"
|
||
```
|
||
|
||
## 总结
|
||
|
||
- **核心类:** `MedicineNameAbbrService::build()`
|
||
- **依赖包:** `overtrue/pinyin`
|
||
- **存储字段:** `name_pinyin_abbr`
|
||
- **批量命令:** `php think sync_medicine_pinyin_abbr`
|
||
- **应用场景:** 药材快速检索、模糊搜索
|
||
|
||
这个功能大大提升了中文药材名称的搜索体验,用户可以通过拼音首字母快速找到目标药材。
|