医药类电商系统中,药品说明书、批准文号、本位码等属于强监管业务字段。本文主要介绍一套药品参数库的设计思路:独立药品模板表存储药品元数据,与商品主表做关联;支持接口拉取、Excel 批量导入两种数据来源;前端根据药品类型(处方药 / OTC)做差异化渲染,同时处理免责提示的条件显示,解决医药商品信息录入繁琐、展示不合规的问题。
> 关键词:医药电商;药品参数库;表结构设计;条件渲染;Excel 批量导入;数据隔离
普通商城商品表直接存储商品详情参数,并不适合医药场景:
1. 大量药品会重复,同一种药品会被多个 SKU、多个商品复用,如果把说明书大字段冗余在商品表,会造成大量数据重复,维护成本高。
2. 监管要求:**处方药前端不能展示完整说明书内容,需要统一展示 “详见药品说明书”;OTC 需要完整展示成份、适应症、不良反应、禁忌、注意事项等信息**。
3. 数据来源多:支持第三方药品接口同步,同时支持运营 Excel 批量导入药品档案。
4. 需要区分数据来源,接口拉取数据支持锁定保护,避免误改;导入数据允许自定义编辑。
如果直接把说明书字段全部塞进商品主表,后续批量更新、统一维护、合规渲染都会很难扩展。因此采用**独立药品模板表 + 商品关联 ID**的模型。
二、数据库设计核心思路
2.1 核心表:drug_template(药品参数模板表,药品库)
> 这张表存储药品公共档案,一条药品档案可以被多个商品引用。
表格
字段 | 说明 |
|---|---|
id | 主键自增 |
approval_no | 批准文号,核心检索字段 |
drug_standard_code | 药品本位码 |
drug_name | 药品通用名称 |
spec | 规格 |
manufacturer | 生产厂家 |
barcode | 商品条码 |
dosage_form | 剂型 |
pack_unit | 包装单位 |
drug_type | 药品类型:处方药 / 甲类 OTC / 乙类 OTC |
ingredients | 成份 |
indications | 适应症 |
usage_dosage | 用法用量 |
adverse_reactions | 不良反应 |
contraindications | 禁忌 |
precautions | 注意事项 |
storage | 贮藏 |
valid_period | 有效期 |
data_source | 数据来源:api 接口同步 /excel_import 导入 |
is_lock | 是否锁定:1 锁定 0 未锁定;接口同步的数据默认锁定,防止误编辑 |
sync_version | 数据版本号,用于缓存失效 |
create_time | 创建时间 |
update_time | 更新时间 |
唯一索引:`uk_approval_spec (approval_no, spec)`**
> 用批准文号 + 规格作为联合唯一约束,防止同药品重复入库。
2.2 商品表关联设计
商品表增加字段:`drug_template_id bigint`,关联 `drug_template.id`。
> 业务逻辑:商品不冗余存储完整说明书,通过 drug_template_id 关联获取药品全部参数。
> 好处:药品档案修改,所有引用该档案的商品全部自动生效,无需逐个修改商品。
三、数据写入的两种通路
class DrugInfoService
{
/**
* 三方药品数据 API 域名
*/
const JISU_API_HOST = 'https://xxxx.com';
/**
* 搜索接口路径
*/
const JISU_SEARCH_PATH = '/medicine/query';
/**
* 详情接口路径
*/
const JISU_DETAIL_PATH = '/medicine/detail';
/**
* system_config 中 AppKey 的菜单名
*/
const CONFIG_APPKEY = 'drug_api_appkey';
/**
* 数据来源标记
*/
const SOURCE = 'jisuapi';
/**
* 公共缓存模板表名(用于受控文件关键字校验)
*/
const TEMPLATE_TABLE = 'drug_template';
/**
* 处方药脱敏占位文案
*/
const MASK = '详见药品说明书';
/**
* 16 个业务字段(drug_template / goods_drug_param 共用)
*/
const FIELDS = [
'approval_num', 'reference_code', 'manufacturer', 'spec', 'type', 'unit', 'barcode',
'disease', 'ingredients', 'indication', 'usage', 'adverse_reaction', 'taboo', 'attention', 'storage', 'validity_period',
];
/**
* 处方药脱敏字段(仅这 7 个字段替换为占位文案)
*/
const MASK_FIELDS = ['disease', 'ingredients', 'indication', 'usage', 'adverse_reaction', 'taboo', 'attention'];
/**
* 搜索接口限流:每管理员每分钟次数
*/
const SEARCH_RATE_LIMIT = 15;
/**
* 搜索限流 Redis key 前缀
*/
const SEARCH_RATE_KEY_PREFIX = 'drug_api_search_rate:';
通路 1:第三方 API 接口拉取
1. 后台输入批准文号 / 本位码 / 药品名称调用数据源接口。
2. 根据`approval_no + spec`判断药品档案是否存在。
- 存在:更新档案,递增 sync_version;
- 不存在:新增记录,`data_source=api`,`is_lock=1`锁定。
3. 将 drug_template_id 回填至当前编辑的商品。
4. 锁定状态下后台表单只读;如需修改,手动解锁`is_lock=0`后允许编辑。
通路 2:Excel 批量导入新增 / 更新药品档案
复用原有商品导入模板,在原有商品字段之后追加药品相关列。
1. 解析 Excel 表头,按表头字段映射,不依赖固定列下标。
2. 逐行读取,优先读取批准文号 + 规格;
3. 根据联合唯一键判断:
- 已存在:更新 drug_template 对应记录;
- 不存在:新增药品档案,`data_source=excel_import`,默认不锁定。
4. 导入支持部分失败:记录行号 + 错误信息,输出错误日志,不整批回滚。
5. 商品记录同时绑定对应的`drug_template_id`。
> ⚠️注意:Excel 导入时,药品类型字段必须校验,为空则标记该行导入失败。
四、前端差异化渲染逻辑(小程序商品详情)
商品详情增加独立 Tab【药品参数】,通过关联的 drug_template 获取药品档案。
<view class="product-intro detail-tabs" id="past3">
<view class="detail-tab-header acea-row row-center-wrapper">
<view class="detail-tab-item" :class="{ on: detailTabIndex === 0 }" @tap="switchDetailTab(0)">
{{$t(`商品介绍`)}}
</view>
<view class="detail-tab-item" :class="{ on: detailTabIndex === 1 }" v-if="drugParam.configured"
@tap="switchDetailTab(1)">
{{$t(`药品参数`)}}
</view>
</view>
<view class="detail-tab-content">
<view v-show="detailTabIndex === 0" class="detail-tab-pane">
<!-- #ifndef APP-PLUS -->
<parser :html="description" ref="article" :tag-style="tagStyle"></parser>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view class="description" v-html="description"></view>
<!-- #endif -->
</view>
<view v-show="detailTabIndex === 1" class="detail-tab-pane" v-if="drugParam.configured">
<view class="drug-param-table" v-if="Object.keys(drugFields).length">
<view class="drug-param-row" v-for="(val, key) in drugFields" :key="key">
<view class="drug-param-cell drug-param-label">{{ key }}</view>
<view class="drug-param-cell drug-param-value">{{ val }}</view>
</view>
</view>
<view class="no-param" v-else>暂无参数</view>
<view class="drug-param-tip" v-if="Object.keys(drugFields).length">
*药品信息仅供参考,请以实物说明书为准,用药请遵医嘱。
</view>
</view>
</view>
</view>
</scroll-view>
</view>
渲染伪逻辑
if(drug_template.drug_type == "处方药"){
// 处方药合规处理:全部字段展示文本“详见药品说明书”
show_full_info = false
// 处方药:不展示免责提示文案
show_disclaimer = false
}else{
// OTC甲类/乙类:渲染完整说明书各个字段
show_full_info = true
// 展示免责提示小字
show_disclaimer = true
}
// 免责文案:药品信息仅供参考,请以实物说明书为准,用药请遵医嘱。UI 层面细节:
- 免责提示文案,不使用全屏通栏 banner;表格下方纯文本、浅灰色小号字体,与表格左对齐,无背景无边框。
- Tab 无论处方药 / OTC 都保留,不做 Tab 隐藏,保证页面结构统一。
五、缓存设计要点
1. drug_template 表设置`sync_version`版本号,每次更新 + 1。
2. 前端 / 接口层缓存药品参数,校验 version,版本发生变化则清除缓存重新拉取。
3. 避免高频重复请求数据源接口,减少第三方接口消耗。
六、遇到的业务坑点总结
1. ❌坑:把说明书大字段冗余存商品表。
> 后果:同药多商品场景,维护成本极高,改一处要改 N 条商品。✅解决方案:独立模板表关联。
2. ❌坑:没有联合唯一索引,导入或接口同步产生大量重复药品档案。
> ✅解决方案:批准文号 + 规格建立唯一索引,做存在更新、不存在新增逻辑。
3. ❌坑:处方药前端直接返回原始适应症、不良反应等字段。
> 后果:违反医药展示监管要求。✅解决方案:服务端做业务层拦截,统一替换展示文本。
4. ❌坑:接口拉取的数据允许直接编辑,数据源被运营误改。
> ✅解决方案:增加 is_lock 锁定标记,接口来源默认锁定,必须手动解锁才可编辑。
5. ❌坑:免责提示全部场景统一展示。
> 后果:处方药没有展示任何说明书内容,展示免责提示逻辑不合理。✅解决方案:OTC 才渲染免责文本。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。