This commit is contained in:
2026-01-04 17:59:28 +08:00
parent 71bf46e0a1
commit 2caf2d3c0c
7 changed files with 621 additions and 614 deletions

View File

@@ -644,87 +644,88 @@ const maskValue = computed(() => {
// ==================== 新评分系统 ==================== // ==================== 新评分系统 ====================
// Feature 风险等级配置(权重越高表示风险越大,最终分数越高越安全) // Feature 风险等级配置(权重越高表示风险越大,最终分数越高越安全)
const featureRiskLevels = { const featureRiskLevels = {
// 🔴 高风险类 - 权重 10 // 🔴 高风险类 - 权重 60有高风险直接扣约70-80分
'FLXG0V4B': 20, // 司法涉诉 'FLXG0V4B': 60, // 司法涉诉
'FLXG7E8F': 20, // 个人涉诉 'FLXG3D56': 60, // 违约失信
'FLXG3D56': 10, // 违约失信 'JRZQ8A2D': 60, // 特殊名单验证
'FLXGDEA9': 18, // 本人不良 'FLXG7E8F': 55, // 个人涉诉
'JRZQ4AA8': 10, // 还款压力 'FLXGDEA9': 55, // 本人不良
// 🟠 中高风险类 - 权重 7 // 🟡 中高风险类 - 权重 20-30
'JRZQ0A03': 7, // 借贷申请记录 'JRZQ4AA8': 25, // 还款压力
'JRZQ6F2A': 7, // 借贷申请 'JRZQ0A03': 25, // 借贷申请记录
'JRZQ8203': 7, // 借贷行为记录 'JRZQ8203': 25, // 借贷行为记录
'JRZQ4B6C': 7, // 信贷表现 'JRZQ4B6C': 25, // 信贷表现
'BehaviorRiskScan': 7, // 风险行为扫描 'JRZQ6F2A': 25, // 借贷申请
'IVYZ8I9J': 7, // 网络社交异常 'BehaviorRiskScan': 60, // 风险行为扫描
'JRZQ8A2D': 9, // 特殊名单验证 'IVYZ8I9J': 45, // 网络社交异常
'JRZQ7F1A': 8, // 全景雷达 'JRZQ7F1A': 20, // 全景雷达
'JRZQ7F1A_ApplyReport': 3, 'JRZQ7F1A_ApplyReport': 8,
'JRZQ7F1A_BehaviorReport': 3, 'JRZQ7F1A_BehaviorReport': 8,
'JRZQ7F1A_BigDataReport': 2, 'JRZQ7F1A_BigDataReport': 4,
'YYSY7D3E': 5, // 手机携号转网 'DWBG7F3A': 25, // 多头借贷
'YYSY8B1C': 5, // 手机在网时长 'YYSY7D3E': 15, // 手机携号转网
'DWBG7F3A': 8, // 多头借贷 'YYSY8B1C': 15, // 手机在网时长
// 🟡 中风险类 - 权重 5 // 🟢 中风险类 - 权重 8-12
'QYGL3F8E': 5, // 人企关系加强版 'QYGL3F8E': 10, // 人企关系加强版
'QCXG7A2B': 5, // 名下车辆 'QCXG7A2B': 10, // 名下车辆
'JRZQ09J8': 5, // 收入评估 'JRZQ09J8': 10, // 收入评估
'JRZQ3C9R': 5, // 支付行为指数 'JRZQ3C9R': 10, // 支付行为指数
// 🔵 低风险类 - 权重 3
'IVYZ5733': 3, // 婚姻状态 // 🔵 低风险类 - 权重 3-5
'IVYZ9A2B': 3, // 学历信息 'IVYZ5733': 4, // 婚姻状态
'IVYZ3P9M': 3, // 学历信息查询(实时版) 'IVYZ9A2B': 4, // 学历信息
'IVYZ3P9M': 4, // 学历信息查询(实时版)
// 📊 复合报告类 - 按子模块动态计算 // 📊 复合报告类 - 按子模块动态计算
'DWBG8B4D': 0, // 谛听多维报告(由子模块计算) 'DWBG8B4D': 0, // 谛听多维报告(由子模块计算)
'DWBG6A2C': 0, // 司南报告(由子模块计算) 'DWBG6A2C': 0, // 司南报告(由子模块计算)
'JRZQ5E9F': 0, // 贷款风险评估(由子模块计算) 'JRZQ5E9F': 0, // 贷款风险评估(由子模块计算)
// 谛听多维报告子模块 // 谛听多维报告子模块
'DWBG8B4D_Overview': 10, 'DWBG8B4D_Overview': 30,
'DWBG8B4D_ElementVerification': 4, 'DWBG8B4D_ElementVerification': 10,
'DWBG8B4D_Identity': 4, 'DWBG8B4D_Identity': 10,
'DWBG8B4D_RiskWarning': 10, 'DWBG8B4D_RiskWarning': 35,
'DWBG8B4D_OverdueRisk': 9, 'DWBG8B4D_OverdueRisk': 30,
'DWBG8B4D_LoanEvaluation': 7, 'DWBG8B4D_LoanEvaluation': 20,
'DWBG8B4D_LeasingRisk': 6, 'DWBG8B4D_LeasingRisk': 18,
'DWBG8B4D_RiskSupervision': 8, 'DWBG8B4D_RiskSupervision': 25,
'DWBG8B4D_RiskWarningTab': 9, 'DWBG8B4D_RiskWarningTab': 30,
// 司南报告子模块 // 司南报告子模块
'DWBG6A2C_StandLiveInfo': 4, 'DWBG6A2C_StandLiveInfo': 10,
'DWBG6A2C_RiskPoint': 9, 'DWBG6A2C_RiskPoint': 28,
'DWBG6A2C_SecurityInfo': 15, 'DWBG6A2C_SecurityInfo': 45,
'DWBG6A2C_AntiFraudInfo': 15, 'DWBG6A2C_AntiFraudInfo': 45,
'DWBG6A2C_RiskList': 12, 'DWBG6A2C_RiskList': 38,
'DWBG6A2C_ApplicationStatistics': 7, 'DWBG6A2C_ApplicationStatistics': 22,
'DWBG6A2C_LendingStatistics': 6, 'DWBG6A2C_LendingStatistics': 18,
'DWBG6A2C_PerformanceStatistics': 7, 'DWBG6A2C_PerformanceStatistics': 22,
'DWBG6A2C_OverdueRecord': 9, 'DWBG6A2C_OverdueRecord': 28,
'DWBG6A2C_CreditDetail': 5, 'DWBG6A2C_CreditDetail': 15,
'DWBG6A2C_RentalBehavior': 5, 'DWBG6A2C_RentalBehavior': 15,
'DWBG6A2C_RiskSupervision': 8, 'DWBG6A2C_RiskSupervision': 25,
// 贷款风险评估子模块 // 贷款风险评估子模块
'CJRZQ5E9F_RiskOverview': 8, 'CJRZQ5E9F_RiskOverview': 25,
'CJRZQ5E9F_CreditScores': 7, 'CJRZQ5E9F_CreditScores': 22,
'CJRZQ5E9F_LoanBehaviorAnalysis': 7, 'CJRZQ5E9F_LoanBehaviorAnalysis': 22,
'CJRZQ5E9F_InstitutionAnalysis': 5, 'CJRZQ5E9F_InstitutionAnalysis': 15,
'CJRZQ5E9F_TimeTrendAnalysis': 6, 'CJRZQ5E9F_TimeTrendAnalysis': 18,
'CJRZQ5E9F_RiskIndicators': 8, 'CJRZQ5E9F_RiskIndicators': 25,
'CJRZQ5E9F_RiskAdvice': 2, 'CJRZQ5E9F_RiskAdvice': 6,
// 人企关系加强版子模块 // 人企关系加强版子模块
'CQYGL3F8E_Investment': 4, 'CQYGL3F8E_Investment': 12,
'CQYGL3F8E_SeniorExecutive': 4, 'CQYGL3F8E_SeniorExecutive': 12,
'CQYGL3F8E_Lawsuit': 8, 'CQYGL3F8E_Lawsuit': 25,
'CQYGL3F8E_InvestHistory': 3, 'CQYGL3F8E_InvestHistory': 8,
'CQYGL3F8E_FinancingHistory': 3, 'CQYGL3F8E_FinancingHistory': 8,
'CQYGL3F8E_Punishment': 7, 'CQYGL3F8E_Punishment': 22,
'CQYGL3F8E_Abnormal': 6, 'CQYGL3F8E_Abnormal': 18,
'CQYGL3F8E_TaxRisk': 7, 'CQYGL3F8E_TaxRisk': 22,
}; };
// 存储每个组件的 ref 引用 // 存储每个组件的 ref 引用

View File

@@ -1,302 +1,303 @@
// 案件类型映射表 // 案件类型映射表
export const lawsuitTypeMap = { export const lawsuitTypeMap = {
sxbzxr: { sxbzxr: {
text: '失信被执行', text: "失信被执行",
color: 'text-red-600 bg-red-50', color: "text-red-600 bg-red-50",
darkColor: 'bg-red-500', darkColor: "bg-red-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
xgbzxr: { xgbzxr: {
text: '限高被执行', text: "限高被执行",
color: 'text-orange-600 bg-orange-50', color: "text-orange-600 bg-orange-50",
darkColor: 'bg-orange-500', darkColor: "bg-orange-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
criminal: { criminal: {
text: '刑事案件', text: "刑事案件",
color: 'text-red-600 bg-red-50', color: "text-red-600 bg-red-50",
darkColor: 'bg-red-500', darkColor: "bg-red-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
civil: { civil: {
text: '民事案件', text: "民事案件",
color: 'text-blue-600 bg-blue-50', color: "text-blue-600 bg-blue-50",
darkColor: 'bg-blue-500', darkColor: "bg-blue-500",
riskLevel: 'medium', // 中风险 riskLevel: "medium", // 中风险
}, },
administrative: { administrative: {
text: '行政案件', text: "行政案件",
color: 'text-purple-600 bg-purple-50', color: "text-purple-600 bg-purple-50",
darkColor: 'bg-purple-500', darkColor: "bg-purple-500",
riskLevel: 'medium', // 中风险 riskLevel: "medium", // 中风险
}, },
implement: { implement: {
text: '执行案件', text: "执行案件",
color: 'text-orange-600 bg-orange-50', color: "text-orange-600 bg-orange-50",
darkColor: 'bg-orange-500', darkColor: "bg-orange-500",
riskLevel: 'medium', // 中风险 riskLevel: "medium", // 中风险
}, },
bankrupt: { bankrupt: {
text: '强制清算与破产案件', text: "强制清算与破产案件",
color: 'text-rose-600 bg-rose-50', color: "text-rose-600 bg-rose-50",
darkColor: 'bg-rose-500', darkColor: "bg-rose-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
preservation: { preservation: {
text: '非诉保全审查', text: "非诉保全审查",
color: 'text-amber-600 bg-amber-50', color: "text-amber-600 bg-amber-50",
darkColor: 'bg-amber-500', darkColor: "bg-amber-500",
riskLevel: 'low', // 低风险 riskLevel: "low", // 低风险
}, },
} };
// 案件类型文本 // 案件类型文本
export const getCaseTypeText = type => { export const getCaseTypeText = (type) => {
return lawsuitTypeMap[type]?.text || '其他案件' return lawsuitTypeMap[type]?.text || "其他案件";
} };
// 案件类型颜色 // 案件类型颜色
export const getCaseTypeColor = type => { export const getCaseTypeColor = (type) => {
return lawsuitTypeMap[type]?.color || 'text-gray-600 bg-gray-50' return lawsuitTypeMap[type]?.color || "text-gray-600 bg-gray-50";
} };
// 案件类型深色 // 案件类型深色
export const getCaseTypeDarkColor = type => { export const getCaseTypeDarkColor = (type) => {
return lawsuitTypeMap[type]?.darkColor || 'bg-gray-500' return lawsuitTypeMap[type]?.darkColor || "bg-gray-500";
} };
// 格式化日期显示 // 格式化日期显示
export const formatDate = dateStr => { export const formatDate = (dateStr) => {
if (!dateStr) return '—' if (!dateStr) return "—";
// 转换YYYY-MM-DD为年月日格式 // 转换YYYY-MM-DD为年月日格式
if (dateStr.includes('-')) { if (dateStr.includes("-")) {
const parts = dateStr.split('-') const parts = dateStr.split("-");
if (parts.length === 3) { if (parts.length === 3) {
return `${parts[0]}${parts[1]}${parts[2]}` return `${parts[0]}${parts[1]}${parts[2]}`;
}
} }
} return dateStr; // 如果不是标准格式则返回原始字符串
return dateStr // 如果不是标准格式则返回原始字符串 };
} // 格式化金额显示(单位:元)
export const formatLawsuitMoney = (money) => {
if (!money) return "—";
// 格式化金额显示(单位:万元) const value = parseFloat(money);
export const formatLawsuitMoney = money => { if (isNaN(value)) return "—";
if (!money) return '—'
const value = parseFloat(money) // 直接显示原始金额(元)
if (isNaN(value)) return '—'
// 超过1亿显示亿元
if (value >= 10000) {
return ( return (
(value / 10000).toLocaleString('zh-CN', { value.toLocaleString("zh-CN", {
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 2, maximumFractionDigits: 2,
}) + ' 亿元' }) + " 元"
) );
} };
// 否则显示万元
return (
value.toLocaleString('zh-CN', {
minimumFractionDigits: 0,
maximumFractionDigits: 2,
}) + ' 万元'
)
}
// 获取案件状态样式 // 获取案件状态样式
export const getCaseStatusClass = status => { export const getCaseStatusClass = (status) => {
if (!status) return 'bg-gray-100 text-gray-500' if (!status) return "bg-gray-100 text-gray-500";
if (status.includes('已结') || status.includes('已办结')) { if (status.includes("已结") || status.includes("已办结")) {
return 'bg-green-50 text-green-600' return "bg-green-50 text-green-600";
} else if (status.includes('执行中') || status.includes('审理中')) { } else if (status.includes("执行中") || status.includes("审理中")) {
return 'bg-blue-50 text-blue-600' return "bg-blue-50 text-blue-600";
} else if (status.includes('未执行')) { } else if (status.includes("未执行")) {
return 'bg-amber-50 text-amber-600' return "bg-amber-50 text-amber-600";
} else { } else {
return 'bg-gray-100 text-gray-500' return "bg-gray-100 text-gray-500";
} }
} };
// 获取企业状态对应的样式 // 获取企业状态对应的样式
export const getStatusClass = status => { export const getStatusClass = (status) => {
if (!status) return 'bg-gray-100 text-gray-500' if (!status) return "bg-gray-100 text-gray-500";
if (status.includes('注销') || status.includes('吊销')) { if (status.includes("注销") || status.includes("吊销")) {
return 'bg-red-50 text-red-600' return "bg-red-50 text-red-600";
} else if (status.includes('存续') || status.includes('在营')) { } else if (status.includes("存续") || status.includes("在营")) {
return 'bg-green-50 text-green-600' return "bg-green-50 text-green-600";
} else if (status.includes('筹建') || status.includes('新设')) { } else if (status.includes("筹建") || status.includes("新设")) {
return 'bg-blue-50 text-blue-600' return "bg-blue-50 text-blue-600";
} else { } else {
return 'bg-yellow-50 text-yellow-600' return "bg-yellow-50 text-yellow-600";
} }
} };
// 格式化资本金额显示 // 格式化资本金额显示
export const formatCapital = (capital, currency) => { export const formatCapital = (capital, currency) => {
if (!capital) return '—' if (!capital) return "—";
// 检查是否包含"万"字或需要显示为万元 // 检查是否包含"万"字或需要显示为万元
let unit = '' let unit = "";
let value = parseFloat(capital) let value = parseFloat(capital);
// 处理原始数据中可能带有的单位 // 处理原始数据中可能带有的单位
if (typeof capital === 'string' && capital.includes('万')) { if (typeof capital === "string" && capital.includes("万")) {
unit = '万' unit = "万";
// 提取数字部分 // 提取数字部分
const numMatch = capital.match(/[\d.]+/) const numMatch = capital.match(/[\d.]+/);
value = numMatch ? parseFloat(numMatch[0]) : 0 value = numMatch ? parseFloat(numMatch[0]) : 0;
} else if (value >= 10000) { } else if (value >= 10000) {
// 大额数字转换为万元显示 // 大额数字转换为万元显示
value = value / 10000 value = value / 10000;
unit = '万' unit = "万";
} }
// 格式化数字,保留两位小数(如果有小数部分) // 格式化数字,保留两位小数(如果有小数部分)
const formattedValue = value.toLocaleString('zh-CN', { const formattedValue = value.toLocaleString("zh-CN", {
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 2, maximumFractionDigits: 2,
}) });
return `${formattedValue}${unit} ${currency || '人民币'}` return `${formattedValue}${unit} ${currency || "人民币"}`;
} };
// 获取涉诉风险等级 // 获取涉诉风险等级
export const getRiskLevel = lawsuitInfo => { export const getRiskLevel = (lawsuitInfo) => {
if (!lawsuitInfo) { if (!lawsuitInfo) {
return {
level: "low",
text: "低风险",
color: "text-green-600 bg-green-50",
};
}
// 失信被执行人是最高风险
if (lawsuitInfo.sxbzxr && lawsuitInfo.sxbzxr.length > 0) {
return {
level: "high",
text: "高风险",
color: "text-red-600 bg-red-50",
};
}
// 限高被执行人是最高风险
if (lawsuitInfo.xgbzxr && lawsuitInfo.xgbzxr.length > 0) {
return {
level: "high",
text: "高风险",
color: "text-red-600 bg-red-50",
};
}
// 有涉诉数据的风险级别
if (lawsuitInfo.data && Object.keys(lawsuitInfo.data).length > 0) {
// 检查是否有未结案的案件
const data = lawsuitInfo.data;
if (data.count && data.count_wei_total && data.count_wei_total > 0) {
return {
level: "medium",
text: "中风险",
color: "text-amber-600 bg-amber-50",
};
}
// 只有已结案的为低中风险
return {
level: "low-medium",
text: "低中风险",
color: "text-yellow-600 bg-yellow-50",
};
}
return { return {
level: 'low', level: "low",
text: '低风险', text: "低风险",
color: 'text-green-600 bg-green-50', color: "text-green-600 bg-green-50",
} };
} };
// 失信被执行人是最高风险
if (lawsuitInfo.sxbzxr && lawsuitInfo.sxbzxr.length > 0) {
return {
level: 'high',
text: '高风险',
color: 'text-red-600 bg-red-50',
}
}
// 限高被执行人是最高风险
if (lawsuitInfo.xgbzxr && lawsuitInfo.xgbzxr.length > 0) {
return {
level: 'high',
text: '高风险',
color: 'text-red-600 bg-red-50',
}
}
// 有涉诉数据的风险级别
if (lawsuitInfo.data && Object.keys(lawsuitInfo.data).length > 0) {
// 检查是否有未结案的案件
const data = lawsuitInfo.data
if (data.count && data.count_wei_total && data.count_wei_total > 0) {
return {
level: 'medium',
text: '中风险',
color: 'text-amber-600 bg-amber-50',
}
}
// 只有已结案的为低中风险
return {
level: 'low-medium',
text: '低中风险',
color: 'text-yellow-600 bg-yellow-50',
}
}
return {
level: 'low',
text: '低风险',
color: 'text-green-600 bg-green-50',
}
}
// 获取涉诉案件统计 // 获取涉诉案件统计
export const getLawsuitStats = lawsuitInfo => { export const getLawsuitStats = (lawsuitInfo) => {
if (!lawsuitInfo) return null if (!lawsuitInfo) return null;
const stats = { const stats = {
total: 0, total: 0,
types: [], types: [],
} };
// 统计各类型案件数量 // 统计各类型案件数量
Object.keys(lawsuitTypeMap).forEach(type => { Object.keys(lawsuitTypeMap).forEach((type) => {
let count = 0 let count = 0;
if (type === 'sxbzxr') { if (type === "sxbzxr") {
count = lawsuitInfo.sxbzxr && lawsuitInfo.sxbzxr.length > 0 ? lawsuitInfo.sxbzxr.length : 0 count =
} else if (type === 'xgbzxr') { lawsuitInfo.sxbzxr && lawsuitInfo.sxbzxr.length > 0
count = lawsuitInfo.xgbzxr && lawsuitInfo.xgbzxr.length > 0 ? lawsuitInfo.xgbzxr.length : 0 ? lawsuitInfo.sxbzxr.length
} else if (lawsuitInfo.data && lawsuitInfo.data[type] && Object.keys(lawsuitInfo.data[type]).length > 0) { : 0;
const typeData = lawsuitInfo.data[type] } else if (type === "xgbzxr") {
count = typeData.cases && typeData.cases.length ? typeData.cases.length : 0 count =
} lawsuitInfo.xgbzxr && lawsuitInfo.xgbzxr.length > 0
? lawsuitInfo.xgbzxr.length
: 0;
} else if (
lawsuitInfo.data &&
lawsuitInfo.data[type] &&
Object.keys(lawsuitInfo.data[type]).length > 0
) {
const typeData = lawsuitInfo.data[type];
count =
typeData.cases && typeData.cases.length
? typeData.cases.length
: 0;
}
if (count > 0) { if (count > 0) {
stats.total += count stats.total += count;
stats.types.push({ stats.types.push({
type, type,
count, count,
name: getCaseTypeText(type), name: getCaseTypeText(type),
color: getCaseTypeColor(type), color: getCaseTypeColor(type),
darkColor: getCaseTypeDarkColor(type), darkColor: getCaseTypeDarkColor(type),
}) });
} }
}) });
return stats return stats;
} };
// 获取案件类型优先级顺序 // 获取案件类型优先级顺序
export const getCaseTypePriority = () => { export const getCaseTypePriority = () => {
return [ return [
'sxbzxr', // 失信被执行人(最高风险) "sxbzxr", // 失信被执行人(最高风险)
'xgbzxr', // 限高被执行人 "xgbzxr", // 限高被执行人
'criminal', // 刑事案件 "criminal", // 刑事案件
'civil', // 民事案件 "civil", // 民事案件
'administrative', // 行政案件 "administrative", // 行政案件
'implement', // 执行案件 "implement", // 执行案件
'bankrupt', // 强制清算与破产案件 "bankrupt", // 强制清算与破产案件
'preservation', // 非诉保全审查 "preservation", // 非诉保全审查
] ];
} };
// 根据案件类型获取风险等级 // 根据案件类型获取风险等级
export const getCaseTypeRiskLevel = caseType => { export const getCaseTypeRiskLevel = (caseType) => {
const typeInfo = lawsuitTypeMap[caseType] const typeInfo = lawsuitTypeMap[caseType];
if (!typeInfo) { if (!typeInfo) {
return { return {
level: 'low', level: "low",
text: '低风险', text: "低风险",
color: 'text-green-600 bg-green-50', color: "text-green-600 bg-green-50",
};
} }
}
const riskLevelMap = { const riskLevelMap = {
high: { high: {
text: '高风险', text: "高风险",
color: 'text-red-600 bg-red-50', color: "text-red-600 bg-red-50",
}, },
medium: { medium: {
text: '中风险', text: "中风险",
color: 'text-amber-600 bg-amber-50', color: "text-amber-600 bg-amber-50",
}, },
low: { low: {
text: '低风险', text: "低风险",
color: 'text-green-600 bg-green-50', color: "text-green-600 bg-green-50",
}, },
} };
return { return {
level: typeInfo.riskLevel, level: typeInfo.riskLevel,
...riskLevelMap[typeInfo.riskLevel], ...riskLevelMap[typeInfo.riskLevel],
} };
} };

View File

@@ -465,12 +465,12 @@ const riskScore = computed(() => {
const lowRiskCount = summaryData.value.byRiskLevel.find(item => item.id === 'low')?.triggered || 0; const lowRiskCount = summaryData.value.byRiskLevel.find(item => item.id === 'low')?.triggered || 0;
// 计算风险分数 // 计算风险分数
// 高风险项:每个扣 30 分 // 高风险项(无法收回):每个扣 40 分
// 中风险项:每个扣 15 // 中风险项(严重逾期):每个扣 20
// 低风险项:每个扣 5 分 // 低风险项(短期逾期):每个扣 5 分
let score = 100; let score = 100;
score -= highRiskCount * 30; score -= highRiskCount * 40;
score -= mediumRiskCount * 15; score -= mediumRiskCount * 20;
score -= lowRiskCount * 5; score -= lowRiskCount * 5;
return Math.max(0, Math.min(100, score)); return Math.max(0, Math.min(100, score));
@@ -544,11 +544,11 @@ onMounted(() => {
</div> </div>
<p class="text-sm text-gray-600 mt-1"> <p class="text-sm text-gray-600 mt-1">
{{ {{
riskSeverity.level === 'critical' riskSeverity.level === 'critical'
? '存在无法收回风险,请立即处理' ? '存在无法收回风险,请立即处理'
: riskSeverity.level === 'warning' : riskSeverity.level === 'warning'
? '存在严重逾期风险,建议尽快处理' ? '存在严重逾期风险,建议尽快处理'
: '存在短期逾期风险,请注意处理' : '存在短期逾期风险,请注意处理'
}} }}
</p> </p>
</div> </div>

View File

@@ -57,7 +57,7 @@
<!-- 所有风险类型列表 --> <!-- 所有风险类型列表 -->
<div class="space-y-3"> <div class="space-y-3">
<!-- 正常人员 --> <!-- 人员状态 -->
<div class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass('0')"> <div class="rounded-lg p-4 border-2 relative" :class="getRiskItemClass('0')">
<div <div
:class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass('0')]"> :class="['absolute top-0 right-0 px-1.5 py-0.5 text-sm font-bold text-white rounded-bl-lg rounded-tr-lg', getRiskBadgeClass('0')]">
@@ -65,13 +65,15 @@
</div> </div>
<div class="flex items-center pr-12"> <div class="flex items-center pr-12">
<div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center"> <div class="w-8 h-8 mr-3 flex-shrink-0 flex items-center justify-center">
<img :src="getRiskItemIcon('0')" alt="正常人员" class="w-8 h-8 object-contain" /> <img :src="getRiskItemIcon('0')" :alt="isNormalPerson ? '正常人员' : '存在风险'"
class="w-8 h-8 object-contain" />
</div> </div>
<div class="flex-1"> <div class="flex-1">
<div class="font-bold text-sm" :class="getRiskItemTextColor('0')"> <div class="font-bold text-sm" :class="getRiskItemTextColor('0')">
{{ getRiskTypeInfo('0').text }} {{ isNormalPerson ? '正常人员' : '人员状态' }}
</div> </div>
<div class="text-sm text-[#999999] mt-0.5">{{ getRiskTypeInfo('0').description }}</div> <div class="text-sm text-[#999999] mt-0.5">{{ isNormalPerson ? '无不良记录,属于正常人员' : '存在不良记录风险'
}}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -460,12 +462,12 @@ const isHit = (code) => {
// 如果level是'0',则正常人员命中 // 如果level是'0',则正常人员命中
return hitRiskCodes.value.includes('0') return hitRiskCodes.value.includes('0')
} }
// 如果直接包含该代码,则命中 // 如果直接包含该代码,则命中
if (hitRiskCodes.value.includes(code)) { if (hitRiskCodes.value.includes(code)) {
return true return true
} }
// 对于父级类型A、B、C、D如果子类型命中父类型也算命中 // 对于父级类型A、B、C、D如果子类型命中父类型也算命中
if (code === 'A') { if (code === 'A') {
// 如果 A1、A2、A3、A4、A5 任何一个命中A 也算命中 // 如果 A1、A2、A3、A4、A5 任何一个命中A 也算命中
@@ -483,7 +485,7 @@ const isHit = (code) => {
// 如果 D1、D2、D3、D4、D5 任何一个命中D 也算命中 // 如果 D1、D2、D3、D4、D5 任何一个命中D 也算命中
return ['D1', 'D2', 'D3', 'D4', 'D5'].some(subCode => hitRiskCodes.value.includes(subCode)) return ['D1', 'D2', 'D3', 'D4', 'D5'].some(subCode => hitRiskCodes.value.includes(subCode))
} }
return false return false
} }

View File

@@ -221,7 +221,7 @@
<span class="text-[#EB3C3C] ml-1">{{ getLawsuitStats(company).total <span class="text-[#EB3C3C] ml-1">{{ getLawsuitStats(company).total
|| ||
0 0
}}</span> }}</span>
</div> </div>
<!-- 企业状态 --> <!-- 企业状态 -->
<span v-if="company.basicInfo && company.basicInfo.regStatus" <span v-if="company.basicInfo && company.basicInfo.regStatus"
@@ -273,13 +273,13 @@
<span class="text-base font-medium text-[#333333]">{{ <span class="text-base font-medium text-[#333333]">{{
company.basicInfo.regStatus || company.basicInfo.regStatus ||
'-' '-'
}}</span> }}</span>
<span class="text-base text-[#666666]">统一社会信用代码:</span> <span class="text-base text-[#666666]">统一社会信用代码:</span>
<span class="text-base font-medium text-[#333333]">{{ <span class="text-base font-medium text-[#333333]">{{
company.basicInfo.creditCode company.basicInfo.creditCode
|| '-' || '-'
}}</span> }}</span>
<span class="text-base text-[#666666]">注册资本:</span> <span class="text-base text-[#666666]">注册资本:</span>
<span class="text-base font-medium text-[#333333]">{{ <span class="text-base font-medium text-[#333333]">{{
@@ -1162,29 +1162,18 @@ const getLawsuitStats = (company) => {
return stats; return stats;
}; };
// 格式化金额显示(单位:万元)
const formatLawsuitMoney = (money) => { const formatLawsuitMoney = (money) => {
if (!money) return "—"; if (!money) return "—";
const value = parseFloat(money); const value = parseFloat(money);
if (isNaN(value)) return "—"; if (isNaN(value)) return "—";
// 超过1亿显示亿元 // 直接显示原始金额(元)
if (value >= 10000) {
return (
(value / 10000).toLocaleString("zh-CN", {
minimumFractionDigits: 0,
maximumFractionDigits: 2,
}) + " 亿元"
);
}
// 否则显示万元
return ( return (
value.toLocaleString("zh-CN", { value.toLocaleString("zh-CN", {
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 2, maximumFractionDigits: 2,
}) + " 元" }) + " 元"
); );
}; };

View File

@@ -1,303 +1,316 @@
// 案件类型映射表 // 案件类型映射表
export const lawsuitTypeMap = { export const lawsuitTypeMap = {
breachCase: { breachCase: {
text: '失信被执行', text: "失信被执行",
color: 'text-red-600 bg-red-50', color: "text-red-600 bg-red-50",
darkColor: 'bg-red-500', darkColor: "bg-red-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
consumptionRestriction: { consumptionRestriction: {
text: '限高被执行', text: "限高被执行",
color: 'text-orange-600 bg-orange-50', color: "text-orange-600 bg-orange-50",
darkColor: 'bg-orange-500', darkColor: "bg-orange-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
criminal: { criminal: {
text: '刑事案件', text: "刑事案件",
color: 'text-red-600 bg-red-50', color: "text-red-600 bg-red-50",
darkColor: 'bg-red-500', darkColor: "bg-red-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
civil: { civil: {
text: '民事案件', text: "民事案件",
color: 'text-blue-600 bg-blue-50', color: "text-blue-600 bg-blue-50",
darkColor: 'bg-blue-500', darkColor: "bg-blue-500",
riskLevel: 'medium', // 中风险 riskLevel: "medium", // 中风险
}, },
administrative: { administrative: {
text: '行政案件', text: "行政案件",
color: 'text-purple-600 bg-purple-50', color: "text-purple-600 bg-purple-50",
darkColor: 'bg-purple-500', darkColor: "bg-purple-500",
riskLevel: 'medium', // 中风险 riskLevel: "medium", // 中风险
}, },
implement: { implement: {
text: '执行案件', text: "执行案件",
color: 'text-orange-600 bg-orange-50', color: "text-orange-600 bg-orange-50",
darkColor: 'bg-orange-500', darkColor: "bg-orange-500",
riskLevel: 'medium', // 中风险 riskLevel: "medium", // 中风险
}, },
bankrupt: { bankrupt: {
text: '强制清算与破产案件', text: "强制清算与破产案件",
color: 'text-rose-600 bg-rose-50', color: "text-rose-600 bg-rose-50",
darkColor: 'bg-rose-500', darkColor: "bg-rose-500",
riskLevel: 'high', // 高风险 riskLevel: "high", // 高风险
}, },
preservation: { preservation: {
text: '非诉保全审查', text: "非诉保全审查",
color: 'text-amber-600 bg-amber-50', color: "text-amber-600 bg-amber-50",
darkColor: 'bg-amber-500', darkColor: "bg-amber-500",
riskLevel: 'low', // 低风险 riskLevel: "low", // 低风险
}, },
} };
// 案件类型文本 // 案件类型文本
export const getCaseTypeText = type => { export const getCaseTypeText = (type) => {
return lawsuitTypeMap[type]?.text || '其他案件' return lawsuitTypeMap[type]?.text || "其他案件";
} };
// 案件类型颜色 // 案件类型颜色
export const getCaseTypeColor = type => { export const getCaseTypeColor = (type) => {
return lawsuitTypeMap[type]?.color || 'text-gray-600 bg-gray-50' return lawsuitTypeMap[type]?.color || "text-gray-600 bg-gray-50";
} };
// 案件类型深色 // 案件类型深色
export const getCaseTypeDarkColor = type => { export const getCaseTypeDarkColor = (type) => {
return lawsuitTypeMap[type]?.darkColor || 'bg-gray-500' return lawsuitTypeMap[type]?.darkColor || "bg-gray-500";
} };
// 格式化日期显示 // 格式化日期显示
export const formatDate = dateStr => { export const formatDate = (dateStr) => {
if (!dateStr) return '—' if (!dateStr) return "—";
// 转换YYYY-MM-DD为年月日格式 // 转换YYYY-MM-DD为年月日格式
if (dateStr.includes('-')) { if (dateStr.includes("-")) {
const parts = dateStr.split('-') const parts = dateStr.split("-");
if (parts.length === 3) { if (parts.length === 3) {
return `${parts[0]}${parts[1]}${parts[2]}` return `${parts[0]}${parts[1]}${parts[2]}`;
}
} }
} return dateStr; // 如果不是标准格式则返回原始字符串
return dateStr // 如果不是标准格式则返回原始字符串 };
}
// 格式化金额显示(单位:万元) export const formatLawsuitMoney = (money) => {
export const formatLawsuitMoney = money => { if (!money) return "—";
if (!money) return '—'
const value = parseFloat(money) const value = parseFloat(money);
if (isNaN(value)) return '—' if (isNaN(value)) return "—";
// 超过1亿显示亿元 // 直接显示原始金额(元)
if (value >= 10000) {
return ( return (
(value / 10000).toLocaleString('zh-CN', { value.toLocaleString("zh-CN", {
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 2, maximumFractionDigits: 2,
}) + ' 亿元' }) + " 元"
) );
} };
// 否则显示万元
return (
value.toLocaleString('zh-CN', {
minimumFractionDigits: 0,
maximumFractionDigits: 2,
}) + ' 万元'
)
}
// 获取案件状态样式 // 获取案件状态样式
export const getCaseStatusClass = status => { export const getCaseStatusClass = (status) => {
if (!status) return 'bg-gray-100 text-gray-500' if (!status) return "bg-gray-100 text-gray-500";
if (status.includes('已结') || status.includes('已办结')) { if (status.includes("已结") || status.includes("已办结")) {
return 'bg-green-50 text-green-600' return "bg-green-50 text-green-600";
} else if (status.includes('执行中') || status.includes('审理中')) { } else if (status.includes("执行中") || status.includes("审理中")) {
return 'bg-blue-50 text-blue-600' return "bg-blue-50 text-blue-600";
} else if (status.includes('未执行')) { } else if (status.includes("未执行")) {
return 'bg-amber-50 text-amber-600' return "bg-amber-50 text-amber-600";
} else { } else {
return 'bg-gray-100 text-gray-500' return "bg-gray-100 text-gray-500";
} }
} };
// 获取企业状态对应的样式 // 获取企业状态对应的样式
export const getStatusClass = status => { export const getStatusClass = (status) => {
if (!status) return 'bg-gray-100 text-gray-500' if (!status) return "bg-gray-100 text-gray-500";
if (status.includes('注销') || status.includes('吊销')) { if (status.includes("注销") || status.includes("吊销")) {
return 'bg-red-50 text-red-600' return "bg-red-50 text-red-600";
} else if (status.includes('存续') || status.includes('在营')) { } else if (status.includes("存续") || status.includes("在营")) {
return 'bg-green-50 text-green-600' return "bg-green-50 text-green-600";
} else if (status.includes('筹建') || status.includes('新设')) { } else if (status.includes("筹建") || status.includes("新设")) {
return 'bg-blue-50 text-blue-600' return "bg-blue-50 text-blue-600";
} else { } else {
return 'bg-yellow-50 text-yellow-600' return "bg-yellow-50 text-yellow-600";
} }
} };
// 格式化资本金额显示 // 格式化资本金额显示
export const formatCapital = (capital, currency) => { export const formatCapital = (capital, currency) => {
if (!capital) return '—' if (!capital) return "—";
// 检查是否包含"万"字或需要显示为万元 // 检查是否包含"万"字或需要显示为万元
let unit = '' let unit = "";
let value = parseFloat(capital) let value = parseFloat(capital);
// 处理原始数据中可能带有的单位 // 处理原始数据中可能带有的单位
if (typeof capital === 'string' && capital.includes('万')) { if (typeof capital === "string" && capital.includes("万")) {
unit = '万' unit = "万";
// 提取数字部分 // 提取数字部分
const numMatch = capital.match(/[\d.]+/) const numMatch = capital.match(/[\d.]+/);
value = numMatch ? parseFloat(numMatch[0]) : 0 value = numMatch ? parseFloat(numMatch[0]) : 0;
} else if (value >= 10000) { } else if (value >= 10000) {
// 大额数字转换为万元显示 // 大额数字转换为万元显示
value = value / 10000 value = value / 10000;
unit = '万' unit = "万";
} }
// 格式化数字,保留两位小数(如果有小数部分) // 格式化数字,保留两位小数(如果有小数部分)
const formattedValue = value.toLocaleString('zh-CN', { const formattedValue = value.toLocaleString("zh-CN", {
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 2, maximumFractionDigits: 2,
}) });
return `${formattedValue}${unit} ${currency || '人民币'}` return `${formattedValue}${unit} ${currency || "人民币"}`;
} };
// 获取涉诉风险等级 // 获取涉诉风险等级
export const getRiskLevel = lawsuitInfo => { export const getRiskLevel = (lawsuitInfo) => {
if (!lawsuitInfo) { if (!lawsuitInfo) {
return {
level: "low",
text: "低风险",
color: "text-green-600 bg-green-50",
};
}
// 失信被执行人是最高风险
if (lawsuitInfo.breachCaseList && lawsuitInfo.breachCaseList.length > 0) {
return {
level: "high",
text: "高风险",
color: "text-red-600 bg-red-50",
};
}
// 限高被执行人是最高风险
if (
lawsuitInfo.consumptionRestrictionList &&
lawsuitInfo.consumptionRestrictionList.length > 0
) {
return {
level: "high",
text: "高风险",
color: "text-red-600 bg-red-50",
};
}
// 有涉诉数据的风险级别
if (
lawsuitInfo.lawsuitStat &&
Object.keys(lawsuitInfo.lawsuitStat).length > 0
) {
// 检查是否有未结案的案件
const data = lawsuitInfo.lawsuitStat;
if (
data.count &&
data.count.count_wei_total &&
data.count.count_wei_total > 0
) {
return {
level: "medium",
text: "中风险",
color: "text-amber-600 bg-amber-50",
};
}
// 只有已结案的为低中风险
return {
level: "low-medium",
text: "低中风险",
color: "text-yellow-600 bg-yellow-50",
};
}
return { return {
level: 'low', level: "low",
text: '低风险', text: "低风险",
color: 'text-green-600 bg-green-50', color: "text-green-600 bg-green-50",
} };
} };
// 失信被执行人是最高风险
if (lawsuitInfo.breachCaseList && lawsuitInfo.breachCaseList.length > 0) {
return {
level: 'high',
text: '高风险',
color: 'text-red-600 bg-red-50',
}
}
// 限高被执行人是最高风险
if (lawsuitInfo.consumptionRestrictionList && lawsuitInfo.consumptionRestrictionList.length > 0) {
return {
level: 'high',
text: '高风险',
color: 'text-red-600 bg-red-50',
}
}
// 有涉诉数据的风险级别
if (lawsuitInfo.lawsuitStat && Object.keys(lawsuitInfo.lawsuitStat).length > 0) {
// 检查是否有未结案的案件
const data = lawsuitInfo.lawsuitStat
if (data.count && data.count.count_wei_total && data.count.count_wei_total > 0) {
return {
level: 'medium',
text: '中风险',
color: 'text-amber-600 bg-amber-50',
}
}
// 只有已结案的为低中风险
return {
level: 'low-medium',
text: '低中风险',
color: 'text-yellow-600 bg-yellow-50',
}
}
return {
level: 'low',
text: '低风险',
color: 'text-green-600 bg-green-50',
}
}
// 获取涉诉案件统计 // 获取涉诉案件统计
export const getLawsuitStats = lawsuitInfo => { export const getLawsuitStats = (lawsuitInfo) => {
if (!lawsuitInfo) return null if (!lawsuitInfo) return null;
const stats = { const stats = {
total: 0, total: 0,
types: [], types: [],
} };
// 统计各类型案件数量 // 统计各类型案件数量
Object.keys(lawsuitTypeMap).forEach(type => { Object.keys(lawsuitTypeMap).forEach((type) => {
let count = 0 let count = 0;
if (type === 'breachCase') { if (type === "breachCase") {
count = lawsuitInfo.breachCaseList && lawsuitInfo.breachCaseList.length > 0 ? lawsuitInfo.breachCaseList.length : 0 count =
} else if (type === 'consumptionRestriction') { lawsuitInfo.breachCaseList &&
count = lawsuitInfo.consumptionRestrictionList && lawsuitInfo.consumptionRestrictionList.length > 0 ? lawsuitInfo.consumptionRestrictionList.length : 0 lawsuitInfo.breachCaseList.length > 0
} else if (lawsuitInfo.lawsuitStat && lawsuitInfo.lawsuitStat[type] && Object.keys(lawsuitInfo.lawsuitStat[type]).length > 0) { ? lawsuitInfo.breachCaseList.length
const typeData = lawsuitInfo.lawsuitStat[type] : 0;
count = typeData.cases && typeData.cases.length ? typeData.cases.length : 0 } else if (type === "consumptionRestriction") {
} count =
lawsuitInfo.consumptionRestrictionList &&
lawsuitInfo.consumptionRestrictionList.length > 0
? lawsuitInfo.consumptionRestrictionList.length
: 0;
} else if (
lawsuitInfo.lawsuitStat &&
lawsuitInfo.lawsuitStat[type] &&
Object.keys(lawsuitInfo.lawsuitStat[type]).length > 0
) {
const typeData = lawsuitInfo.lawsuitStat[type];
count =
typeData.cases && typeData.cases.length
? typeData.cases.length
: 0;
}
if (count > 0) { if (count > 0) {
stats.total += count stats.total += count;
stats.types.push({ stats.types.push({
type, type,
count, count,
name: getCaseTypeText(type), name: getCaseTypeText(type),
color: getCaseTypeColor(type), color: getCaseTypeColor(type),
darkColor: getCaseTypeDarkColor(type), darkColor: getCaseTypeDarkColor(type),
}) });
} }
}) });
return stats return stats;
} };
// 获取案件类型优先级顺序 // 获取案件类型优先级顺序
export const getCaseTypePriority = () => { export const getCaseTypePriority = () => {
return [ return [
'breachCase', // 失信被执行人(最高风险) "breachCase", // 失信被执行人(最高风险)
'consumptionRestriction', // 限高被执行人 "consumptionRestriction", // 限高被执行人
'criminal', // 刑事案件 "criminal", // 刑事案件
'civil', // 民事案件 "civil", // 民事案件
'administrative', // 行政案件 "administrative", // 行政案件
'implement', // 执行案件 "implement", // 执行案件
'bankrupt', // 强制清算与破产案件 "bankrupt", // 强制清算与破产案件
'preservation', // 非诉保全审查 "preservation", // 非诉保全审查
] ];
} };
// 根据案件类型获取风险等级 // 根据案件类型获取风险等级
export const getCaseTypeRiskLevel = caseType => { export const getCaseTypeRiskLevel = (caseType) => {
const typeInfo = lawsuitTypeMap[caseType] const typeInfo = lawsuitTypeMap[caseType];
if (!typeInfo) { if (!typeInfo) {
return { return {
level: 'low', level: "low",
text: '低风险', text: "低风险",
color: 'text-green-600 bg-green-50', color: "text-green-600 bg-green-50",
};
} }
}
const riskLevelMap = { const riskLevelMap = {
high: { high: {
text: '高风险', text: "高风险",
color: 'text-red-600 bg-red-50', color: "text-red-600 bg-red-50",
}, },
medium: { medium: {
text: '中风险', text: "中风险",
color: 'text-amber-600 bg-amber-50', color: "text-amber-600 bg-amber-50",
}, },
low: { low: {
text: '低风险', text: "低风险",
color: 'text-green-600 bg-green-50', color: "text-green-600 bg-green-50",
}, },
} };
return {
level: typeInfo.riskLevel,
...riskLevelMap[typeInfo.riskLevel],
}
}
return {
level: typeInfo.riskLevel,
...riskLevelMap[typeInfo.riskLevel],
};
};

View File

@@ -18,6 +18,7 @@ export default defineConfig({
target: "http://127.0.0.1:8888", // 本地接口地址 target: "http://127.0.0.1:8888", // 本地接口地址
// target: "https://quannengcha.com", // 本地接口地址 // target: "https://quannengcha.com", // 本地接口地址
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path, // 可选:确保路径不被修改
}, },
}, },
}, },