本文档详细说明 智能打标 系统如何实现与第三方系统的对接功能,包括路由配置、消息处理、数据验证等系统内部实现细节。
文件路径:/src/router/router-filter.js
配置内容:
const whiteList = ['/login', '/forgetPwd', '/about', '/externalPage'];
说明:将 /externalPage 添加到白名单,确保第三方系统可以直接访问该页面而不需要登录。
文件路径:/src/router/index.js
配置内容:
{
path: '/externalPage',
component: () => import('@/views/aiTagging/externalPage/index.vue'),
meta: {
title: '外部打标页面',
noCache: true
}
}
文件路径:/src/views/aiTagging/externalPage/index.vue
核心功能:
externalPageLoaded 消息externalParams 消息externalParamsReceived 确认消息初始化消息监听器:
mounted() {
// 监听来自第三方系统的消息
window.addEventListener('message', this.handleMessage);
// 页面加载完成后发送加载完成消息
this.sendPageLoadedMessage();
},
beforeDestroy() {
// 清理事件监听器
window.removeEventListener('message', this.handleMessage);
}
页面加载完成消息:
sendPageLoadedMessage() {
const message = {
type: 'externalPageLoaded',
loadedAt: Date.now(),
status: 'ready'
};
// 发送消息给父窗口(iframe 方式)
if (window.parent !== window) {
window.parent.postMessage(message, '*');
}
}
处理第三方系统消息:
handleMessage(event) {
const data = event.data;
if (data && data.type === 'externalParams') {
this.processExternalParams(data);
}
}
processExternalParams(params) {
// 验证必填字段
const missingFields = this.validateRequiredFields(params);
if (missingFields.length > 0) {
// 数据不完整,显示错误信息
this.loadingStatus = 'error';
this.errorMessage = '数据接收不完整,请检查缺失字段';
this.missingFields = missingFields;
this.receivedData = params;
} else {
// 数据完整,开始处理
this.loadingStatus = 'processing';
this.receivedData = params;
// 存储参数
this.businessAttr = params.business_attr;
this.userData = {
user_id: params.user_id,
user_nm: params.user_nm,
user_org: params.user_org || '',
user_endpoint: params.user_endpoint || '',
contract_no: params.contract_no || ''
};
// 发送确认消息
this.sendConfirmationMessage(params);
// 调用业务属性查询
this.queryBusinessAttr();
}
}
发送确认消息:
sendConfirmationMessage(originalData) {
const message = {
type: 'externalParamsReceived',
originalData: originalData,
receivedAt: Date.now(),
status: 'success'
};
// 发送消息给父窗口(iframe 方式)
if (window.parent !== window) {
window.parent.postMessage(message, '*');
}
}
验证函数:
validateRequiredFields(params) {
const missingFields = [];
if (!params.business_attr) {
missingFields.push('贷款申请编号');
}
if (!params.user_id) {
missingFields.push('用户ID');
}
if (!params.user_nm) {
missingFields.push('用户姓名');
}
if (!params.user_org) {
missingFields.push('所属机构');
}
if (!params.user_endpoint) {
missingFields.push('所属行社');
}
if (!params.contract_no) {
missingFields.push('合同编号');
}
return missingFields;
}
配置说明:API 请求不需要携带 token,需要设置 needToken: false
实现代码:
queryBusinessAttr() {
yufp.service.request({
url: backend.tagServer + "/api/fastapi/query",
method: 'POST',
data: {
businessAttr: this.businessAttr
},
needToken: false, // 确保设置为 false
callback: (code, error, response) => {
if (response.code == '0') {
// 处理成功响应
this.loadingStatus = 'success';
this.taggingData = response.data;
} else {
// 处理错误
this.loadingStatus = 'error';
this.errorMessage = response.message || '查询业务属性失败';
}
}
});
}
data() {
return {
// 加载状态:loading, success, error, idle
loadingStatus: 'idle',
// 错误信息
errorMessage: '',
// 缺失字段
missingFields: [],
// 接收到的数据
receivedData: {},
// 业务属性
businessAttr: '',
// 用户数据
userData: {},
// 打标数据
taggingData: {}
};
}
加载中:
<div v-if="loadingStatus === 'loading'" class="loading-container">
<el-icon class="is-loading"><loading /></el-icon>
<span>数据加载中...</span>
</div>
数据不完整:
<div v-else-if="loadingStatus === 'error'" class="error-container">
<el-alert
title="数据接收不完整"
type="error"
:closable="false"
show-icon
>
<div class="error-content">
<p>{{ errorMessage }}</p>
<div v-if="missingFields.length > 0" class="missing-fields">
<span class="missing-label">缺失字段:</span>
<el-tag v-for="field in missingFields" :key="field" type="danger" size="small">
{{ field }}
</el-tag>
</div>
<div v-if="Object.keys(receivedData).length > 0" class="received-data">
<span class="received-label">已接收数据:</span>
<pre>{{ JSON.stringify(receivedData, null, 2) }}</pre>
</div>
</div>
</el-alert>
</div>
加载成功:
<div v-else-if="loadingStatus === 'success'" class="success-container">
<!-- 打标结果展示 -->
<TaggingResult :tagging-data="taggingData" />
</div>
.external-page-container {
min-height: 100vh;
background-color: #f5f7fa;
display: flex;
flex-direction: column;
}
.content-wrapper {
flex: 1;
display: flex;
flex-direction: column;
padding: 20px;
}
.loading-container,
.error-container,
.success-container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 40px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
确保 iframe 内容可以滚动:
<iframe
src="http://your-domain.com/#/externalPage"
frameborder="0"
width="100%"
height="100%"
scrolling="auto"
></iframe>
// 渐进式超时机制
const timeouts = [5000, 10000, 15000];
let currentTimeoutIndex = 0;
function checkPageLoaded() {
if (pageLoaded) {
return;
}
if (currentTimeoutIndex < timeouts.length) {
setTimeout(() => {
if (!pageLoaded) {
showLoadingMessage(`页面加载中,已等待 ${timeouts[currentTimeoutIndex] / 1000} 秒...`);
currentTimeoutIndex++;
checkPageLoaded();
}
}, timeouts[currentTimeoutIndex]);
} else {
showErrorMessage('页面加载超时,请刷新重试');
}
}
handleMessage(event) {
try {
const data = event.data;
if (data && data.type === 'externalParams') {
this.processExternalParams(data);
}
} catch (error) {
console.error('处理消息时发生错误:', error);
this.loadingStatus = 'error';
this.errorMessage = '处理数据时发生错误';
}
}
// 验证消息来源
const trustedOrigins = ['https://trusted-third-party.com'];
window.addEventListener('message', (event) => {
// 验证消息来源
if (!trustedOrigins.includes(event.origin)) {
console.warn('来自未知来源的消息:', event.origin);
return;
}
// 处理消息
});
// 详细的日志记录
console.log('页面加载完成,发送消息:', message);
console.log('接收到第三方消息:', event.data);
console.log('消息来源:', event.origin);
console.log('数据验证结果:', missingFields);
if (process.env.NODE_ENV === 'development') {
console.log('开发模式:第三方对接功能');
// 模拟数据
setTimeout(() => {
this.processExternalParams({
type: 'externalParams',
business_attr: 'TEST2024001',
user_id: 'testuser001',
user_nm: '测试用户',
user_org: '测试机构',
user_endpoint: '测试分行',
contract_no: 'TESTCONTRACT001',
timestamp: Date.now(),
source: 'testSystem'
});
}, 1000);
}
系统设计考虑了向后兼容性,新增消息类型不会影响现有功能。
本文档最后更新:2026年3月17日