367 lines
8.5 KiB
Markdown
367 lines
8.5 KiB
Markdown
# 处方用量数据库实现完整指南
|
||
|
||
## 概述
|
||
为处方系统添加用量、单位和代煎字段的完整数据库实现。
|
||
|
||
## 1. 数据库迁移
|
||
|
||
### 执行SQL文件
|
||
**文件**: `add_prescription_dosage_fields.sql`
|
||
|
||
```sql
|
||
-- 添加处方用量相关字段
|
||
ALTER TABLE `zyt_tcm_prescription`
|
||
ADD COLUMN `dosage_amount` decimal(10,2) DEFAULT NULL COMMENT '用量数值' AFTER `prescription_type`,
|
||
ADD COLUMN `dosage_unit` varchar(10) NOT NULL DEFAULT '' COMMENT '用量单位(g/ml)' AFTER `dosage_amount`,
|
||
ADD COLUMN `need_decoction` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否代煎(0否1是,仅饮片)' AFTER `dosage_unit`;
|
||
```
|
||
|
||
### 执行方式
|
||
```bash
|
||
mysql -u用户名 -p数据库名 < add_prescription_dosage_fields.sql
|
||
```
|
||
|
||
### 字段说明
|
||
|
||
| 字段名 | 类型 | 默认值 | 说明 |
|
||
|--------|------|--------|------|
|
||
| `dosage_amount` | decimal(10,2) | NULL | 用量数值,支持小数 |
|
||
| `dosage_unit` | varchar(10) | '' | 用量单位 (g/ml) |
|
||
| `need_decoction` | tinyint(1) | 0 | 是否代煎 (0=否, 1=是) |
|
||
|
||
## 2. 后端实现
|
||
|
||
### 2.1 模型层 (Model)
|
||
**文件**: `server/app/common/model/tcm/Prescription.php`
|
||
|
||
```php
|
||
class Prescription extends BaseModel
|
||
{
|
||
// ... 其他配置
|
||
|
||
// 字段类型转换
|
||
protected $type = [
|
||
'dosage_amount' => 'float',
|
||
'need_decoction' => 'integer',
|
||
];
|
||
}
|
||
```
|
||
|
||
**作用**: 自动将数据库字段转换为正确的PHP类型。
|
||
|
||
### 2.2 业务逻辑层 (Logic)
|
||
**文件**: `server/app/adminapi/logic/tcm/PrescriptionLogic.php`
|
||
|
||
#### add() 方法 - 添加处方
|
||
```php
|
||
$data = [
|
||
// ... 其他字段
|
||
'prescription_type' => $params['prescription_type'] ?? '浓缩水丸',
|
||
'dosage_amount' => isset($params['dosage_amount']) ? (float)$params['dosage_amount'] : null,
|
||
'dosage_unit' => $params['dosage_unit'] ?? '',
|
||
'need_decoction' => (int)($params['need_decoction'] ?? 0),
|
||
// ... 其他字段
|
||
];
|
||
```
|
||
|
||
#### edit() 方法 - 编辑处方
|
||
```php
|
||
$data = [
|
||
// ... 其他字段
|
||
'prescription_type' => $params['prescription_type'] ?? $prescription->prescription_type,
|
||
'dosage_amount' => isset($params['dosage_amount']) ? (float)$params['dosage_amount'] : $prescription->dosage_amount,
|
||
'dosage_unit' => $params['dosage_unit'] ?? $prescription->dosage_unit,
|
||
'need_decoction' => isset($params['need_decoction']) ? (int)$params['need_decoction'] : (int)($prescription->need_decoction ?? 0),
|
||
// ... 其他字段
|
||
];
|
||
```
|
||
|
||
## 3. 前端实现
|
||
|
||
### 3.1 TypeScript 接口
|
||
**文件**: `admin/src/components/tcm-prescription/index.vue`
|
||
|
||
```typescript
|
||
interface PrescriptionForm {
|
||
// ... 其他字段
|
||
prescription_type: string
|
||
dosage_amount: number | undefined
|
||
dosage_unit: string
|
||
need_decoction: boolean
|
||
// ... 其他字段
|
||
}
|
||
```
|
||
|
||
### 3.2 响应式数据
|
||
```typescript
|
||
const formData = reactive<PrescriptionForm>({
|
||
// ... 其他字段
|
||
prescription_type: '浓缩水丸',
|
||
dosage_amount: 1,
|
||
dosage_unit: 'g',
|
||
need_decoction: false,
|
||
// ... 其他字段
|
||
})
|
||
```
|
||
|
||
### 3.3 自动切换逻辑
|
||
```typescript
|
||
watch(() => formData.prescription_type, (newType) => {
|
||
if (newType === '浓缩水丸') {
|
||
formData.dosage_unit = 'g'
|
||
formData.dosage_amount = 1
|
||
formData.need_decoction = false
|
||
} else if (newType === '饮片') {
|
||
formData.dosage_unit = 'ml'
|
||
formData.dosage_amount = 50
|
||
} else {
|
||
formData.dosage_unit = 'g'
|
||
formData.dosage_amount = undefined
|
||
formData.need_decoction = false
|
||
}
|
||
})
|
||
```
|
||
|
||
## 4. 数据流转
|
||
|
||
### 4.1 保存流程
|
||
```
|
||
前端表单
|
||
↓
|
||
{
|
||
prescription_type: "浓缩水丸",
|
||
dosage_amount: 5,
|
||
dosage_unit: "g",
|
||
need_decoction: false
|
||
}
|
||
↓
|
||
后端 PrescriptionLogic::add()
|
||
↓
|
||
数据库 zyt_tcm_prescription
|
||
↓
|
||
dosage_amount: 5.00
|
||
dosage_unit: "g"
|
||
need_decoction: 0
|
||
```
|
||
|
||
### 4.2 读取流程
|
||
```
|
||
数据库查询
|
||
↓
|
||
Prescription Model (类型转换)
|
||
↓
|
||
{
|
||
dosage_amount: 5.0, // float
|
||
dosage_unit: "g", // string
|
||
need_decoction: 0 // int
|
||
}
|
||
↓
|
||
前端接收
|
||
↓
|
||
{
|
||
dosage_amount: 5,
|
||
dosage_unit: "g",
|
||
need_decoction: false
|
||
}
|
||
```
|
||
|
||
## 5. 数据示例
|
||
|
||
### 5.1 浓缩水丸处方
|
||
```json
|
||
{
|
||
"prescription_type": "浓缩水丸",
|
||
"dosage_amount": 5.00,
|
||
"dosage_unit": "g",
|
||
"need_decoction": 0
|
||
}
|
||
```
|
||
|
||
### 5.2 饮片处方(代煎)
|
||
```json
|
||
{
|
||
"prescription_type": "饮片",
|
||
"dosage_amount": 150.00,
|
||
"dosage_unit": "ml",
|
||
"need_decoction": 1
|
||
}
|
||
```
|
||
|
||
### 5.3 颗粒处方
|
||
```json
|
||
{
|
||
"prescription_type": "颗粒",
|
||
"dosage_amount": 15.50,
|
||
"dosage_unit": "g",
|
||
"need_decoction": 0
|
||
}
|
||
```
|
||
|
||
## 6. 部署步骤
|
||
|
||
### 步骤 1: 备份数据库
|
||
```bash
|
||
mysqldump -u用户名 -p数据库名 > backup_$(date +%Y%m%d_%H%M%S).sql
|
||
```
|
||
|
||
### 步骤 2: 执行数据库迁移
|
||
```bash
|
||
mysql -u用户名 -p数据库名 < add_prescription_dosage_fields.sql
|
||
```
|
||
|
||
### 步骤 3: 验证字段添加
|
||
```sql
|
||
SHOW COLUMNS FROM `zyt_tcm_prescription` LIKE 'dosage%';
|
||
SHOW COLUMNS FROM `zyt_tcm_prescription` LIKE 'need_decoction';
|
||
```
|
||
|
||
### 步骤 4: 部署后端代码
|
||
```bash
|
||
# 上传修改的文件
|
||
- server/app/common/model/tcm/Prescription.php
|
||
- server/app/adminapi/logic/tcm/PrescriptionLogic.php
|
||
```
|
||
|
||
### 步骤 5: 部署前端代码
|
||
```bash
|
||
# 构建前端
|
||
cd admin
|
||
npm run build
|
||
|
||
# 上传构建产物
|
||
# 上传 dist/ 目录到服务器
|
||
```
|
||
|
||
### 步骤 6: 清除缓存(如需要)
|
||
```bash
|
||
cd server
|
||
php think clear
|
||
```
|
||
|
||
### 步骤 7: 测试功能
|
||
1. 创建新处方,选择不同类型
|
||
2. 验证用量字段正确保存
|
||
3. 编辑处方,验证数据正确加载
|
||
4. 查看处方详情,验证显示正确
|
||
|
||
## 7. 数据验证
|
||
|
||
### 7.1 前端验证
|
||
```typescript
|
||
// 浓缩水丸:1-10g
|
||
if (formData.prescription_type === '浓缩水丸') {
|
||
if (formData.dosage_amount < 1 || formData.dosage_amount > 10) {
|
||
// 错误提示
|
||
}
|
||
}
|
||
|
||
// 饮片:50-250ml,步进50
|
||
if (formData.prescription_type === '饮片') {
|
||
if (formData.dosage_amount % 50 !== 0) {
|
||
// 错误提示
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7.2 后端验证(建议添加)
|
||
```php
|
||
// 在 PrescriptionLogic::add() 中添加
|
||
if ($params['prescription_type'] === '浓缩水丸') {
|
||
$amount = (float)($params['dosage_amount'] ?? 0);
|
||
if ($amount < 1 || $amount > 10) {
|
||
self::setError('浓缩水丸用量必须在1-10g之间');
|
||
return null;
|
||
}
|
||
}
|
||
|
||
if ($params['prescription_type'] === '饮片') {
|
||
$amount = (float)($params['dosage_amount'] ?? 0);
|
||
if ($amount < 50 || $amount > 250 || $amount % 50 !== 0) {
|
||
self::setError('饮片用量必须为50-250ml,且为50的倍数');
|
||
return null;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 8. 常见问题
|
||
|
||
### Q1: 字段已存在错误
|
||
```
|
||
ERROR 1060 (42S21): Duplicate column name 'dosage_amount'
|
||
```
|
||
**解决**: 字段已存在,跳过此步骤或先删除字段再添加。
|
||
|
||
### Q2: 旧数据如何处理?
|
||
**方案**: 旧数据的 `dosage_amount` 为 NULL,前端显示为空,不影响功能。
|
||
|
||
### Q3: 如何批量更新旧数据?
|
||
```sql
|
||
-- 为浓缩水丸类型设置默认用量
|
||
UPDATE `zyt_tcm_prescription`
|
||
SET
|
||
`dosage_amount` = 1,
|
||
`dosage_unit` = 'g'
|
||
WHERE `prescription_type` = '浓缩水丸'
|
||
AND `dosage_amount` IS NULL;
|
||
|
||
-- 为饮片类型设置默认用量
|
||
UPDATE `zyt_tcm_prescription`
|
||
SET
|
||
`dosage_amount` = 50,
|
||
`dosage_unit` = 'ml'
|
||
WHERE `prescription_type` = '饮片'
|
||
AND `dosage_amount` IS NULL;
|
||
```
|
||
|
||
## 9. 回滚方案
|
||
|
||
如果需要回滚,执行以下SQL:
|
||
|
||
```sql
|
||
-- 删除添加的字段
|
||
ALTER TABLE `zyt_tcm_prescription`
|
||
DROP COLUMN `dosage_amount`,
|
||
DROP COLUMN `dosage_unit`,
|
||
DROP COLUMN `need_decoction`;
|
||
```
|
||
|
||
## 10. 相关文件清单
|
||
|
||
### 数据库
|
||
- `add_prescription_dosage_fields.sql` - 数据库迁移文件
|
||
|
||
### 后端
|
||
- `server/app/common/model/tcm/Prescription.php` - 处方模型
|
||
- `server/app/adminapi/logic/tcm/PrescriptionLogic.php` - 处方业务逻辑
|
||
|
||
### 前端
|
||
- `admin/src/components/tcm-prescription/index.vue` - 处方组件
|
||
|
||
### 文档
|
||
- `PRESCRIPTION_DOSAGE_FEATURE.md` - 功能说明文档
|
||
- `PRESCRIPTION_DOSAGE_DATABASE_IMPLEMENTATION.md` - 本文档
|
||
|
||
## 11. 测试清单
|
||
|
||
- [ ] 数据库字段添加成功
|
||
- [ ] 创建浓缩水丸处方,用量1-10g
|
||
- [ ] 创建饮片处方,用量50-250ml
|
||
- [ ] 饮片处方代煎选项正常
|
||
- [ ] 编辑处方,数据正确加载
|
||
- [ ] 切换处方类型,用量自动调整
|
||
- [ ] 保存处方,数据正确存储
|
||
- [ ] 查看处方详情,显示正确
|
||
- [ ] 旧数据兼容性测试
|
||
|
||
## 总结
|
||
|
||
此实现完整覆盖了从数据库到前端的所有层次:
|
||
1. ✅ 数据库字段添加
|
||
2. ✅ 模型层类型转换
|
||
3. ✅ 业务逻辑层数据处理
|
||
4. ✅ 前端表单交互
|
||
5. ✅ 自动切换逻辑
|
||
6. ✅ 数据验证
|
||
|
||
所有代码已实现,只需执行数据库迁移即可使用!
|