781 lines
38 KiB
HTML
781 lines
38 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>数据资产智能识别接口测试 - Finyx Data AI</title>
|
||
<link rel="stylesheet" href="test_common.css">
|
||
<style>
|
||
.field-tag {
|
||
display: inline-block;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
font-size: 11px;
|
||
margin-right: 4px;
|
||
margin-bottom: 4px;
|
||
}
|
||
.tag-pii { background-color: #ffebee; color: #d32f2f; }
|
||
.tag-important { background-color: #fff3e0; color: #f57c00; }
|
||
.confidence-bar {
|
||
height: 8px;
|
||
background-color: #e0e0e0;
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
margin-top: 4px;
|
||
}
|
||
.confidence-fill {
|
||
height: 100%;
|
||
border-radius: 4px;
|
||
transition: width 0.3s ease;
|
||
}
|
||
.confidence-high { background-color: #4caf50; }
|
||
.confidence-medium { background-color: #ff9800; }
|
||
.confidence-low { background-color: #f44336; }
|
||
|
||
.field-card {
|
||
border-left: 3px solid transparent;
|
||
padding-left: 12px;
|
||
margin-bottom: 12px;
|
||
}
|
||
.field-card.pii { border-left-color: #f44336; }
|
||
.field-card.important { border-left-color: #ff9800; }
|
||
|
||
.table-accordion {
|
||
border: 1px solid var(--border-color);
|
||
border-radius: var(--radius);
|
||
margin-bottom: 16px;
|
||
overflow: hidden;
|
||
}
|
||
.accordion-header {
|
||
background-color: var(--light-color);
|
||
padding: 16px;
|
||
cursor: pointer;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
transition: var(--transition);
|
||
}
|
||
.accordion-header:hover {
|
||
background-color: #e9ecef;
|
||
}
|
||
.accordion-header.active {
|
||
background-color: var(--primary-color);
|
||
color: var(--white);
|
||
}
|
||
.accordion-content {
|
||
display: none;
|
||
padding: 16px;
|
||
background-color: var(--white);
|
||
}
|
||
.accordion-content.active {
|
||
display: block;
|
||
}
|
||
.accordion-icon {
|
||
transition: transform 0.3s ease;
|
||
}
|
||
.accordion-header.active .accordion-icon {
|
||
transform: rotate(180deg);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<!-- 页面头部 -->
|
||
<header class="page-header">
|
||
<h1 class="page-title">🔍 数据资产智能识别接口测试</h1>
|
||
<p class="page-subtitle">
|
||
使用大模型识别数据资产的中文名称、业务含义、PII敏感信息和重要数据特征
|
||
</p>
|
||
</header>
|
||
|
||
<div class="content-grid">
|
||
<!-- 左侧:输入表单 -->
|
||
<div class="col-4">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">输入参数</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<form id="analyzeForm">
|
||
<div class="form-group">
|
||
<label class="form-label" for="projectId">项目ID *</label>
|
||
<input type="text" id="projectId" class="form-control" value="project_001" placeholder="输入项目ID">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="industry">行业信息</label>
|
||
<select id="industry" class="form-control">
|
||
<option value="">请选择行业</option>
|
||
<option value="retail-fresh" selected>零售生鲜</option>
|
||
<option value="retail-general">零售通用</option>
|
||
<option value="finance">金融</option>
|
||
<option value="healthcare">医疗健康</option>
|
||
<option value="logistics">物流</option>
|
||
<option value="manufacturing">制造业</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="context">业务背景信息</label>
|
||
<textarea id="context" class="form-control" rows="4" placeholder="描述业务背景、使用场景等">某连锁生鲜零售企业,主营水果、蔬菜等生鲜产品,拥有200+线下门店和线上电商平台</textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">大模型配置</label>
|
||
<div class="form-row">
|
||
<select id="model" class="form-control">
|
||
<option value="qwen-max" selected>通义千问 Max</option>
|
||
<option value="gpt-4">GPT-4</option>
|
||
</select>
|
||
<input type="number" id="temperature" class="form-control" value="0.3" min="0" max="1" step="0.1" title="温度参数">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">选项配置</label>
|
||
<div>
|
||
<label style="margin-right: 16px;">
|
||
<input type="checkbox" id="enablePII" checked> 启用PII识别
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" id="enableImportant" checked> 启用重要数据识别
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">快速使用虚拟数据</label>
|
||
<div class="btn-group">
|
||
<button type="button" class="btn btn-info btn-sm" onclick="loadMockData('retail')">零售场景</button>
|
||
<button type="button" class="btn btn-info btn-sm" onclick="loadMockData('finance')">金融场景</button>
|
||
<button type="button" class="btn btn-info btn-sm" onclick="loadMockData('user')">用户中心</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="btn-group" style="margin-top: 20px;">
|
||
<button type="submit" class="btn btn-primary">🚀 开始分析</button>
|
||
<button type="button" class="btn btn-outline" onclick="resetForm()">重置</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- API 调用信息 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">API 调用信息</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="form-group">
|
||
<label class="form-label">请求端点</label>
|
||
<code style="display: block; padding: 8px; background: var(--light-color); border-radius: var(--radius); font-size: 12px;">
|
||
POST /api/v1/inventory/ai-analyze
|
||
</code>
|
||
</div>
|
||
<div id="requestInfo" class="form-group">
|
||
<label class="form-label">请求数据</label>
|
||
<pre id="requestJson" style="max-height: 200px; overflow: auto; font-size: 11px; background: var(--light-color); padding: 8px; border-radius: var(--radius);">等待提交...</pre>
|
||
</div>
|
||
<div id="responseInfo" class="form-group" style="display: none;">
|
||
<label class="form-label">响应数据</label>
|
||
<pre id="responseJson" style="max-height: 300px; overflow: auto; font-size: 11px; background: var(--light-color); padding: 8px; border-radius: var(--radius);"></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧:结果展示 -->
|
||
<div class="col-8">
|
||
<!-- 加载状态 -->
|
||
<div id="loadingArea" style="display: none;"></div>
|
||
|
||
<!-- 结果区域 -->
|
||
<div id="resultArea" style="display: none;">
|
||
<!-- 统计信息 -->
|
||
<div class="stats-grid">
|
||
<div class="stat-card">
|
||
<div class="stat-label">总表数</div>
|
||
<div class="stat-value" id="statTables">0</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-label">总字段数</div>
|
||
<div class="stat-value" id="statFields">0</div>
|
||
</div>
|
||
<div class="stat-card danger">
|
||
<div class="stat-label">PII 字段数</div>
|
||
<div class="stat-value" id="statPII">0</div>
|
||
</div>
|
||
<div class="stat-card warning">
|
||
<div class="stat-label">重要数据字段</div>
|
||
<div class="stat-value" id="statImportant">0</div>
|
||
</div>
|
||
<div class="stat-card success">
|
||
<div class="stat-label">平均置信度</div>
|
||
<div class="stat-value" id="statConfidence">0%</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PII 识别统计 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">🔒 PII 敏感信息识别</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div id="piiChart"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 表识别结果 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">📊 表识别结果</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div id="tableResults"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 重要数据类型 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">⭐ 重要数据类型识别</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div id="importantDataChart"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 置信度分布 -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">📈 置信度分布</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div id="confidenceChart"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空状态 -->
|
||
<div id="emptyState" class="card" style="text-align: center; padding: 60px 20px;">
|
||
<div style="font-size: 48px; margin-bottom: 20px;">🎯</div>
|
||
<h3 style="margin-bottom: 12px;">等待分析</h3>
|
||
<p style="color: var(--text-muted);">
|
||
填写左侧表单参数,或点击"快速使用虚拟数据"按钮<br>
|
||
然后点击"开始分析"按钮进行数据资产智能识别
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="base_test_framework.js"></script>
|
||
<script>
|
||
// ==================== 虚拟数据 ====================
|
||
const mockData = {
|
||
retail: {
|
||
tables: [
|
||
{
|
||
raw_name: "t_user_base_01",
|
||
fields: [
|
||
{ raw_name: "user_id", type: "varchar(64)", comment: "用户唯一标识符" },
|
||
{ raw_name: "phone", type: "varchar(11)", comment: "用户手机号码" },
|
||
{ raw_name: "email", type: "varchar(100)", comment: "用户电子邮箱" },
|
||
{ raw_name: "nickname", type: "varchar(50)", comment: "用户昵称" },
|
||
{ raw_name: "register_time", type: "datetime", comment: "注册时间" }
|
||
]
|
||
},
|
||
{
|
||
raw_name: "t_order_detail",
|
||
fields: [
|
||
{ raw_name: "order_id", type: "bigint", comment: "订单ID" },
|
||
{ raw_name: "user_id", type: "varchar(64)", comment: "用户ID" },
|
||
{ raw_name: "product_name", type: "varchar(200)", comment: "商品名称" },
|
||
{ raw_name: "quantity", type: "int", comment: "购买数量" },
|
||
{ raw_name: "price", type: "decimal(10,2)", comment: "商品单价" },
|
||
{ raw_name: "total_amount", type: "decimal(10,2)", comment: "订单总金额" },
|
||
{ raw_name: "pay_time", type: "datetime", comment: "支付时间" }
|
||
]
|
||
},
|
||
{
|
||
raw_name: "t_member_info",
|
||
fields: [
|
||
{ raw_name: "member_id", type: "varchar(64)", comment: "会员ID" },
|
||
{ raw_name: "member_level", type: "int", comment: "会员等级" },
|
||
{ raw_name: "points", type: "int", comment: "会员积分" },
|
||
{ raw_name: "birth_date", type: "date", comment: "出生日期" },
|
||
{ raw_name: "id_card", type: "varchar(18)", comment: "身份证号码" }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
finance: {
|
||
tables: [
|
||
{
|
||
raw_name: "t_account_info",
|
||
fields: [
|
||
{ raw_name: "account_no", type: "varchar(32)", comment: "账户号码" },
|
||
{ raw_name: "customer_name", type: "varchar(100)", comment: "客户姓名" },
|
||
{ raw_name: "id_card", type: "varchar(18)", comment: "身份证号码" },
|
||
{ raw_name: "phone", type: "varchar(11)", comment: "联系电话" },
|
||
{ raw_name: "balance", type: "decimal(18,2)", comment: "账户余额" }
|
||
]
|
||
},
|
||
{
|
||
raw_name: "t_transaction_record",
|
||
fields: [
|
||
{ raw_name: "trans_id", type: "bigint", comment: "交易流水号" },
|
||
{ raw_name: "account_no", type: "varchar(32)", comment: "账户号码" },
|
||
{ raw_name: "amount", type: "decimal(18,2)", comment: "交易金额" },
|
||
{ raw_name: "trans_type", type: "varchar(20)", comment: "交易类型" },
|
||
{ raw_name: "trans_time", type: "datetime", comment: "交易时间" },
|
||
{ raw_name: "counter_account", type: "varchar(32)", comment: "对方账户" }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
user: {
|
||
tables: [
|
||
{
|
||
raw_name: "user_profile",
|
||
fields: [
|
||
{ raw_name: "uid", type: "bigint", comment: "用户ID" },
|
||
{ raw_name: "username", type: "varchar(50)", comment: "用户名" },
|
||
{ raw_name: "real_name", type: "varchar(50)", comment: "真实姓名" },
|
||
{ raw_name: "mobile", type: "varchar(11)", comment: "手机号" },
|
||
{ raw_name: "email", type: "varchar(100)", comment: "邮箱" },
|
||
{ raw_name: "address", type: "varchar(500)", comment: "家庭地址" },
|
||
{ raw_name: "create_time", type: "datetime", comment: "创建时间" }
|
||
]
|
||
},
|
||
{
|
||
raw_name: "user_login_log",
|
||
fields: [
|
||
{ raw_name: "log_id", type: "bigint", comment: "日志ID" },
|
||
{ raw_name: "user_id", type: "bigint", comment: "用户ID" },
|
||
{ raw_name: "login_ip", type: "varchar(50)", comment: "登录IP" },
|
||
{ raw_name: "login_time", type: "datetime", comment: "登录时间" },
|
||
{ raw_name: "user_agent", type: "varchar(500)", comment: "用户代理" }
|
||
]
|
||
},
|
||
{
|
||
raw_name: "user_payment",
|
||
fields: [
|
||
{ raw_name: "payment_id", type: "bigint", comment: "支付ID" },
|
||
{ raw_name: "user_id", type: "bigint", comment: "用户ID" },
|
||
{ raw_name: "card_number", type: "varchar(30)", comment: "银行卡号" },
|
||
{ raw_name: "bank_name", type: "varchar(100)", comment: "银行名称" },
|
||
{ raw_name: "expiry_date", type: "varchar(10)", comment: "有效期" }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
};
|
||
|
||
// ==================== 模拟分析结果 ====================
|
||
function generateMockResponse(requestData) {
|
||
const tables = requestData.tables || [];
|
||
let totalFields = 0;
|
||
let piiFields = 0;
|
||
let importantFields = 0;
|
||
let totalConfidence = 0;
|
||
let piiTypes = {};
|
||
let importantDataTypes = {};
|
||
let confidenceRanges = { high: 0, medium: 0, low: 0 };
|
||
|
||
const processedTables = tables.map(table => {
|
||
const processedFields = table.fields.map(field => {
|
||
const hasPII = detectPII(field.raw_name, field.comment);
|
||
const isImportant = detectImportantData(field.raw_name, field.comment);
|
||
const confidence = calculateConfidence(field);
|
||
|
||
if (hasPII) {
|
||
piiFields++;
|
||
const piiType = detectPIIType(field.raw_name);
|
||
piiTypes[piiType] = (piiTypes[piiType] || 0) + 1;
|
||
}
|
||
|
||
if (isImportant) {
|
||
importantFields++;
|
||
const dataType = detectDataType(field.raw_name);
|
||
importantDataTypes[dataType] = (importantDataTypes[dataType] || 0) + 1;
|
||
}
|
||
|
||
if (confidence >= 80) confidenceRanges.high++;
|
||
else if (confidence >= 60) confidenceRanges.medium++;
|
||
else confidenceRanges.low++;
|
||
|
||
totalConfidence += confidence;
|
||
totalFields++;
|
||
|
||
return {
|
||
raw_name: field.raw_name,
|
||
ai_name: generateChineseName(field.raw_name),
|
||
desc: field.comment || generateDescription(field.raw_name),
|
||
type: field.type,
|
||
pii: hasPII ? [detectPIIType(field.raw_name)] : [],
|
||
pii_type: hasPII ? detectPIIType(field.raw_name) : null,
|
||
is_important_data: isImportant,
|
||
confidence: confidence
|
||
};
|
||
});
|
||
|
||
const tablePII = [];
|
||
const tableImportantDataTypes = [];
|
||
processedFields.forEach(f => {
|
||
if (f.pii.length > 0) tablePII.push(...f.pii);
|
||
if (f.is_important_data && f.pii_type) {
|
||
if (!tableImportantDataTypes.includes(f.pii_type)) {
|
||
tableImportantDataTypes.push(f.pii_type);
|
||
}
|
||
}
|
||
});
|
||
|
||
return {
|
||
raw_name: table.raw_name,
|
||
ai_name: generateChineseName(table.raw_name),
|
||
desc: generateDescription(table.raw_name),
|
||
confidence: Math.round(processedFields.reduce((sum, f) => sum + f.confidence, 0) / processedFields.length),
|
||
ai_completed: true,
|
||
fields: processedFields,
|
||
pii: tablePII,
|
||
important: tablePII.length > 0,
|
||
important_data_types: tableImportantDataTypes
|
||
};
|
||
});
|
||
|
||
const statistics = {
|
||
total_tables: tables.length,
|
||
total_fields: totalFields,
|
||
pii_fields_count: piiFields,
|
||
important_data_fields_count: importantFields,
|
||
average_confidence: totalFields > 0 ? Math.round(totalConfidence / totalFields) : 0
|
||
};
|
||
|
||
return {
|
||
tables: processedTables,
|
||
statistics: statistics,
|
||
processing_time: (Math.random() * 3 + 1).toFixed(2),
|
||
model_used: requestData.options?.model || 'qwen-max',
|
||
piiTypes: piiTypes,
|
||
importantDataTypes: importantDataTypes,
|
||
confidenceRanges: confidenceRanges
|
||
};
|
||
}
|
||
|
||
// 辅助函数
|
||
function detectPII(fieldName, comment) {
|
||
const piiKeywords = ['phone', 'mobile', 'email', 'mail', 'id_card', 'idcard', 'name', 'real_name', 'idcard', 'address', 'card', 'bank', 'birth', 'id'];
|
||
const fieldLower = fieldName.toLowerCase();
|
||
const commentLower = (comment || '').toLowerCase();
|
||
return piiKeywords.some(keyword => fieldLower.includes(keyword) || commentLower.includes(keyword));
|
||
}
|
||
|
||
function detectPIIType(fieldName) {
|
||
const fieldLower = fieldName.toLowerCase();
|
||
if (fieldLower.includes('phone') || fieldLower.includes('mobile')) return '手机号';
|
||
if (fieldLower.includes('email') || fieldLower.includes('mail')) return '邮箱';
|
||
if (fieldLower.includes('id_card') || fieldLower.includes('idcard')) return '身份证号';
|
||
if (fieldLower.includes('name')) return '姓名';
|
||
if (fieldLower.includes('address')) return '地址';
|
||
if (fieldLower.includes('card') || fieldLower.includes('bank')) return '银行卡号';
|
||
if (fieldLower.includes('birth')) return '出生日期';
|
||
return '其他敏感信息';
|
||
}
|
||
|
||
function detectImportantData(fieldName, comment) {
|
||
const importantKeywords = ['balance', 'amount', 'price', 'payment', 'transaction', 'trans', 'points', 'score'];
|
||
const fieldLower = fieldName.toLowerCase();
|
||
const commentLower = (comment || '').toLowerCase();
|
||
return importantKeywords.some(keyword => fieldLower.includes(keyword) || commentLower.includes(keyword));
|
||
}
|
||
|
||
function detectDataType(fieldName) {
|
||
const fieldLower = fieldName.toLowerCase();
|
||
if (fieldLower.includes('balance') || fieldLower.includes('amount') || fieldLower.includes('price')) return '金融数据';
|
||
if (fieldLower.includes('transaction') || fieldLower.includes('trans') || fieldLower.includes('payment')) return '交易数据';
|
||
if (fieldLower.includes('points') || fieldLower.includes('score')) return '积分数据';
|
||
return '其他重要数据';
|
||
}
|
||
|
||
function calculateConfidence(field) {
|
||
let baseScore = 70;
|
||
if (field.comment && field.comment.length > 0) baseScore += 15;
|
||
if (field.type && field.type.length > 0) baseScore += 10;
|
||
return Math.min(99, Math.round(baseScore + Math.random() * 5));
|
||
}
|
||
|
||
function generateChineseName(fieldName) {
|
||
const translations = {
|
||
'user_id': '用户ID',
|
||
'uid': '用户唯一标识',
|
||
'phone': '手机号',
|
||
'mobile': '联系电话',
|
||
'email': '电子邮箱',
|
||
'nickname': '用户昵称',
|
||
'username': '用户名',
|
||
'real_name': '真实姓名',
|
||
'address': '收货地址',
|
||
'register_time': '注册时间',
|
||
'create_time': '创建时间',
|
||
'login_time': '登录时间',
|
||
'order_id': '订单编号',
|
||
'product_name': '商品名称',
|
||
'quantity': '购买数量',
|
||
'price': '商品单价',
|
||
'total_amount': '订单总额',
|
||
'pay_time': '支付时间',
|
||
'member_id': '会员编号',
|
||
'member_level': '会员等级',
|
||
'points': '会员积分',
|
||
'birth_date': '出生日期',
|
||
'id_card': '身份证号码',
|
||
'account_no': '账户号码',
|
||
'customer_name': '客户姓名',
|
||
'balance': '账户余额',
|
||
'trans_id': '交易流水号',
|
||
'amount': '交易金额',
|
||
'trans_type': '交易类型',
|
||
'trans_time': '交易时间',
|
||
'counter_account': '对方账户',
|
||
'log_id': '日志编号',
|
||
'login_ip': '登录IP地址',
|
||
'user_agent': '用户代理',
|
||
'payment_id': '支付编号',
|
||
'card_number': '银行卡号',
|
||
'bank_name': '银行名称',
|
||
'expiry_date': '有效期'
|
||
};
|
||
return translations[fieldName.toLowerCase()] || fieldName;
|
||
}
|
||
|
||
function generateDescription(tableName) {
|
||
const descriptions = {
|
||
't_user_base_01': '存储用户的基础信息,包括用户ID、联系方式等核心身份数据',
|
||
'user_profile': '用户个人资料信息,包含用户的真实身份信息',
|
||
't_order_detail': '订单详情记录,存储每个订单的商品明细和支付信息',
|
||
't_member_info': '会员信息表,记录会员等级、积分等会员权益数据',
|
||
't_account_info': '账户信息表,存储客户的银行账户和余额信息',
|
||
't_transaction_record': '交易记录表,记录所有账户的交易流水',
|
||
'user_login_log': '用户登录日志,记录用户的登录行为和安全信息',
|
||
'user_payment': '用户支付信息,存储用户的银行卡等支付方式'
|
||
};
|
||
return descriptions[tableName] || '存储业务数据的关键数据表';
|
||
}
|
||
|
||
// ==================== 表单处理 ====================
|
||
let currentMockData = null;
|
||
|
||
function loadMockData(type) {
|
||
currentMockData = mockData[type];
|
||
document.getElementById('context').value = {
|
||
'retail': '某连锁生鲜零售企业,主营水果、蔬菜等生鲜产品,拥有200+线下门店和线上电商平台',
|
||
'finance': '某银行机构,提供个人和企业金融服务',
|
||
'user': '用户中心系统,负责用户注册、登录、权限管理等核心功能'
|
||
}[type];
|
||
|
||
// 更新行业选择
|
||
document.getElementById('industry').value = {
|
||
'retail': 'retail-fresh',
|
||
'finance': 'finance',
|
||
'user': 'retail-fresh'
|
||
}[type];
|
||
|
||
showToast(`已加载${{ 'retail': '零售', 'finance': '金融', 'user': '用户中心' }[type]}场景虚拟数据`);
|
||
}
|
||
|
||
function resetForm() {
|
||
document.getElementById('analyzeForm').reset();
|
||
currentMockData = null;
|
||
document.getElementById('resultArea').style.display = 'none';
|
||
document.getElementById('emptyState').style.display = 'block';
|
||
document.getElementById('requestInfo').style.display = 'block';
|
||
document.getElementById('responseInfo').style.display = 'none';
|
||
}
|
||
|
||
// 表单提交
|
||
document.getElementById('analyzeForm').addEventListener('submit', async function(e) {
|
||
e.preventDefault();
|
||
|
||
// 获取表单数据
|
||
const requestData = {
|
||
project_id: document.getElementById('projectId').value,
|
||
industry: document.getElementById('industry').value,
|
||
context: document.getElementById('context').value,
|
||
options: {
|
||
model: document.getElementById('model').value,
|
||
temperature: parseFloat(document.getElementById('temperature').value),
|
||
enable_pii_detection: document.getElementById('enablePII').checked,
|
||
enable_important_data_detection: document.getElementById('enableImportant').checked
|
||
}
|
||
};
|
||
|
||
// 使用虚拟数据或空数据
|
||
if (currentMockData) {
|
||
requestData.tables = currentMockData.tables;
|
||
} else {
|
||
// 提示用户需要输入表数据
|
||
showToast('请使用快速虚拟数据或手动输入表数据');
|
||
return;
|
||
}
|
||
|
||
// 显示请求数据
|
||
document.getElementById('requestJson').textContent = JSON.stringify(requestData, null, 2);
|
||
document.getElementById('responseInfo').style.display = 'none';
|
||
|
||
// 显示加载状态
|
||
document.getElementById('emptyState').style.display = 'none';
|
||
document.getElementById('resultArea').style.display = 'none';
|
||
showLoading('loadingArea');
|
||
|
||
try {
|
||
// 模拟API调用
|
||
await delay(2000);
|
||
|
||
// 生成模拟响应
|
||
const response = generateMockResponse(requestData);
|
||
|
||
// 显示结果
|
||
hideLoading('loadingArea', '');
|
||
document.getElementById('resultArea').style.display = 'block';
|
||
|
||
// 显示响应数据
|
||
document.getElementById('responseInfo').style.display = 'block';
|
||
document.getElementById('responseJson').textContent = JSON.stringify(response, null, 2);
|
||
|
||
// 渲染统计信息
|
||
renderStatistics(response.statistics);
|
||
|
||
// 渲染图表
|
||
renderCharts(response);
|
||
|
||
// 渲染表结果
|
||
renderTableResults(response.tables);
|
||
|
||
showSuccess('loadingArea', '✅ 分析完成!');
|
||
setTimeout(() => {
|
||
document.getElementById('loadingArea').style.display = 'none';
|
||
}, 2000);
|
||
|
||
} catch (error) {
|
||
hideLoading('loadingArea', '');
|
||
showError('loadingArea', error.message);
|
||
}
|
||
});
|
||
|
||
// 渲染统计信息
|
||
function renderStatistics(statistics) {
|
||
document.getElementById('statTables').textContent = statistics.total_tables;
|
||
document.getElementById('statFields').textContent = statistics.total_fields;
|
||
document.getElementById('statPII').textContent = statistics.pii_fields_count;
|
||
document.getElementById('statImportant').textContent = statistics.important_data_fields_count;
|
||
document.getElementById('statConfidence').textContent = statistics.average_confidence + '%';
|
||
}
|
||
|
||
// 渲染图表
|
||
function renderCharts(response) {
|
||
// PII 类型分布
|
||
if (Object.keys(response.piiTypes).length > 0) {
|
||
const piiData = Object.entries(response.piiTypes).map(([key, value]) => ({
|
||
label: key,
|
||
value: value
|
||
}));
|
||
renderBarChart('piiChart', piiData, 'PII 敏感信息类型分布');
|
||
} else {
|
||
document.getElementById('piiChart').innerHTML = '<p style="text-align: center; color: var(--text-muted);">未检测到 PII 敏感信息</p>';
|
||
}
|
||
|
||
// 重要数据类型
|
||
if (Object.keys(response.importantDataTypes).length > 0) {
|
||
const importantData = Object.entries(response.importantDataTypes).map(([key, value]) => ({
|
||
label: key,
|
||
value: value
|
||
}));
|
||
renderBarChart('importantDataChart', importantData, '重要数据类型分布');
|
||
} else {
|
||
document.getElementById('importantDataChart').innerHTML = '<p style="text-align: center; color: var(--text-muted);">未检测到重要数据</p>';
|
||
}
|
||
|
||
// 置信度分布
|
||
const confidenceData = [
|
||
{ label: '高 (≥80%)', value: response.confidenceRanges.high, color: '#4caf50' },
|
||
{ label: '中 (60-79%)', value: response.confidenceRanges.medium, color: '#ff9800' },
|
||
{ label: '低 (<60%)', value: response.confidenceRanges.low, color: '#f44336' }
|
||
];
|
||
renderBarChart('confidenceChart', confidenceData, '识别置信度分布');
|
||
}
|
||
|
||
// 渲染表结果
|
||
function renderTableResults(tables) {
|
||
const container = document.getElementById('tableResults');
|
||
|
||
let html = '';
|
||
tables.forEach((table, index) => {
|
||
html += `
|
||
<div class="table-accordion">
|
||
<div class="accordion-header" onclick="toggleAccordion(this)">
|
||
<div>
|
||
<strong style="font-size: 16px;">${table.ai_name}</strong>
|
||
<div style="font-size: 12px; color: var(--text-muted); margin-top: 4px;">
|
||
原始名称: ${table.raw_name} | 字段数: ${table.fields.length} | 置信度: ${table.confidence}%
|
||
</div>
|
||
</div>
|
||
<div>
|
||
${table.important ? '<span class="field-tag tag-important">重要数据</span>' : ''}
|
||
${table.pii.length > 0 ? `<span class="field-tag tag-pii">含PII: ${table.pii.join(', ')}</span>` : ''}
|
||
<span class="accordion-icon">▼</span>
|
||
</div>
|
||
</div>
|
||
<div class="accordion-content">
|
||
<p style="margin-bottom: 12px; color: var(--text-muted);">${table.desc}</p>
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
|
||
`;
|
||
|
||
table.fields.forEach(field => {
|
||
const hasPII = field.pii.length > 0;
|
||
const isImportant = field.is_important_data;
|
||
const confidenceClass = field.confidence >= 80 ? 'confidence-high' : (field.confidence >= 60 ? 'confidence-medium' : 'confidence-low');
|
||
|
||
html += `
|
||
<div class="field-card ${hasPII ? 'pii' : ''} ${isImportant ? 'important' : ''}">
|
||
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 4px;">
|
||
<strong style="font-size: 13px;">${field.ai_name}</strong>
|
||
<div style="font-size: 11px;">
|
||
${hasPII ? `<span class="field-tag tag-pii">${field.pii_type}</span>` : ''}
|
||
${isImportant ? '<span class="field-tag tag-important">重要</span>' : ''}
|
||
</div>
|
||
</div>
|
||
<div style="font-size: 11px; color: var(--text-muted); margin-bottom: 4px;">
|
||
${field.raw_name} | ${field.type}
|
||
</div>
|
||
<div style="font-size: 12px; margin-bottom: 6px;">${field.desc}</div>
|
||
<div style="font-size: 11px; display: flex; justify-content: space-between;">
|
||
<span>置信度: ${field.confidence}%</span>
|
||
</div>
|
||
<div class="confidence-bar">
|
||
<div class="confidence-fill ${confidenceClass}" style="width: ${field.confidence}%;"></div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
html += `
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
container.innerHTML = html;
|
||
}
|
||
|
||
// 切换折叠面板
|
||
function toggleAccordion(header) {
|
||
header.classList.toggle('active');
|
||
const content = header.nextElementSibling;
|
||
content.classList.toggle('active');
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|