在开发新项目中。我们面临一个具体场景:纯预览展示的协议文档需要动态填充用户数据。这些协议本身是静态HTML模板,但其中包含大量需要根据具体业务数据动态替换的字段,如客户姓名、贷款金额、银行信息等。
技术挑战
- 多环境适配:协议模板需要在开发、测试、生产不同环境中运行
- 数据安全:敏感数据(如银行卡号、身份证号)需要安全获取和展示
- 动态替换:协议中的占位符需要精准、高效地被实际数据替换
- 兼容性:方案需要支持多种浏览器环境和模块系统
解决方案架构
核心设计理念
我们设计了一个SignatureDataService类,作为数据获取和模板填充的核心服务。该方案采用以下关键设计:
- 环境智能判断:自动识别运行环境,配置对应的API端点
- 数据隔离存储:使用本地存储管理业务入口标识(entryCode)
- 模板引擎:轻量级占位符替换机制
- 单例模式:确保全局唯一的数据服务实例
环境配置策略
javascript
function getEnvConfig() {
const hostname = window.location.hostname;
const href = window.location.href;
// 开发环境
if (hostname === 'localhost') {
return {
apiBaseUrl: 'http://localhost:8080/api',
env: 'development'
};
}
// 测试环境
if (href.includes('.test.') || hostname.includes('test')) {
return {
apiBaseUrl: '测试环境地址',
env: 'testcloud'
};
}
// 生产环境
return {
apiBaseUrl: ' 生产环境地址',
env: 'prodcloud'
};
}
核心服务类
SignatureDataService类封装了完整的数据处理流程:
1. 数据获取
javascript
async fetchSignatureData() {
const entryCode = this.getEntryCode();
if (!entryCode) return null;
const apiUrl = `${this.config.apiBaseUrl}/signature/getSignatureParams`;
const response = await fetch(`${apiUrl}?entryCode=${encodeURIComponent(entryCode)}`);
// ... 处理响应
}
2. 模板填充
javascript
fillTemplate(data) {
if (!data) return;
let content = document.body.innerHTML;
const fields = {
'bankName': data.bankName || '',
'bankCardNo': data.bankCardNo || '',
// ... 其他30+字段
};
// 正则表达式替换所有${fieldName}占位符
Object.keys(fields).forEach(key => {
const placeholder = `${${key}}`;
const regex = new RegExp(
placeholder.replace(/$/g, '\$').replace(/{/g, '\{').replace(/}/g, '\}'),
'g'
);
content = content.replace(regex, this.escapeHtml(fields[key]));
});
document.body.innerHTML = content;
}
3. 安全防护
javascript
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
支持的数据字段
系统支持超过30个业务字段的自动填充,涵盖:
- 客户信息:customerName, cardNum, phoneNum
- 贷款信息:loanAmount, period, totalInterest
- 车辆信息:carModel, chassisNo, carColor
- 公司信息:companyName, companyUsci, companyAddress
- 金额相关:所有金额字段同时提供数字和中文大写形式
使用方式
1. HTML模板准备
协议模板中使用${fieldName}格式的占位符:
html
<div class="contract-section">
<p>甲方(借款人):${customerName}</p>
<p>身份证号:${cardNum}</p>
<p>贷款金额:${loanAmount}元(${loanAmountWord})</p>
</div>
2. 页面初始化
javascript
// 方式一:使用默认配置
const service = window.SignatureDataService.getSignatureService();
service.initPage();
// 方式二:自定义配置
const service = new window.SignatureDataService.SignatureDataService({
storageKey: 'customEntryCode'
});
service.initPage();
// 方式三:直接获取数据
const data = await window.SignatureDataService.fetchSignatureData();
技术优势
1. 无框架依赖
纯JavaScript实现,不依赖React、Vue等框架,适用于各种传统项目
2. 性能优化
- 单例模式减少内存开销
- 批量正则替换提升渲染效率
- 按需加载数据
3. 安全考虑
- HTML转义防止XSS攻击
- 敏感数据本地存储隔离
- HTTPS环境自动适配
4. 扩展性
- 模块化设计,易于添加新字段
- 支持CommonJS和浏览器全局两种导出方式
- 配置可覆盖,便于定制
5. 错误处理
完善的异常捕获机制:
javascript
try {
const data = await this.fetchSignatureData();
if (!data) {
console.error('数据加载失败,请稍后重试');
return false;
}
this.fillTemplate(data);
return true;
} catch (error) {
console.error('初始化失败:', error);
return false;
}