Menu item update, homepage update, ignore Resource folder

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
william.wan 2026-02-12 23:57:06 +08:00
parent 80470e008b
commit 863a8a6d9a
29 changed files with 1841 additions and 86 deletions

4
.gitignore vendored
View File

@ -12,6 +12,10 @@ dist
dist-ssr dist-ssr
*.local *.local
# Resource files
Resource
资源中心
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
!.vscode/extensions.json !.vscode/extensions.json

View File

@ -53,7 +53,7 @@ rmo-website/
2. **公司介绍** 2. **公司介绍**
- 临研安公司简介 - 临研安公司简介
- 活动动态(研讨会、发布会、展会、培训会) - 活动动态(研讨会、发布会、展会、培训会)
- 资源中心(法律法规、团体标准、行业共识、视频) - 资源中心(法律法规、条款标准、行业共识、视频)
3. **我们的服务** 3. **我们的服务**
- 自保(专项风险管理基金) - 自保(专项风险管理基金)

View File

@ -140,14 +140,14 @@
1. **保险方案页面**(已实现) 1. **保险方案页面**(已实现)
- 基础保障、全面保障说明 - 基础保障、全面保障说明
- 保险团体标准核心内容 - 保险条款标准核心内容
- **获取报价入口**:页面内提供「获取报价」按钮,点击后打开报价申请流程(弹窗或报价页面,见 2.3.2.2 - **获取报价入口**:页面内提供「获取报价」按钮,点击后打开报价申请流程(弹窗或报价页面,见 2.3.2.2
- 保险服务内容: - 保险服务内容:
- 保险合同审查 - 保险合同审查
- 理赔审查 - 理赔审查
- 保险条款修订 - 保险条款修订
- 理赔规则制定 - 理赔规则制定
- 团体标准制定 - 条款标准制定
- 服务供应商展示(保险公司、经纪公司 logo - 服务供应商展示(保险公司、经纪公司 logo
2. **保证方案页面**(已实现) 2. **保证方案页面**(已实现)

View File

@ -0,0 +1,383 @@
# RMO 价值主张与优势提炼
**落实GCP风险管理要求一切为患者安全**
*项目中的受试者以及未来上市后使用该药的患者*
基于《概述总结》文件夹中的核心文档提炼
---
## 一、患者安全的挑战
### 1.1 核心挑战
- **创新疗法带来患者安全的未知风险**:基因治疗、细胞治疗等新技术应用增加了试验的复杂性和风险,对患者安全带来新的挑战
- **受试者对自身权益的关注不断提升**:随着法规完善和公众意识提高,受试者对权益保护、补偿机制、安全保障的期望越来越高
- **不及时处理可能导致巨大的外溢风险**中国临床试验纠纷中约60%的案件因处理不及时引发,可能影响项目进展、企业声誉,甚至导致项目终止
### 1.2 行业现状与挑战(详细)
#### 患者安全风险日益凸显
- **临床试验风险复杂多样**SUSAR、ADRSADR、AESAE、与试验相关非医疗一切风险
- **风险识别困难**:试验相关性、因果相关性、预期与严重性判断存在专业门槛
- **处理不及时引发纠纷**中国临床试验纠纷中约60%的案件因处理不及时引发
- **责任界定不清**申办者、研究者、研究机构、参与者、CXO之间责任划分存在盲区
#### 风险管理能力不足
- **风险能力尚未体系化,工具单一**:目前国内仅有商业保险可进行风险分散和分摊;尚未有政策性强制保险、行业风险基金等机制
- **商业保险投保率低,上市风险裸奔**临床试验阶段投保率超过90%药品上市后持有人投保率不足15%(长期)
- **风险能力储备低于实际投保风险能力**:商业保险条款与现行法律、行政制度、行业现状等不符,存在"门票式保险"
- **专业鸿沟**:保险行业对医药理解不足,医药行业对风险管理理解不足,双方存在专业鸿沟
#### 企业面临的困境
- **显性风险与"隐形"风险并存**
- 受试者发生"不良事件等"处理不及时
- "被动"放弃因(研究者过错)代位追偿
- 仅能使用销售费用进行补偿的合规问题
- "不良事件等"处理专业性不足
- **纠纷管理存盲区**
- 不适合与受试者直接接触
- 临床试验项目的"强势乙方"
- 超出保障范围的赔偿/补偿
- 临床试验各主体缺少清晰的专人处理
---
## 二、政策法规要求
### 2.1 核心要求
- **ICH E6 R3患者安全是首要考虑因素**ICH E6(R3)再次强调试验参与者的权益、安全和健康是临床试验设计和实施的首要考虑因素。这一原则贯穿于整个试验过程中,以确保参与者在试验中的权益得到最大程度的保护。
- **申办者责任:诊疗费用承担、及时补偿**:对于因试验导致的损害,申办者应负责承担相关诊疗费用;申办者应提供适当的补偿,确保参与者的权益得到全面保障;申办者和研究者应当及时兑付给予受试者的补偿或者赔偿。
- **高质量安全数据,保障未来广泛人群的安全性**:通过识别关键质量因素并制定相应的风险管理策略,最大程度地降低试验风险并确保结果的可靠性,最终保护试验参与者的权益;高质量的安全数据不仅保障当前受试者安全,更为未来上市后广泛人群的安全性提供重要保障。
### 2.2 ICH E6(R3) 详细要求
#### 知情同意与参与者权益保障
- **隐私与保密**:试验必须保护参与者的隐私和其相关信息的保密性
- **充分知情**:参与者的参与应是自愿的,并基于充分知情的同意过程;信息必须清晰简洁和易于理解
- **退出权**:参与者有权随时决定停用试验用药品或退出试验,而不会受到惩罚或损失其本应享有的利益
- **地位提升**:将"Subject"改为"Participant",体现对试验参与者地位的尊重和提升
#### 申办者责任与补偿机制
- **诊疗费用承担**:对于因试验导致的损害,申办者应负责承担相关诊疗费用
- **适当补偿**:申办者应提供适当的补偿,确保参与者的权益得到全面保障
- **及时兑付**:申办者和研究者应当及时兑付给予受试者的补偿或者赔偿
#### 安全性监测与报告
- **加强监测**:加强了临床试验安全性的监测和报告要求,确保研究者能够及时识别和报告不良事件
- **医疗保健责任**:明确了研究者在试验过程中应对参与者的医疗保健负责,确保其得到妥善的医疗处理
- **保护责任**:进一步强化了研究者对参与者权益、安全和健康的保护责任
#### 基于风险的质量管理
- **风险识别**:要求申办者在试验开始前和整个试验实施过程中识别可能对关键质量因素产生有意义影响的风险
- **风险控制**:根据风险级别实施相应的控制措施
- **质量保证**:通过识别关键质量因素并制定相应的风险管理策略,最大程度地降低试验风险并确保结果的可靠性,最终保护试验参与者的权益
### 2.2 ICH GCP 现代化趋势
#### 质量源于设计Quality by Design
- **前瞻性规划**:在试验设计和规划阶段明确数据质量参数
- **关键质量因素CTQ**:识别对研究结论可靠性和患者安全至关重要的因素
- **基于风险的监控**:根据风险评估结果,实施相应的监控策略
#### 基于风险的方法Risk-Based Approach
- **灵活性与适应性**:认识到不同试验类型的风险水平差异,允许相应的灵活性
- **聚焦关键风险**:将监督活动聚焦于预防或减轻对数据质量和人类受试者保护过程至关重要的风险
- **持续改进**:通过风险识别、评估和控制,持续改进试验质量
#### 数据质量与受试者保护并重
- **双重目标**确保人类受试者保护assurance of human subject protection和确保数据质量assurance of data quality
- **全生命周期管理**:适用于产品开发整个生命周期的临床试验
- **国际协调**:支持多区域临床试验的协调和成功
### 2.3 中国法规要求
#### GCP 2020版要求
- **无过错责任原则**中国2020版GCP删除了"医疗事故除外"条款将责任范围扩大至所有试验相关损害与ICH E6 R2的"无过错责任"原则完全接轨
- **申办者责任主体**:以申办者为责任主体,通过经济补偿与及时兑付机制确保受试者损害得到救济
- **保险或保证**:申办者应当向研究者和临床试验机构提供与临床试验相关的法律上、经济上的保险或者保证,并与临床试验的风险性质和风险程度相适应
---
## 三、RMO 解决方案
### 3.1 核心解决方案
- **基于风险管理科学识别风险,采取措施**构建风险地图帮助申办者识别可能对关键质量因素产生有意义影响的风险区分首要风险SUSAR、SAE和次要风险AE、外溢风险实施差异化风险管理策略通过风险减量服务从源头降低风险发生概率提升试验质量。
- **专业评估、24小时响应一站式理赔支持**:多学科专家团队对不良事件进行独立评估,确保责任界定清晰、补偿标准合理;通过一站式理赔服务,确保受试者损害得到及时救治和补偿,避免因处理不及时引发纠纷;通过数字化平台和直付能力,实现快速理赔和费用结算,确保及时兑付。
- **积极解纷,服务研究者与试验参与者**:针对受试者出险后的全流程管理(联系、安抚、安排就医、沟通诉求、沟通合理预期);及时介入,避免矛盾激化;通过专业沟通,降低项目中断、危机公关等关联风险;无需企业方参与患者沟通与谈判,减少纠纷风险。
### 3.2 构建完整风险管理闭环
### 3.2 构建完整业务闭环
#### 挑战 → 政策 → 解决方案的逻辑闭环
```
当前挑战(患者安全风险)
政策法规要求ICH E6 R3、GCP现代化
RMO解决方案全链条风险管理
风险识别 → 风险转移 → 风险减量 → 理赔服务
保障患者安全与权益
提升试验质量与合规性
降低企业风险与成本
```
#### 具体实现路径
**阶段一:风险识别与评估**
- 基于ICH E6 R3要求构建风险地图试验相关性、因果相关性、预期与严重性
- 识别关键质量因素CTQ制定风险管理策略
- 评估项目风险等级,确定保障方案
**阶段二:风险转移与保障**
- **首要风险**SUSAR、SAE造成的身故/残疾赔偿金):通过高杠杆保险转移
- **次要风险**非SUSAR医疗费用、外溢风险通过"自保基金+风险减量服务+外溢风险管理服务"解决
- 确保保障范围与政策法规要求一致,避免"门票式保险"
**阶段三:风险减量与质量提升**
- **方案优化**知情同意书审阅、修改、建议确保符合ICH E6 R3要求
- **质量提升**结合保险的RMP计划促进研究质量提升
- **合规支持**:确保临床研究项目合规执行,避免/减少方案违背
**阶段四:理赔服务与权益保障**
- **一站式理赔**:统一咨询电话,无需企业方参与患者沟通与谈判
- **及时响应**24小时内响应确保受试者损害得到及时救治
- **专业评估**:多学科专家团队独立评估,确保责任界定清晰
- **快速理赔**:数字化平台支持在线审核/赔付,实现及时兑付
---
## 四、RMO 价值
### 4.1 核心价值
- **经济上保证受试者的及时救治,保障其权益**通过RMO模式确保申办者能够及时承担与试验相关的诊疗费用提供标准化的补偿机制确保受试者权益得到全面保障通过数字化平台和直付能力实现快速理赔和费用结算确保及时兑付。
- **分层管理小概率大风险SUSAR与大概率小风险AE**首要风险SUSAR、SAE造成的身故/残疾赔偿金通过高杠杆保险转移次要风险非SUSAR医疗费用、外溢风险通过"自保基金+风险减量服务+外溢风险管理服务"解决;实现成本可控、保障全面的风险管理。
- **遵守风险管理法规要求,降低申办者与受试者风险与成本**响应ICH E6 R3等国际法规要求保障试验参与者权益、安全和健康通过专业风险管理服务构建"挑战-政策-解决方案"的完整业务闭环;降低受试者经济补偿总支出(保费支出、私下和解支出、内部人员工时),同时降低企业风险与成本。
---
## 五、RMO 价值主张(详细)
### 4.1 核心定位
**RMORisk Management Organization风险管理组织** 是一站式临床试验与上市后责任风险管理的专业服务组织,通过整合**保险公司、保险经纪、药物警戒、第三方评估机构**等资源,为生物医药企业提供从风险识别、风险转移、风险减量到理赔服务的全链条风险管理解决方案。
**RMO的使命**响应ICH E6 R3等国际法规要求保障试验参与者权益、安全和健康通过专业风险管理服务。
### 5.2 三大核心价值
#### 价值一:解决风险管理边界认知不足的问题
- **对应挑战**:生物医药企业对风险管理的边界认知不足,缺少专人处理;纠纷管理存盲区,缺少独立中间人处理纠纷。
- **政策要求**ICH E6 R3要求申办者识别风险、实施控制措施确保参与者权益、安全和健康。
- **RMO方案**:提供专业团队,统一行业术语,构建保险与医药行业的对话基础,让企业"讲的清楚、买的明白、赔的容易";通过一站式理赔服务,避免企业直接面对受试者,减少纠纷风险。
#### 价值二:实现风险分层管理与成本优化
- **对应挑战**:传统保险模式将所有风险打包,导致高保费、低覆盖,或出现"门票式保险"(仅满足监管要求,实际保障不足)。
- **政策要求**ICH E6 R3要求基于风险的质量管理识别关键质量因素实施差异化风险控制。
- **RMO方案**
- **首要风险**SUSAR、SAE造成的身故/残疾赔偿金通过高杠杆保险转移符合ICH E6 R3对严重不良事件的保障要求
- **次要风险**非SUSAR医疗费用、外溢风险通过"自保基金+风险减量服务+外溢风险管理服务"解决,实现成本可控
- 实现**成本可控、保障全面**的风险管理,既满足政策要求,又优化企业成本
#### 价值三:赋能生命科学风险管理生态
- **对应挑战**:保险行业对医药理解不足,医药行业对风险管理理解不足,双方存在专业鸿沟;风险能力尚未体系化,工具单一。
- **政策要求**ICH GCP现代化强调质量源于设计、基于风险的方法需要跨学科专业能力。
- **RMO方案**:作为桥梁,协调保险与医药,推进责任保险落地;通过数字化平台、专业团队、标准化流程,构建跨领域风险解决方案;推动行业标准建设,提升行业专业能力。
---
## 六、RMO 核心优势
### 2.1 专业能力优势
#### 跨学科专业团队
- **医学+保险+法律+科技**的复合型团队
- 具备医师资格、药师资格、律师资格的专业人员
- 医药行业工作20+年药物警戒工作18年的资深专家
- 生命科学保险领域10+年工作经验的专业团队
#### 风险识别与评估能力
- 构建**风险地图**:基于临床试验风险类型梳理,建立三维坐标体系(试验相关性、因果相关性、预期与严重性)
- 独立第三方评估:多学科专家团队对不良事件进行原因判断,提供中立、专业的评估意见
- 数据驱动的风险量化:不断细分风险因素,建立风险因素量化模型,完善费率拟定公式
### 2.2 服务模式优势
#### 一站式服务
- **一站式理赔服务**统一咨询电话4009-606-520无需企业方参与患者沟通与谈判
- **全流程管理**:从承保前的风险评估到出险后的介入处理,提供全流程解决方案
- **数字化平台**投保、理赔全流程在线化消除信息孤岛提升效率60%
#### 风险减量服务
- **方案优化**:知情同意书审阅、修改、建议;相关方风险管理与最小化培训
- **质量提升**结合保险的RMP计划促进研究质量提升与药监要求的风险管理结合
- **合规支持**:确保临床研究项目合规执行,避免/减少方案违背
#### 外溢风险管理服务
- **事件管理**:针对受试者出险后的全流程管理(联系、安抚、安排就医、沟通诉求、沟通合理预期)
- **纠纷化解**:及时介入,避免矛盾激化;通过专业沟通,降低项目中断、危机公关等关联风险
- **成本控制**:降低受试者经济补偿总支出(保费支出、私下和解支出、内部人员工时)
### 2.3 技术平台优势
#### 数字化能力
- **智能投保**:方案预估、智能推荐、过程追踪、便捷投保、数字制单
- **高效理赔**:智能核损、在线审核/赔付、理赔标准化、案件实时追踪和追溯
- **数据管理**:案件材料全流程管理,支持文件详情在线预览,避免资料漏交或错交
#### 标准化流程
- **统一标准**:平台内置与各大保司统一的理赔标准和理赔文件
- **自动理算**:系统根据理赔类型自动计算理算金额,理算过程及结果清晰透明可见
- **流程追溯**:全程溯源,无惧人员离职变动,确保标准化的流程
### 2.4 生态协作优势
#### 多方资源整合
- **保险公司**:提供清晰、合理的"主要风险"保障体系和规则
- **保险经纪(华泰)**:代表客户与保司进行承保风险翻译、评估、谈判,管理"外溢风险"
- **临研安**:提供药物警戒、风险评估、理赔支持等专业技术服务
- **药盾基金会**:提供第三方独立评估意见
#### 直付能力
- 华泰长期为日本多家保险公司提供转诊、医疗推荐、费用结算服务业务已开展近30年
- 具有外币结算资质,力争逐步实现与医院直付,提升时效性
### 2.5 行业影响优势
#### 推动行业标准建设
- 联合临床试验领域专家和保险行业专家建立行业共识及可操作的标准SOP
- 成立针对临床试验保险涉及受试者保护的行业组织
- 推动人工智能在临床试验保险领域的智能化建设
#### 提升行业专业能力
- 结合临床试验行业协会和保险相关行业协会,对保险从业人员进行临床试验相关培训
- 提升保险相关业务专业知识,更好地为客户提供专业服务
---
## 七、RMO 差异化竞争力
### 3.1 与传统保险模式对比
| 维度 | 传统保险模式 | RMO模式 |
|------|------------|---------|
| **保障范围** | 主要覆盖SUSAR其他风险保障不足 | 分层保障:首要风险(保险)+次要风险RMO模式 |
| **理赔效率** | 周期长、赔付慢、资料杂、无标准 | 在线审核/赔付标准化流程60%效能提升 |
| **专业能力** | 保险行业缺乏医药专业知识 | 医学+保险+法律+科技复合型团队 |
| **成本控制** | 高保费、低覆盖 | 成本可控,通过自保基金+风险减量降低总支出 |
| **服务模式** | 被动理赔 | 主动风险管理:风险评估+保障建议+理赔服务+风险减量 |
### 3.2 核心差异化点
1. **从"保险购买"到"风险管理"**:不仅提供保险产品,更提供全链条风险管理服务
2. **从"单一工具"到"综合方案"**:整合保险、自保基金、风险减量、外溢风险管理等多种工具
3. **从"被动应对"到"主动预防"**:通过风险减量服务,从源头降低风险发生概率
4. **从"信息孤岛"到"数字化平台"**:通过数字化平台打通投保、理赔全流程,提升效率
---
## 八、RMO 使命与愿景
### 使命
为临床试验、药械持有人等责任保险提供技术支持服务
### 中期目标
**"讲的清楚、买的明白、赔的容易"**
### 长期愿景
**因保险介入,临床试验与药物警戒质量得以提升至全民知晓**
---
## 九、适用场景
### 5.1 临床试验阶段
- 申办者需要全面风险管理解决方案
- 需要降低受试者经济补偿总支出
- 需要提升理赔效率,避免纠纷激化
- 需要风险减量服务,提升研究质量
### 5.2 上市后阶段
- MAH持有人需要产品责任保险
- 需要与临床试验责任保险的衔接
- 需要应对合规检查与风险事件
### 5.3 特殊需求
- 国际多中心临床试验(需要外币结算、直付能力)
- 新技术应用(基因治疗、细胞治疗等高风险项目)
- 复杂理赔案件(需要多学科专家团队独立评估)
---
## 十、业务逻辑闭环总结
### 9.1 完整业务逻辑
```
┌─────────────────────────────────────────────────────────────┐
│ 当前挑战(患者安全风险) │
│ • 风险识别困难、责任界定不清 │
│ • 风险管理能力不足、专业鸿沟 │
│ • 处理不及时引发纠纷、成本控制困难 │
└──────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 政策法规要求(国际趋势) │
│ • ICH E6 R3患者安全是首要考虑因素 │
│ • 申办者责任:诊疗费用承担、适当补偿、及时兑付 │
│ • 基于风险的质量管理:风险识别、控制、质量保证 │
│ • GCP现代化质量源于设计、基于风险的方法 │
└──────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ RMO解决方案全链条风险管理
│ │
│ 风险识别 → 风险转移 → 风险减量 → 理赔服务 │
│ ↓ ↓ ↓ ↓ │
│ 风险地图 分层保障 质量提升 权益保障 │
│ │
│ • 响应政策要求:保障患者安全与权益 │
│ • 落实申办者责任:诊疗费用承担、及时兑付 │
│ • 支持风险管理:风险识别、分层控制、质量提升 │
└──────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 价值实现(闭环效果) │
│ • 保障患者安全与权益符合ICH E6 R3要求
│ • 提升试验质量与合规性(基于风险的质量管理) │
│ • 降低企业风险与成本(风险分层、成本优化) │
│ • 构建行业生态(推动标准建设、提升专业能力) │
└─────────────────────────────────────────────────────────────┘
```
### 9.2 关键成功因素
1. **政策响应**深度理解ICH E6 R3、GCP现代化等国际法规要求确保解决方案符合政策导向
2. **专业能力**:医学+保险+法律+科技的复合型团队,具备跨学科专业能力
3. **全链条服务**:从风险识别到理赔服务的完整闭环,确保患者安全与权益保障
4. **数字化支撑**:通过数字化平台提升效率,实现标准化、透明化的风险管理
5. **生态协作**:整合多方资源,构建行业生态,推动标准建设
### 9.3 业务价值
- **对患者**:权益、安全和健康得到全面保障,损害得到及时救治和补偿
- **对企业**:降低风险与成本,提升合规性与质量,减少纠纷与危机
- **对行业**:推动标准建设,提升专业能力,构建健康生态
- **对监管**:响应政策要求,支持基于风险的质量管理,提升行业整体水平
---
*基于《概述总结》文件夹中的核心文档提炼整合ICH E6 R3和GCP现代化要求文档日期2025年2月*

99
extract_rmo_content.py Normal file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
提取RMO概述总结文件内容用于提炼价值主张和优势
"""
import os
import sys
from pathlib import Path
try:
from docx import Document
HAS_DOCX = True
except ImportError:
HAS_DOCX = False
print("警告: python-docx 未安装,无法读取 .docx 文件")
try:
from pptx import Presentation
HAS_PPTX = True
except ImportError:
HAS_PPTX = False
print("警告: python-pptx 未安装,无法读取 .pptx 文件")
def extract_docx(file_path):
"""提取DOCX文件文本内容"""
if not HAS_DOCX:
return None
try:
doc = Document(file_path)
paragraphs = [p.text for p in doc.paragraphs if p.text.strip()]
return '\n'.join(paragraphs)
except Exception as e:
return f"读取错误: {e}"
def extract_pptx(file_path):
"""提取PPTX文件文本内容"""
if not HAS_PPTX:
return None
try:
prs = Presentation(file_path)
slides_text = []
for i, slide in enumerate(prs.slides, 1):
slide_text = []
for shape in slide.shapes:
if hasattr(shape, "text") and shape.text.strip():
slide_text.append(shape.text.strip())
if slide_text:
slides_text.append(f"--- 幻灯片 {i} ---\n" + "\n".join(slide_text))
return "\n\n".join(slides_text)
except Exception as e:
return f"读取错误: {e}"
def main():
base_dir = Path(r"d:\SoftwarePrj\RMO网站\资源中心\关于RMO介绍\RMO概述\概述总结")
files_to_read = [
("方案制定/一站式临床试验风险管理RMO.docx", extract_docx),
("构建中国药械风险能力责任保障体系(阶段性汇报)【20250505】.pptx", extract_pptx),
("华泰_构建生命科学领域责任保险新质生产力202407.pptx", extract_pptx),
("临研安生命科学保险技术支持服务介绍 202505.pptx", extract_pptx),
("MAH持有人责任风险管理方案-网站建设.pptx", extract_pptx),
]
output_lines = []
output_lines.append("=" * 80)
output_lines.append("RMO概述总结文件内容提取")
output_lines.append("=" * 80)
output_lines.append("")
for file_rel_path, extract_func in files_to_read:
file_path = base_dir / file_rel_path
if not file_path.exists():
output_lines.append(f"文件不存在: {file_rel_path}")
output_lines.append("")
continue
output_lines.append(f"\n{'='*80}")
output_lines.append(f"文件: {file_rel_path}")
output_lines.append(f"{'='*80}\n")
content = extract_func(file_path)
if content:
output_lines.append(content)
else:
output_lines.append("无法提取内容(可能缺少依赖库)")
output_lines.append("\n")
# 输出到文件
output_file = base_dir / "提取内容_概述总结.txt"
with open(output_file, 'w', encoding='utf-8') as f:
f.write('\n'.join(output_lines))
print(f"内容已提取到: {output_file}")
print("\n提取的内容预览:")
print('\n'.join(output_lines[:50]))
if __name__ == "__main__":
main()

View File

@ -182,6 +182,13 @@
border-top: none; border-top: none;
} }
/* 知识资源为四列,保证宽度并右对齐避免超出视口 */
.dropdown-menu-knowledge {
min-width: 880px;
left: auto;
right: 0;
}
.dropdown-submenu { .dropdown-submenu {
flex: 1; flex: 1;
padding: 20px 0; padding: 20px 0;
@ -403,6 +410,12 @@
min-width: auto; min-width: auto;
} }
.dropdown-menu-knowledge {
min-width: auto;
left: 0;
right: auto;
}
.dropdown-submenu { .dropdown-submenu {
border-right: none; border-right: none;
border-bottom: 1px solid var(--border-color, #eee); border-bottom: 1px solid var(--border-color, #eee);

View File

@ -24,6 +24,9 @@
<div v-show="aboutRmoOpen" class="dropdown-menu dropdown-menu-level2 dropdown-menu-level3-wrapper"> <div v-show="aboutRmoOpen" class="dropdown-menu dropdown-menu-level2 dropdown-menu-level3-wrapper">
<div class="dropdown-submenu"> <div class="dropdown-submenu">
<RouterLink to="/about/overview" class="dropdown-submenu-title-link">RMO概述</RouterLink> <RouterLink to="/about/overview" class="dropdown-submenu-title-link">RMO概述</RouterLink>
<RouterLink to="/about/insurers">合作保司</RouterLink>
<RouterLink to="/about/brokers">专家经纪</RouterLink>
<RouterLink to="/about/third-party">第三方机构</RouterLink>
</div> </div>
<div class="dropdown-submenu"> <div class="dropdown-submenu">
<RouterLink to="/concern" class="dropdown-submenu-title-link">风险职责</RouterLink> <RouterLink to="/concern" class="dropdown-submenu-title-link">风险职责</RouterLink>
@ -65,7 +68,7 @@
</div> </div>
<div <div
class="nav-dropdown" class="nav-dropdown nav-dropdown-has-level3"
@mouseenter="knowledgeOpen = true" @mouseenter="knowledgeOpen = true"
@mouseleave="knowledgeOpen = false" @mouseleave="knowledgeOpen = false"
> >
@ -76,11 +79,30 @@
知识资源 知识资源
<span class="dropdown-arrow"></span> <span class="dropdown-arrow"></span>
</RouterLink> </RouterLink>
<div v-show="knowledgeOpen" class="dropdown-menu dropdown-menu-level2"> <div v-show="knowledgeOpen" class="dropdown-menu dropdown-menu-level2 dropdown-menu-level3-wrapper dropdown-menu-knowledge">
<RouterLink to="/knowledge/regulations">法规指南</RouterLink> <div class="dropdown-submenu">
<RouterLink to="/knowledge/insurance">保险知识</RouterLink> <RouterLink to="/knowledge/regulations" class="dropdown-submenu-title-link">PV知识</RouterLink>
<RouterLink to="/knowledge/pv-insurance">PV与保险</RouterLink> <RouterLink to="/knowledge/regulations">法规指南</RouterLink>
<RouterLink to="/faq">常见问题</RouterLink> <RouterLink to="/knowledge/ai-app">AI应用</RouterLink>
</div>
<div class="dropdown-submenu">
<RouterLink to="/knowledge/insurance" class="dropdown-submenu-title-link">保险知识</RouterLink>
<RouterLink to="/knowledge/insurance/regulations">基础知识</RouterLink>
<RouterLink to="/knowledge/insurance/overseas">国外比较</RouterLink>
<RouterLink to="/knowledge/insurance/group-standard">条款标准</RouterLink>
</div>
<div class="dropdown-submenu">
<RouterLink to="/faq" class="dropdown-submenu-title-link">常见问题</RouterLink>
<RouterLink to="/faq/duty-logic">职责逻辑</RouterLink>
<RouterLink to="/faq/coverage">保障范围</RouterLink>
<RouterLink to="/faq/pv-insurance">PV与保险</RouterLink>
</div>
<div class="dropdown-submenu">
<RouterLink to="/knowledge/learning-center" class="dropdown-submenu-title-link">学习中心</RouterLink>
<RouterLink to="/knowledge/learning-center/cases">案例学习</RouterLink>
<RouterLink to="/knowledge/learning-center/videos">培训视频</RouterLink>
<RouterLink to="/knowledge/learning-center/exam">考试中心</RouterLink>
</div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,361 @@
<template>
<div class="rmo-value-proposition">
<!-- 标题区域 -->
<div class="proposition-header">
<h2 class="section-title">落实GCP风险管理要求一切为患者安全</h2>
<p class="section-subtitle">项目中的受试者以及未来上市后使用该药的患者</p>
</div>
<!-- 业务逻辑闭环流程图 -->
<div class="logic-flow">
<div class="flow-step" v-for="(step, index) in flowSteps" :key="index">
<div class="step-content">
<div class="step-header">
<span class="step-badge" :class="`badge-${index + 1}`">{{ step.title }}</span>
</div>
<ul class="step-points">
<li v-for="(point, i) in step.points" :key="i">{{ point }}</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { RouterLink } from 'vue-router'
const flowSteps = [
{
title: '患者安全的挑战',
points: [
'创新疗法带来患者安全的未知风险',
'AE/SAE治疗更复杂费用更高',
'受试者对自身权益的关注不断提升'
]
},
{
title: '政策法规要求',
points: [
'GCP R3患者安全是首要考虑因素',
'申办者责任:诊疗费用承担、及时补偿',
'高质量安全数据,保障未来广泛人群的安全性'
]
},
{
title: 'RMO解决方案',
points: [
'基于风险管理科学识别风险,采取措施',
'专业评估、24小时响应一站式理赔支持',
'积极解纷,服务研究者与试验参与者'
]
},
{
title: 'RMO价值',
points: [
'经济上保证受试者的及时救治,保障其权益',
'分层管理小概率大风险SUSAR与大概率小风险AE',
'遵守风险管理法规要求,降低申办者与受试者风险与成本'
]
}
]
</script>
<style scoped>
.rmo-value-proposition {
width: 100%;
max-width: 100%;
margin: 0 auto;
padding: 60px 40px;
box-sizing: border-box;
}
.proposition-header {
text-align: center;
margin-bottom: 64px;
}
.section-title {
font-size: 2.75rem;
font-weight: 700;
color: var(--text-primary, #1f2937);
margin-bottom: 20px;
letter-spacing: -0.02em;
}
.section-subtitle {
font-size: 1.125rem;
color: var(--text-secondary, #6b7280);
max-width: 900px;
margin: 0 auto;
line-height: 1.7;
}
/* 业务逻辑闭环流程图 */
.logic-flow {
display: flex;
flex-direction: row;
gap: 16px;
margin-bottom: 0;
justify-content: center;
align-items: stretch;
width: 100%;
position: relative;
}
.flow-step {
display: flex;
flex-direction: row;
align-items: stretch;
position: relative;
flex: 0 0 auto;
width: 95%;
max-width: 320px;
}
.step-content {
flex: 1;
background: white;
border-radius: 16px;
padding: 32px 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
border: 1px solid var(--border-color, #e5e7eb);
width: 95%;
min-width: 300px;
display: flex;
flex-direction: column;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.step-content::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--step-color, #0ea5e9) 0%, transparent 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.step-content:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
border-color: var(--step-color, #0ea5e9);
}
.step-content:hover::before {
opacity: 1;
}
.flow-step:nth-child(1) .step-content {
--step-color: #ef4444;
}
.flow-step:nth-child(2) .step-content {
--step-color: #f59e0b;
}
.flow-step:nth-child(3) .step-content {
--step-color: #0ea5e9;
}
.flow-step:nth-child(4) .step-content {
--step-color: #10b981;
}
.step-header {
margin-bottom: 20px;
}
.step-badge {
display: inline-block;
padding: 8px 16px;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: white;
}
.badge-1 {
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
}
.badge-2 {
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
}
.badge-3 {
background: linear-gradient(135deg, #0ea5e9 0%, #0284c7 100%);
}
.badge-4 {
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
}
.step-points {
list-style: none;
padding: 0;
margin: 0;
flex: 1;
}
.step-points li {
padding: 8px 0;
padding-left: 24px;
position: relative;
color: var(--text-secondary, #4b5563);
line-height: 1.6;
font-size: 0.9375rem;
transition: color 0.2s ease;
word-break: keep-all;
}
.step-content:hover .step-points li {
color: var(--text-primary, #1f2937);
}
.step-points li::before {
content: '';
position: absolute;
left: 8px;
top: 16px;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--step-color, #0ea5e9);
transition: transform 0.2s ease;
}
.step-content:hover .step-points li::before {
transform: scale(1.3);
}
/* 行动按钮 */
.action-buttons {
display: flex;
justify-content: center;
gap: 24px;
flex-wrap: wrap;
}
.btn {
padding: 14px 32px;
font-size: 1rem;
font-weight: 500;
border-radius: 8px;
text-decoration: none;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
justify-content: center;
}
.btn-primary {
background: var(--brand-primary, #0ea5e9);
color: white;
border: 2px solid var(--brand-primary, #0ea5e9);
}
.btn-primary:hover {
background: var(--brand-primary-dark, #0284c7);
border-color: var(--brand-primary-dark, #0284c7);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(14, 165, 233, 0.3);
}
.btn-secondary {
background: transparent;
color: var(--brand-primary, #0ea5e9);
border: 2px solid var(--brand-primary, #0ea5e9);
}
.btn-secondary:hover {
background: var(--brand-primary, #0ea5e9);
color: white;
transform: translateY(-2px);
}
/* 响应式设计 */
@media (max-width: 1400px) {
.flow-step {
min-width: 260px;
}
.step-content {
min-width: 260px;
padding: 28px 20px;
}
}
@media (max-width: 1200px) {
.rmo-value-proposition {
padding: 50px 32px;
}
.logic-flow {
gap: 16px;
}
.flow-step {
min-width: 240px;
}
.step-content {
min-width: 240px;
padding: 28px 20px;
}
}
@media (max-width: 968px) {
.logic-flow {
flex-direction: column;
gap: 24px;
}
.flow-step {
width: 100%;
}
}
@media (max-width: 768px) {
.rmo-value-proposition {
padding: 40px 24px;
}
.proposition-header {
margin-bottom: 48px;
}
.section-title {
font-size: 2rem;
}
.section-subtitle {
font-size: 1rem;
}
.step-content {
padding: 24px 20px;
}
.step-badge {
font-size: 0.75rem;
padding: 6px 12px;
}
.step-points li {
font-size: 0.875rem;
padding: 8px 0;
padding-left: 20px;
}
}
</style>

View File

@ -1,7 +1,15 @@
.about-overview { .about-overview,
.about-page {
min-height: 100%; min-height: 100%;
} }
.section-desc {
font-size: 16px;
color: var(--text-color);
line-height: 1.6;
margin: 16px 0 0 0;
}
.content-grid { .content-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));

View File

@ -96,9 +96,9 @@ function Company() {
</ul> </ul>
</div> </div>
<div className="resource-category"> <div className="resource-category">
<h3>📊 </h3> <h3>📊 </h3>
<ul className="resource-list"> <ul className="resource-list">
<li></li> <li></li>
<li></li> <li></li>
<li></li> <li></li>
</ul> </ul>

View File

@ -192,8 +192,8 @@
.solutions-grid { .solutions-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(4, 1fr);
gap: 32px; gap: 20px;
margin-top: 48px; margin-top: 48px;
} }
@ -201,7 +201,7 @@
background: var(--white); background: var(--white);
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
border-radius: 12px; border-radius: 12px;
padding: 40px 32px; padding: 24px 20px;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
color: var(--text-color); color: var(--text-color);
@ -218,29 +218,45 @@
} }
.solution-icon { .solution-icon {
font-size: 64px; font-size: 40px;
margin-bottom: 24px; margin-bottom: 16px;
} }
.solution-card h3 { .solution-card h3 {
font-size: 24px; font-size: 18px;
font-weight: 600; font-weight: 600;
margin-bottom: 16px; margin-bottom: 10px;
color: var(--text-color); color: var(--text-color);
} }
.solution-card p { .solution-card p {
font-size: 16px; font-size: 14px;
color: var(--text-light); color: var(--text-light);
line-height: 1.6; line-height: 1.5;
margin-bottom: 24px; margin-bottom: 16px;
flex: 1; flex: 1;
} }
.solution-link { .solution-link {
color: var(--brand-primary); color: var(--brand-primary);
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 14px;
}
@media (max-width: 1100px) {
.solutions-grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* ========== RMO价值主张组件包装 ========== */
.rmo-solution-wrapper {
width: 100%;
max-width: 1600px;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
overflow: visible;
} }
/* ========== 核心能力 Section ========== */ /* ========== 核心能力 Section ========== */
@ -368,7 +384,11 @@
font-size: 16px; font-size: 16px;
} }
.solutions-grid, .solutions-grid {
grid-template-columns: 1fr;
gap: 24px;
}
.knowledge-grid { .knowledge-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: 24px; gap: 24px;

View File

@ -78,7 +78,7 @@ function Home() {
<div className="hero-content"> <div className="hero-content">
<h1 className="hero-title"></h1> <h1 className="hero-title"></h1>
<p className="hero-subtitle"> <p className="hero-subtitle">
</p> </p>
<div className="hero-buttons"> <div className="hero-buttons">
<Link to="/about/overview" className="btn btn-primary"></Link> <Link to="/about/overview" className="btn btn-primary"></Link>
@ -87,10 +87,6 @@ function Home() {
</button> </button>
</div> </div>
</div> </div>
<div className="hero-scroll-hint">
<span></span>
<div className="scroll-arrow"></div>
</div>
</section> </section>
{/* Section 2: 解决方案 */} {/* Section 2: 解决方案 */}
@ -99,8 +95,8 @@ function Home() {
className="home-section solutions-section" className="home-section solutions-section"
> >
<div className="section-content"> <div className="section-content">
<h2 className="section-title"></h2> <h2 className="section-title">RMO风险管理解决方</h2>
<p className="section-subtitle"></p> <p className="section-subtitle"></p>
<div className="solutions-grid"> <div className="solutions-grid">
<Link to="/solutions/pharmacovigilance" className="solution-card"> <Link to="/solutions/pharmacovigilance" className="solution-card">
<div className="solution-icon">📊</div> <div className="solution-icon">📊</div>

View File

@ -531,7 +531,7 @@
grid-row: 2; grid-row: 2;
} }
/* 右侧 1×2保险团体标准核心内容 */ /* 右侧 1×2保险条款标准核心内容 */
.insurance-cell-standard { .insurance-cell-standard {
grid-column: 4; grid-column: 4;
grid-row: 1 / 3; grid-row: 1 / 3;

View File

@ -73,9 +73,9 @@ function Insurance() {
</p> </p>
</div> </div>
{/* 右侧 1×2保险团体标准核心内容 */} {/* 右侧 1×2保险条款标准核心内容 */}
<div className="insurance-grid-cell insurance-cell-standard"> <div className="insurance-grid-cell insurance-cell-standard">
<h3 className="insurance-cell-title"></h3> <h3 className="insurance-cell-title"></h3>
<ul className="insurance-standard-list"> <ul className="insurance-standard-list">
<li>SUSAR与低风险AE应分开定价</li> <li>SUSAR与低风险AE应分开定价</li>
<li>/</li> <li>/</li>
@ -112,8 +112,8 @@ function Insurance() {
<p></p> <p></p>
</div> </div>
<div className="insurance-item"> <div className="insurance-item">
<h4></h4> <h4></h4>
<p></p> <p></p>
</div> </div>
</div> </div>
</div> </div>
@ -126,7 +126,7 @@ function Insurance() {
<section className="section section-service-providers"> <section className="section section-service-providers">
<div className="container"> <div className="container">
<h2 className="section-title"></h2> <h2 className="section-title"></h2>
<p className="section-desc"></p> <p className="section-desc"></p>
<div className="service-provider-logos"> <div className="service-provider-logos">
{[ {[
{ name: '太平洋保险', file: '太平洋保险logo.jpeg' }, { name: '太平洋保险', file: '太平洋保险logo.jpeg' },
@ -289,7 +289,7 @@ function InsuranceGuarantee() {
<tr> <tr>
<td className="compare-row-label"></td> <td className="compare-row-label"></td>
<td> <td>
GCP及伦理审查对保障的要求 GCP及伦理审查对保障的要求
</td> </td>
<td> <td>
GCP及机构内控要求 GCP及机构内控要求

View File

@ -233,8 +233,8 @@ function Services() {
<p></p> <p></p>
</div> </div>
<div className="insurance-item"> <div className="insurance-item">
<h4></h4> <h4></h4>
<p></p> <p></p>
</div> </div>
</div> </div>
<h3></h3> <h3></h3>

View File

@ -7,6 +7,46 @@
margin: 0 auto; margin: 0 auto;
} }
.privacy-commitment {
margin: 16px 0;
padding: 14px 16px;
background: rgba(14, 165, 233, 0.06);
border: 1px solid rgba(14, 165, 233, 0.2);
border-radius: 8px;
}
.privacy-checkbox-label {
display: flex;
align-items: flex-start;
gap: 10px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
color: var(--text-color);
margin-bottom: 10px;
}
.privacy-checkbox-label input {
margin: 3px 0 0 0;
flex-shrink: 0;
}
.privacy-commitment p {
margin: 0;
font-size: 12px;
line-height: 1.6;
color: var(--text-color, #555);
}
.privacy-commitment a {
color: var(--brand-primary, #0ea5e9);
text-decoration: none;
}
.privacy-commitment a:hover {
text-decoration: underline;
}
.calculator-form { .calculator-form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -2,6 +2,164 @@
min-height: 100%; min-height: 100%;
} }
.quotes-cards-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
gap: 24px;
max-width: 1200px;
}
.quote-card {
border: 1px solid var(--border-color);
border-radius: 12px;
background: var(--white);
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
overflow: hidden;
transition: box-shadow 0.2s ease, border-color 0.2s ease;
}
.quote-card:hover {
border-color: rgba(14, 165, 233, 0.4);
box-shadow: 0 4px 16px rgba(14, 165, 233, 0.12);
}
.quote-card.expanded {
border-color: var(--brand-primary, #0ea5e9);
box-shadow: 0 4px 20px rgba(14, 165, 233, 0.15);
}
.quote-card-header {
display: flex;
align-items: center;
gap: 16px;
padding: 20px 24px;
cursor: pointer;
background: linear-gradient(to right, rgba(224, 242, 254, 0.6), rgba(186, 230, 253, 0.4));
}
.quote-card-icon {
font-size: 32px;
line-height: 1;
}
.quote-card-title-wrap {
flex: 1;
}
.quote-card-title-wrap h3 {
margin: 0 0 4px 0;
font-size: 18px;
font-weight: 600;
color: var(--brand-text-default);
}
.quote-card-title-wrap p {
margin: 0;
font-size: 13px;
color: var(--text-color);
}
.quote-card-arrow {
font-size: 14px;
color: var(--text-color);
}
.quote-card-body {
padding: 24px;
border-top: 1px solid var(--border-color);
}
.quote-form .form-group input[type="email"],
.quote-form .form-group input[type="tel"],
.quote-form .form-group input[type="number"],
.quote-form .form-group select {
width: 100%;
padding: 10px 12px;
font-size: 14px;
border: 1px solid var(--border-color);
border-radius: 8px;
box-sizing: border-box;
}
.quote-form .required {
color: #e11d48;
}
.captcha-row {
display: flex;
align-items: center;
gap: 12px;
}
.captcha-row input {
width: 120px !important;
max-width: 120px;
}
.captcha-code {
padding: 8px 16px;
font-size: 18px;
font-weight: 600;
letter-spacing: 4px;
background: #f0f0f0;
border-radius: 6px;
color: var(--brand-text-default);
}
.btn-captcha-refresh {
padding: 8px 12px;
font-size: 13px;
border: 1px solid var(--border-color);
border-radius: 6px;
background: var(--white);
color: var(--text-color);
cursor: pointer;
}
.btn-captcha-refresh:hover {
background: var(--bg-color, #f5f5f5);
}
.privacy-commitment {
margin: 20px 0 16px 0;
padding: 14px 16px;
background: rgba(14, 165, 233, 0.06);
border: 1px solid rgba(14, 165, 233, 0.2);
border-radius: 8px;
}
.privacy-checkbox-label {
display: flex;
align-items: flex-start;
gap: 10px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
color: var(--text-color);
margin-bottom: 10px;
}
.privacy-checkbox-label input {
margin: 3px 0 0 0;
flex-shrink: 0;
}
.privacy-commitment p {
margin: 0;
font-size: 12px;
line-height: 1.6;
color: var(--text-color);
}
.privacy-commitment a {
color: var(--brand-primary, #0ea5e9);
text-decoration: none;
}
.privacy-commitment a:hover {
text-decoration: underline;
}
.section-project-quotes .container { .section-project-quotes .container {
max-width: 900px; max-width: 900px;
} }

View File

@ -7,6 +7,9 @@ import { useAuthStore } from '@/stores/auth'
// 页面组件 // 页面组件
import Home from '@/views/Home.vue' import Home from '@/views/Home.vue'
import AboutOverview from '@/views/AboutOverview.vue' import AboutOverview from '@/views/AboutOverview.vue'
import AboutInsurers from '@/views/AboutInsurers.vue'
import AboutBrokers from '@/views/AboutBrokers.vue'
import AboutThirdParty from '@/views/AboutThirdParty.vue'
import RiskDutiesOverview from '@/views/RiskDutiesOverview.vue' import RiskDutiesOverview from '@/views/RiskDutiesOverview.vue'
import Sponsor from '@/views/Sponsor.vue' import Sponsor from '@/views/Sponsor.vue'
import Holder from '@/views/Holder.vue' import Holder from '@/views/Holder.vue'
@ -16,6 +19,7 @@ import Participant from '@/views/Participant.vue'
import SolutionsPharmacovigilance from '@/views/SolutionsPharmacovigilance.vue' import SolutionsPharmacovigilance from '@/views/SolutionsPharmacovigilance.vue'
import SolutionsClinicalInsurance from '@/views/SolutionsClinicalInsurance.vue' import SolutionsClinicalInsurance from '@/views/SolutionsClinicalInsurance.vue'
import SolutionsProductInsurance from '@/views/SolutionsProductInsurance.vue' import SolutionsProductInsurance from '@/views/SolutionsProductInsurance.vue'
import SolutionsFundPayment from '@/views/SolutionsFundPayment.vue'
import SmartAcquisition from '@/views/SmartAcquisition.vue' import SmartAcquisition from '@/views/SmartAcquisition.vue'
import PVReport from '@/views/PVReport.vue' import PVReport from '@/views/PVReport.vue'
import DrugSafetyDict from '@/views/DrugSafetyDict.vue' import DrugSafetyDict from '@/views/DrugSafetyDict.vue'
@ -27,6 +31,7 @@ import KnowledgePvInsurance from '@/views/KnowledgePvInsurance.vue'
import ResourceCenter from '@/views/ResourceCenter.vue' import ResourceCenter from '@/views/ResourceCenter.vue'
import Overseas from '@/views/Overseas.vue' import Overseas from '@/views/Overseas.vue'
import FAQ from '@/views/FAQ.vue' import FAQ from '@/views/FAQ.vue'
import LearningCenter from '@/views/LearningCenter.vue'
import Contact from '@/views/Contact.vue' import Contact from '@/views/Contact.vue'
import PrivacyPolicy from '@/views/PrivacyPolicy.vue' import PrivacyPolicy from '@/views/PrivacyPolicy.vue'
import Login from '@/views/Login.vue' import Login from '@/views/Login.vue'
@ -56,6 +61,9 @@ const router = createRouter({
children: [ children: [
{ path: '', component: Home }, { path: '', component: Home },
{ path: 'about/overview', component: AboutOverview }, { path: 'about/overview', component: AboutOverview },
{ path: 'about/insurers', component: AboutInsurers },
{ path: 'about/brokers', component: AboutBrokers },
{ path: 'about/third-party', component: AboutThirdParty },
{ path: 'concern', component: RiskDutiesOverview }, { path: 'concern', component: RiskDutiesOverview },
{ path: 'sponsor', component: Sponsor }, { path: 'sponsor', component: Sponsor },
{ path: 'holder', component: Holder }, { path: 'holder', component: Holder },
@ -65,6 +73,7 @@ const router = createRouter({
{ path: 'solutions/pharmacovigilance', component: SolutionsPharmacovigilance }, { path: 'solutions/pharmacovigilance', component: SolutionsPharmacovigilance },
{ path: 'solutions/clinical-insurance', component: SolutionsClinicalInsurance }, { path: 'solutions/clinical-insurance', component: SolutionsClinicalInsurance },
{ path: 'solutions/product-insurance', component: SolutionsProductInsurance }, { path: 'solutions/product-insurance', component: SolutionsProductInsurance },
{ path: 'solutions/fund-payment', component: SolutionsFundPayment },
{ path: 'risk-data/smart-acquisition', component: SmartAcquisition }, { path: 'risk-data/smart-acquisition', component: SmartAcquisition },
{ path: 'risk-data/pv-report', component: PVReport }, { path: 'risk-data/pv-report', component: PVReport },
{ path: 'risk-data/drug-safety-dict', component: DrugSafetyDict }, { path: 'risk-data/drug-safety-dict', component: DrugSafetyDict },
@ -78,14 +87,25 @@ const router = createRouter({
{ path: 'post-market/insurance', component: PostMarket }, { path: 'post-market/insurance', component: PostMarket },
{ path: 'post-market/guarantee', component: PostMarket }, { path: 'post-market/guarantee', component: PostMarket },
{ path: 'knowledge/regulations', component: KnowledgeRegulations }, { path: 'knowledge/regulations', component: KnowledgeRegulations },
{ path: 'knowledge/ai-app', component: SmartAcquisition },
{ path: 'knowledge/insurance', component: KnowledgeInsurance }, { path: 'knowledge/insurance', component: KnowledgeInsurance },
{ path: 'knowledge/insurance/regulations', component: KnowledgeRegulations },
{ path: 'knowledge/insurance/overseas', component: Overseas },
{ path: 'knowledge/insurance/group-standard', component: KnowledgeInsurance },
{ path: 'knowledge/pv-insurance', component: KnowledgePvInsurance }, { path: 'knowledge/pv-insurance', component: KnowledgePvInsurance },
{ path: 'knowledge/learning-center', component: LearningCenter },
{ path: 'knowledge/learning-center/cases', component: LearningCenter },
{ path: 'knowledge/learning-center/videos', component: LearningCenter },
{ path: 'knowledge/learning-center/exam', component: LearningCenter },
{ path: 'system-management', component: ResourceCenter }, { path: 'system-management', component: ResourceCenter },
{ path: 'system-management/laws', component: ResourceCenter }, { path: 'system-management/laws', component: ResourceCenter },
{ path: 'system-management/practice-guide', component: ResourceCenter }, { path: 'system-management/practice-guide', component: ResourceCenter },
{ path: 'system-management/training', component: ResourceCenter }, { path: 'system-management/training', component: ResourceCenter },
{ path: 'system-management/faq', component: FAQ }, { path: 'system-management/faq', component: FAQ },
{ path: 'faq', component: FAQ }, { path: 'faq', component: FAQ },
{ path: 'faq/duty-logic', component: FAQ },
{ path: 'faq/coverage', component: FAQ },
{ path: 'faq/pv-insurance', component: FAQ },
{ path: 'contact', component: Contact }, { path: 'contact', component: Contact },
{ path: 'privacy-policy', component: PrivacyPolicy }, { path: 'privacy-policy', component: PrivacyPolicy },
{ path: 'overseas', component: Overseas }, { path: 'overseas', component: Overseas },

View File

@ -0,0 +1,34 @@
<template>
<PageContainer>
<div class="about-page">
<PageHeader title="专家经纪" description="专业保险经纪团队" />
<div class="page-body">
<section class="section">
<div class="container">
<h2 class="section-title">专家经纪</h2>
<p class="section-desc">RMO拥有经验丰富的保险经纪专家团队为申办方持有人等提供专业的保险方案设计与风险管理建议</p>
<div class="content-grid">
<div class="content-card">
<h3>专业能力</h3>
<p>深入了解生命科学行业特点结合法规要求提供定制化保险方案</p>
</div>
<div class="content-card">
<h3>全流程服务</h3>
<p>从方案设计投保协助到理赔支持提供一站式经纪服务</p>
</div>
</div>
</div>
</section>
</div>
</div>
</PageContainer>
</template>
<script setup lang="ts">
import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue'
</script>
<style scoped>
@import '@/pages/AboutOverview.css';
</style>

View File

@ -0,0 +1,34 @@
<template>
<PageContainer>
<div class="about-page">
<PageHeader title="合作保司" description="RMO生态合作保险公司" />
<div class="page-body">
<section class="section">
<div class="container">
<h2 class="section-title">合作保司</h2>
<p class="section-desc">RMO与多家知名保险公司建立战略合作为生命科学行业提供专业可靠的保险保障服务</p>
<div class="content-grid">
<div class="content-card">
<h3>合作优势</h3>
<p>精选行业领先的保险机构确保保障方案的专业性与可靠性</p>
</div>
<div class="content-card">
<h3>服务保障</h3>
<p>合作保司承诺高效理赔优质服务为临床试验与上市后产品提供全面保障</p>
</div>
</div>
</div>
</section>
</div>
</div>
</PageContainer>
</template>
<script setup lang="ts">
import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue'
</script>
<style scoped>
@import '@/pages/AboutOverview.css';
</style>

View File

@ -0,0 +1,34 @@
<template>
<PageContainer>
<div class="about-page">
<PageHeader title="第三方机构" description="RMO生态合作第三方服务机构" />
<div class="page-body">
<section class="section">
<div class="container">
<h2 class="section-title">第三方机构</h2>
<p class="section-desc">RMO与多家第三方服务机构建立合作关系共同为生命科学行业提供药物警戒临床研究数据处理等专业服务</p>
<div class="content-grid">
<div class="content-card">
<h3>合作范围</h3>
<p>涵盖CROSMO数据管理法规咨询等领域的优质第三方服务机构</p>
</div>
<div class="content-card">
<h3>质量保障</h3>
<p>严格筛选合作机构确保服务质量和合规性为项目保驾护航</p>
</div>
</div>
</div>
</section>
</div>
</div>
</PageContainer>
</template>
<script setup lang="ts">
import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue'
</script>
<style scoped>
@import '@/pages/AboutOverview.css';
</style>

View File

@ -18,38 +18,17 @@
> >
<div v-if="i === 0" class="hero-content"> <div v-if="i === 0" class="hero-content">
<h1 class="hero-title">赋能生命科学风险管理</h1> <h1 class="hero-title">赋能生命科学风险管理</h1>
<p class="hero-subtitle">为临床试验和上市后药物安全提供全方位的风险管理解决方案</p> <p class="hero-subtitle">患者安全始终第一</p>
<div class="hero-buttons"> <div class="hero-buttons">
<RouterLink to="/about/overview" class="btn btn-primary">了解更多</RouterLink> <RouterLink to="/about/overview" class="btn btn-primary">了解更多</RouterLink>
<button type="button" class="btn btn-secondary" @click="quoteModal.openQuoteModal">获取报价</button> <button type="button" class="btn btn-secondary" @click="handleGetQuote">获取报价</button>
</div>
<div class="hero-scroll-hint">
<span>向下滚动</span>
<div class="scroll-arrow"></div>
</div> </div>
</div> </div>
<div v-else class="section-content"> <div v-else class="section-content">
<h2 class="section-title">{{ section.title }}</h2> <h2 v-if="section.title" class="section-title">{{ section.title }}</h2>
<p v-if="section.subtitle" class="section-subtitle">{{ section.subtitle }}</p> <p v-if="section.subtitle" class="section-subtitle">{{ section.subtitle }}</p>
<div v-if="i === 1" class="solutions-grid"> <div v-if="i === 1" class="rmo-solution-wrapper">
<RouterLink to="/solutions/pharmacovigilance" class="solution-card"> <RmoValueProposition />
<div class="solution-icon">📊</div>
<h3>药物警戒</h3>
<p>系统化的数据收集监测和分析识别潜在风险信号</p>
<span class="solution-link">了解更多 </span>
</RouterLink>
<RouterLink to="/solutions/clinical-insurance" class="solution-card">
<div class="solution-icon">🛡</div>
<h3>临床保险</h3>
<p>为临床试验提供全面的保险保障服务</p>
<span class="solution-link">了解更多 </span>
</RouterLink>
<RouterLink to="/solutions/product-insurance" class="solution-card">
<div class="solution-icon">💼</div>
<h3>产品保险</h3>
<p>上市后药物安全与风险管理保障</p>
<span class="solution-link">了解更多 </span>
</RouterLink>
</div> </div>
<div v-else-if="i === 2" class="capabilities-grid"> <div v-else-if="i === 2" class="capabilities-grid">
<div v-for="item in capabilities" :key="item.label" class="capability-item"> <div v-for="item in capabilities" :key="item.label" class="capability-item">
@ -86,9 +65,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from 'vue' import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { useQuoteModalStore } from '@/stores/quoteModal' import { useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import RmoValueProposition from '@/components/RmoValueProposition.vue'
const quoteModal = useQuoteModalStore() const router = useRouter()
const auth = useAuthStore()
function handleGetQuote() {
if (!auth.isAuthenticated) {
if (window.confirm('获取报价需先登录,是否前往登录?')) {
router.push({ path: '/login', query: { from: '/dashboard/project-quotes' } })
}
return
}
router.push('/dashboard/project-quotes')
}
const currentSection = ref(0) const currentSection = ref(0)
const sectionsRef = ref<(HTMLElement | null)[]>([]) const sectionsRef = ref<(HTMLElement | null)[]>([])
let observer: IntersectionObserver | null = null let observer: IntersectionObserver | null = null
@ -103,7 +95,7 @@ const heroStyle = {
const sections = [ const sections = [
{ class: 'hero-section', title: '', subtitle: '' }, { class: 'hero-section', title: '', subtitle: '' },
{ class: 'solutions-section', title: '一体化风险管理解决方案', subtitle: '提供全流程研发服务与解决方案' }, { class: 'solutions-section', title: '', subtitle: '' },
{ class: 'capabilities-section', title: '核心能力', subtitle: '' }, { class: 'capabilities-section', title: '核心能力', subtitle: '' },
{ class: 'knowledge-section', title: '知识资源', subtitle: '分享我们的行业洞见和研发咨询' }, { class: 'knowledge-section', title: '知识资源', subtitle: '分享我们的行业洞见和研发咨询' },
{ class: 'contact-section', title: '联系我们', subtitle: '获取RMO最新资讯第一时间了解我们的企业动态' } { class: 'contact-section', title: '联系我们', subtitle: '获取RMO最新资讯第一时间了解我们的企业动态' }

View File

@ -0,0 +1,74 @@
<template>
<PageContainer>
<div class="learning-center-page">
<PageHeader :title="pageTitle" :description="pageDescription" />
<div class="page-body">
<section class="section">
<div class="container">
<div class="learning-content">
<p class="placeholder-text">{{ placeholderText }}</p>
</div>
</div>
</section>
</div>
</div>
</PageContainer>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue'
const route = useRoute()
const pageConfig: Record<string, { title: string; description: string; placeholder: string }> = {
'index': {
title: '学习中心',
description: '案例学习、培训视频与考试中心',
placeholder: '请从左侧菜单选择案例学习、培训视频或考试中心。'
},
'cases': {
title: '案例学习',
description: '通过真实案例掌握药物警戒与保险风险管理',
placeholder: '案例学习内容建设中,敬请期待。'
},
'videos': {
title: '培训视频',
description: '系统化培训视频,助力专业能力提升',
placeholder: '培训视频内容建设中,敬请期待。'
},
'exam': {
title: '考试中心',
description: '在线测评与认证考试',
placeholder: '考试中心功能建设中,敬请期待。'
}
}
const currentKey = computed(() => {
const path = route.path
if (path.endsWith('/cases')) return 'cases'
if (path.endsWith('/videos')) return 'videos'
if (path.endsWith('/exam')) return 'exam'
return 'index'
})
const pageTitle = computed(() => pageConfig[currentKey.value]?.title ?? '学习中心')
const pageDescription = computed(() => pageConfig[currentKey.value]?.description ?? '')
const placeholderText = computed(() => pageConfig[currentKey.value]?.placeholder ?? '内容建设中,敬请期待。')
</script>
<style scoped>
.learning-center-page {
min-height: 60vh;
}
.learning-content {
padding: 2rem 0;
}
.placeholder-text {
color: var(--text-secondary, #666);
text-align: center;
font-size: 1rem;
}
</style>

View File

@ -11,7 +11,7 @@
填写项目方案编号项目标题申办者项目分期可手动填写或上传项目方案由 AI 识别生成报价后可向各保司获取精准报价 填写项目方案编号项目标题申办者项目分期可手动填写或上传项目方案由 AI 识别生成报价后可向各保司获取精准报价
</p> </p>
<div class="get-quotes-actions"> <div class="get-quotes-actions">
<button type="button" class="btn btn-primary get-quotes-btn" @click="quoteModal.openQuoteModal"> <button type="button" class="btn btn-primary get-quotes-btn" @click="handleGetQuote">
获取报价 获取报价
</button> </button>
<button <button
@ -30,7 +30,7 @@
<div class="container"> <div class="container">
<div class="card main-card"> <div class="card main-card">
<h2>保险方案</h2> <h2>保险方案</h2>
<p>基础保障全面保障保险团体标准核心内容等</p> <p>基础保障全面保障保险条款标准核心内容等</p>
</div> </div>
</div> </div>
</section> </section>
@ -42,13 +42,21 @@
<script setup lang="ts"> <script setup lang="ts">
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth' import { useAuthStore } from '@/stores/auth'
import { useQuoteModalStore } from '@/stores/quoteModal'
import PageContainer from '@/components/PageContainer.vue' import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue' import PageHeader from '@/components/PageHeader.vue'
const router = useRouter() const router = useRouter()
const auth = useAuthStore() const auth = useAuthStore()
const quoteModal = useQuoteModalStore()
function handleGetQuote() {
if (!auth.isAuthenticated) {
if (window.confirm('获取报价需先登录,是否前往登录?')) {
router.push({ path: '/login', query: { from: '/dashboard/project-quotes' } })
}
return
}
router.push('/dashboard/project-quotes')
}
</script> </script>
<style scoped> <style scoped>

View File

@ -0,0 +1,172 @@
<template>
<PageContainer>
<div class="solutions-fund-payment-page">
<PageHeader title="基金支付" description="华泰经纪直接支付医疗费用业务" />
<div class="page-body">
<section class="section">
<div class="container">
<div class="fund-payment-intro card main-card">
<h2>华泰经纪直接支付医疗费用</h2>
<p class="intro-desc">
华泰经纪作为专业的保险经纪公司提供直接支付医疗费用基金支付服务
当受试者或患者发生保险责任范围内的医疗费用时华泰经纪可先行垫付相关费用
有效减轻患者及申办方的资金压力提升理赔体验与保障效率
</p>
<div class="intro-features">
<div class="feature-item">
<span class="feature-icon"></span>
<span>快速垫付缓解资金压力</span>
</div>
<div class="feature-item">
<span class="feature-icon">🏥</span>
<span>医疗费用直付简化流程</span>
</div>
<div class="feature-item">
<span class="feature-icon">🤝</span>
<span>专业服务保障患者权益</span>
</div>
</div>
</div>
<div class="related-links card main-card">
<h3>相关业务</h3>
<p>了解更多保障与保险业务请访问以下页面</p>
<div class="links-grid">
<RouterLink to="/rmo-mode/guarantee" class="related-link-card">
<span class="link-icon">🛡</span>
<span class="link-title">临床试验保证业务</span>
<span class="link-desc">了解临床试验保证方案设计</span>
<span class="link-arrow"></span>
</RouterLink>
<RouterLink to="/post-market/guarantee" class="related-link-card">
<span class="link-icon">💼</span>
<span class="link-title">上市后保险保证业务</span>
<span class="link-desc">了解上市后保险与保证方案</span>
<span class="link-arrow"></span>
</RouterLink>
</div>
</div>
</div>
</section>
</div>
</div>
</PageContainer>
</template>
<script setup lang="ts">
import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue'
</script>
<style scoped>
.solutions-fund-payment-page {
min-height: 100%;
}
.fund-payment-intro {
padding: 32px;
margin-bottom: 24px;
}
.fund-payment-intro h2 {
font-size: 24px;
font-weight: 600;
margin: 0 0 20px 0;
color: var(--brand-text-default);
}
.intro-desc {
font-size: 16px;
line-height: 1.8;
color: var(--text-color);
margin: 0 0 24px 0;
}
.intro-features {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.feature-item {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 20px;
background: rgba(14, 165, 233, 0.08);
border-radius: 8px;
font-size: 15px;
color: var(--text-color);
}
.feature-icon {
font-size: 20px;
}
.related-links {
padding: 32px;
}
.related-links h3 {
font-size: 20px;
font-weight: 600;
margin: 0 0 12px 0;
color: var(--brand-text-default);
}
.related-links p {
font-size: 14px;
color: var(--text-color);
margin: 0 0 24px 0;
}
.links-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 20px;
}
.related-link-card {
display: flex;
flex-direction: column;
gap: 8px;
padding: 24px;
border: 1px solid var(--border-color);
border-radius: 12px;
background: var(--white);
text-decoration: none;
color: inherit;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.related-link-card:hover {
border-color: var(--brand-primary, #0ea5e9);
box-shadow: 0 4px 16px rgba(14, 165, 233, 0.15);
}
.link-icon {
font-size: 32px;
}
.link-title {
font-size: 18px;
font-weight: 600;
color: var(--brand-text-default);
}
.link-desc {
font-size: 14px;
color: var(--text-color);
}
.link-arrow {
margin-top: auto;
font-size: 18px;
color: var(--brand-primary, #0ea5e9);
}
@media (max-width: 768px) {
.links-grid {
grid-template-columns: 1fr;
}
}
</style>

View File

@ -39,11 +39,11 @@
<div class="container"> <div class="container">
<h2 class="section-title">快捷方式</h2> <h2 class="section-title">快捷方式</h2>
<div class="quick-actions"> <div class="quick-actions">
<button type="button" class="quick-action-card quick-action-button" @click="quoteModal.openQuoteModal"> <RouterLink to="/dashboard/project-quotes" class="quick-action-card quick-action-button">
<div class="action-icon">💼</div> <div class="action-icon">💼</div>
<h3>获取报价</h3> <h3>获取报价</h3>
<p>填写资料生成报价获取精准报价</p> <p>PV报价临床试验保险产品责任保险</p>
</button> </RouterLink>
<RouterLink to="/dashboard/project-quotes" class="quick-action-card"> <RouterLink to="/dashboard/project-quotes" class="quick-action-card">
<div class="action-icon">📋</div> <div class="action-icon">📋</div>
<h3>报价页面</h3> <h3>报价页面</h3>
@ -102,12 +102,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useAuthStore } from '@/stores/auth' import { useAuthStore } from '@/stores/auth'
import { useQuoteModalStore } from '@/stores/quoteModal'
import PageContainer from '@/components/PageContainer.vue' import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue' import PageHeader from '@/components/PageHeader.vue'
const auth = useAuthStore() const auth = useAuthStore()
const quoteModal = useQuoteModalStore()
const isPolicyholder = computed(() => auth.user?.role === '投保人') const isPolicyholder = computed(() => auth.user?.role === '投保人')
const isInsurer = computed(() => auth.user?.role === '保险人') const isInsurer = computed(() => auth.user?.role === '保险人')

View File

@ -38,7 +38,14 @@
<label for="premium-duration">试验周期</label> <label for="premium-duration">试验周期</label>
<input id="premium-duration" v-model="formData.duration" type="number" placeholder="请输入试验周期" required /> <input id="premium-duration" v-model="formData.duration" type="number" placeholder="请输入试验周期" required />
</div> </div>
<button type="submit" class="btn btn-primary">计算保费</button> <div class="privacy-commitment">
<label class="privacy-checkbox-label">
<input type="checkbox" v-model="privacyAgreed" required />
<span>我已阅读并理解该承诺声明</span>
</label>
<p>达诺/华泰经纪及RMO生态成员承诺对您在本网页下提供的任何信息包括您的个人信息将按照相关的法律法规及泰格医药隐私政策的规定进行严格保密更多信息详见<RouterLink to="/privacy-policy" target="_blank">隐私政策</RouterLink></p>
</div>
<button type="submit" class="btn btn-primary" :disabled="!privacyAgreed">计算保费</button>
</form> </form>
<div v-if="result !== null" class="calculator-result"> <div v-if="result !== null" class="calculator-result">
<h3>预估保费{{ result }} </h3> <h3>预估保费{{ result }} </h3>
@ -65,6 +72,7 @@ const formData = ref({
}) })
const result = ref<number | null>(null) const result = ref<number | null>(null)
const privacyAgreed = ref(false)
function handleSubmit() { function handleSubmit() {
result.value = Math.floor(Math.random() * 500000) + 100000 result.value = Math.floor(Math.random() * 500000) + 100000

View File

@ -1,13 +1,192 @@
<template> <template>
<PageContainer> <PageContainer>
<div class="project-quotes-page"> <div class="project-quotes-page">
<PageHeader title="项目报价" description="查看各保司报价" /> <PageHeader title="项目报价" description="选择报价类型并填写表单获取报价" />
<div class="page-body"> <div class="page-body">
<section class="section"> <section class="section">
<div class="container"> <div class="quotes-cards-grid">
<div class="card main-card"> <!-- PV报价卡片 -->
<h2>项目报价</h2> <div class="quote-card" :class="{ expanded: expandedCard === 'pv' }">
<p>各保司报价与询价记录</p> <div class="quote-card-header" @click="toggleCard('pv')">
<div class="quote-card-icon">📊</div>
<div class="quote-card-title-wrap">
<h3>PV报价</h3>
<p>药物警戒服务报价咨询</p>
</div>
<span class="quote-card-arrow">{{ expandedCard === 'pv' ? '▼' : '▶' }}</span>
</div>
<div v-show="expandedCard === 'pv'" class="quote-card-body">
<form class="quote-form" @submit.prevent="handlePvSubmit">
<div class="form-group">
<label for="pv-name">姓名 <span class="required">*</span></label>
<input id="pv-name" v-model="pvForm.name" type="text" placeholder="请输入姓名" required />
</div>
<div class="form-row">
<div class="form-group">
<label for="pv-email">电子邮箱 <span class="required">*</span></label>
<input id="pv-email" v-model="pvForm.email" type="email" placeholder="请输入电子邮箱" required />
</div>
<div class="form-group">
<label for="pv-phone">联系电话 <span class="required">*</span></label>
<input id="pv-phone" v-model="pvForm.phone" type="tel" placeholder="请输入联系电话" required />
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="pv-company">公司 <span class="required">*</span></label>
<input id="pv-company" v-model="pvForm.company" type="text" placeholder="请输入公司名称" required />
</div>
<div class="form-group">
<label for="pv-position">职位</label>
<input id="pv-position" v-model="pvForm.position" type="text" placeholder="请输入职位" />
</div>
</div>
<div class="form-group">
<label for="pv-question">业务相关问题 <span class="required">*</span></label>
<textarea id="pv-question" v-model="pvForm.question" placeholder="请描述您的业务问题或需求" rows="4" required></textarea>
</div>
<div class="form-group">
<label for="pv-captcha">验证码 <span class="required">*</span></label>
<div class="captcha-row">
<input id="pv-captcha" v-model="pvForm.captcha" type="text" placeholder="请输入验证码" maxlength="4" required />
<span class="captcha-code">{{ captchaCode }}</span>
<button type="button" class="btn-captcha-refresh" @click="refreshCaptcha">刷新</button>
</div>
</div>
<div class="privacy-commitment">
<label class="privacy-checkbox-label">
<input type="checkbox" v-model="pvPrivacyAgreed" required />
<span>我已阅读并理解该承诺声明</span>
</label>
<p>达诺/华泰经纪及RMO生态成员承诺对您在本网页下提供的任何信息包括您的个人信息将按照相关的法律法规及泰格医药隐私政策的规定进行严格保密更多信息详见<RouterLink to="/privacy-policy" target="_blank">隐私政策</RouterLink></p>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary" :disabled="pvSubmitting || !pvPrivacyAgreed">
{{ pvSubmitting ? '提交中...' : '提交' }}
</button>
</div>
</form>
</div>
</div>
<!-- 临床试验保险报价卡片 -->
<div class="quote-card" :class="{ expanded: expandedCard === 'clinical' }">
<div class="quote-card-header" @click="toggleCard('clinical')">
<div class="quote-card-icon">🛡</div>
<div class="quote-card-title-wrap">
<h3>临床试验保险报价</h3>
<p>临床试验责任保险报价咨询</p>
</div>
<span class="quote-card-arrow">{{ expandedCard === 'clinical' ? '▼' : '▶' }}</span>
</div>
<div v-show="expandedCard === 'clinical'" class="quote-card-body">
<form class="quote-form" @submit.prevent="handleClinicalSubmit">
<div class="form-group">
<label for="clinical-projectType">项目类型</label>
<select id="clinical-projectType" v-model="clinicalForm.projectType">
<option value="">请选择</option>
<option value="phase1">I期临床试验</option>
<option value="phase2">II期临床试验</option>
<option value="phase3">III期临床试验</option>
<option value="phase4">IV期临床试验</option>
</select>
</div>
<div class="form-group">
<label for="clinical-riskLevel">风险等级</label>
<select id="clinical-riskLevel" v-model="clinicalForm.riskLevel">
<option value="">请选择</option>
<option value="low">低风险</option>
<option value="medium">中风险</option>
<option value="high">高风险</option>
</select>
</div>
<div class="form-row">
<div class="form-group">
<label for="clinical-coverage">保障金额</label>
<input id="clinical-coverage" v-model="clinicalForm.coverageAmount" type="number" placeholder="请输入保障金额" />
</div>
<div class="form-group">
<label for="clinical-participants">受试者人数</label>
<input id="clinical-participants" v-model="clinicalForm.participantCount" type="number" placeholder="请输入受试者人数" />
</div>
</div>
<div class="form-group">
<label for="clinical-duration">试验周期</label>
<input id="clinical-duration" v-model="clinicalForm.duration" type="number" placeholder="请输入试验周期" />
</div>
<div class="form-group">
<label for="clinical-remark">备注说明</label>
<textarea id="clinical-remark" v-model="clinicalForm.remark" placeholder="请输入其他需求说明" rows="3"></textarea>
</div>
<div class="privacy-commitment">
<label class="privacy-checkbox-label">
<input type="checkbox" v-model="clinicalPrivacyAgreed" required />
<span>我已阅读并理解该承诺声明</span>
</label>
<p>达诺/华泰经纪及RMO生态成员承诺对您在本网页下提供的任何信息包括您的个人信息将按照相关的法律法规及泰格医药隐私政策的规定进行严格保密更多信息详见<RouterLink to="/privacy-policy" target="_blank">隐私政策</RouterLink></p>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary" :disabled="clinicalSubmitting || !clinicalPrivacyAgreed">
{{ clinicalSubmitting ? '提交中...' : '提交' }}
</button>
</div>
</form>
</div>
</div>
<!-- 产品责任保险报价卡片 -->
<div class="quote-card" :class="{ expanded: expandedCard === 'product' }">
<div class="quote-card-header" @click="toggleCard('product')">
<div class="quote-card-icon">💼</div>
<div class="quote-card-title-wrap">
<h3>产品责任保险报价</h3>
<p>上市后产品责任保险报价咨询</p>
</div>
<span class="quote-card-arrow">{{ expandedCard === 'product' ? '▼' : '▶' }}</span>
</div>
<div v-show="expandedCard === 'product'" class="quote-card-body">
<form class="quote-form" @submit.prevent="handleProductSubmit">
<div class="form-group">
<label for="product-productName">产品名称</label>
<input id="product-productName" v-model="productForm.productName" type="text" placeholder="请输入产品名称" />
</div>
<div class="form-group">
<label for="product-productType">产品类型</label>
<select id="product-productType" v-model="productForm.productType">
<option value="">请选择</option>
<option value="drug">药品</option>
<option value="device">医疗器械</option>
<option value="other">其他</option>
</select>
</div>
<div class="form-row">
<div class="form-group">
<label for="product-coverage">保障金额</label>
<input id="product-coverage" v-model="productForm.coverageAmount" type="number" placeholder="请输入保障金额" />
</div>
<div class="form-group">
<label for="product-sales">年销售额</label>
<input id="product-sales" v-model="productForm.annualSales" type="number" placeholder="请输入年销售额" />
</div>
</div>
<div class="form-group">
<label for="product-remark">备注说明</label>
<textarea id="product-remark" v-model="productForm.remark" placeholder="请输入其他需求说明" rows="3"></textarea>
</div>
<div class="privacy-commitment">
<label class="privacy-checkbox-label">
<input type="checkbox" v-model="productPrivacyAgreed" required />
<span>我已阅读并理解该承诺声明</span>
</label>
<p>达诺/华泰经纪及RMO生态成员承诺对您在本网页下提供的任何信息包括您的个人信息将按照相关的法律法规及泰格医药隐私政策的规定进行严格保密更多信息详见<RouterLink to="/privacy-policy" target="_blank">隐私政策</RouterLink></p>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary" :disabled="productSubmitting || !productPrivacyAgreed">
{{ productSubmitting ? '提交中...' : '提交' }}
</button>
</div>
</form>
</div>
</div> </div>
</div> </div>
</section> </section>
@ -17,8 +196,106 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'
import PageContainer from '@/components/PageContainer.vue' import PageContainer from '@/components/PageContainer.vue'
import PageHeader from '@/components/PageHeader.vue' import PageHeader from '@/components/PageHeader.vue'
type ExpandedCard = 'pv' | 'clinical' | 'product' | null
const expandedCard = ref<ExpandedCard>('pv')
const pvForm = ref({
name: '',
email: '',
phone: '',
company: '',
position: '',
question: '',
captcha: ''
})
const clinicalForm = ref({
projectType: '',
riskLevel: '',
coverageAmount: '',
participantCount: '',
duration: '',
remark: ''
})
const productForm = ref({
productName: '',
productType: '',
coverageAmount: '',
annualSales: '',
remark: ''
})
const captchaCode = ref('')
const pvPrivacyAgreed = ref(false)
const clinicalPrivacyAgreed = ref(false)
const productPrivacyAgreed = ref(false)
const pvSubmitting = ref(false)
const clinicalSubmitting = ref(false)
const productSubmitting = ref(false)
function generateCaptcha() {
captchaCode.value = Math.random().toString(36).slice(2, 6).toUpperCase()
}
function refreshCaptcha() {
generateCaptcha()
}
onMounted(() => {
generateCaptcha()
})
function toggleCard(card: ExpandedCard) {
expandedCard.value = expandedCard.value === card ? null : card
}
async function handlePvSubmit() {
if (pvForm.value.captcha.toUpperCase() !== captchaCode.value) {
alert('验证码错误,请重新输入')
refreshCaptcha()
return
}
pvSubmitting.value = true
try {
await new Promise(r => setTimeout(r, 800))
alert('PV报价提交成功我们会尽快与您联系。')
pvForm.value = { name: '', email: '', phone: '', company: '', position: '', question: '', captcha: '' }
pvPrivacyAgreed.value = false
refreshCaptcha()
} finally {
pvSubmitting.value = false
}
}
async function handleClinicalSubmit() {
clinicalSubmitting.value = true
try {
await new Promise(r => setTimeout(r, 800))
alert('临床试验保险报价提交成功!我们会尽快与您联系。')
clinicalForm.value = { projectType: '', riskLevel: '', coverageAmount: '', participantCount: '', duration: '', remark: '' }
clinicalPrivacyAgreed.value = false
} finally {
clinicalSubmitting.value = false
}
}
async function handleProductSubmit() {
productSubmitting.value = true
try {
await new Promise(r => setTimeout(r, 800))
alert('产品责任保险报价提交成功!我们会尽快与您联系。')
productForm.value = { productName: '', productType: '', coverageAmount: '', annualSales: '', remark: '' }
productPrivacyAgreed.value = false
} finally {
productSubmitting.value = false
}
}
</script> </script>
<style scoped> <style scoped>

View File

@ -6,12 +6,12 @@ RMORisk Management Organization, 是一个“一站式的、涉及到患者/
1.主页:-模式/理念/价值/团队 1.主页:-模式/理念/价值/团队
2.公司介绍:临研安 2.公司介绍:临研安
-活动:参加的行业研讨会、发布会、展会、培训会等 -活动:参加的行业研讨会、发布会、展会、培训会等
-资源:法律法规、团体标准、行业共识、视频 -资源:法律法规、条款标准、行业共识、视频
我们的服务(重点是可以提供给申办者的服务) 我们的服务(重点是可以提供给申办者的服务)
-自保(专项风险管理基金) -自保(专项风险管理基金)
-风险减量服务 -风险减量服务
-外溢风险管理服务 -外溢风险管理服务
-保险:保险合同审查、理赔审查。保险条款修订、理赔规则指定、团体标准。 -保险:保险合同审查、理赔审查。保险条款修订、理赔规则指定、条款标准。
3.申办方 3.申办方
风险管理 风险管理