f
This commit is contained in:
@@ -1,481 +1,524 @@
|
|||||||
<script setup lang="ts">
|
<script setup>
|
||||||
import { computed } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
import { useRiskNotifier } from '@/composables/useRiskNotifier';
|
||||||
|
|
||||||
// 接收父组件传入的 props
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: Object,
|
data: { type: Object, default: () => ({}) },
|
||||||
params: Object,
|
params: { type: Object, default: () => ({}) },
|
||||||
|
apiId: { type: String, default: '' },
|
||||||
|
index: { type: Number, default: 0 },
|
||||||
|
notifyRiskStatus: { type: Function, default: () => { } },
|
||||||
});
|
});
|
||||||
|
|
||||||
// 定义组件名称,用于在控制台输出调试信息
|
const periodTab = ref('threeYears'); // 近三年 | 近五年
|
||||||
const componentName = 'IVYZ0S0D';
|
|
||||||
|
|
||||||
// 将 props.data 赋值给 reportData 变量
|
// 支持 data 或 data.result(接口返回的 result 对象)
|
||||||
let reportData: any = props.data || {};
|
const result = computed(() => props.data?.result ?? props.data ?? {});
|
||||||
|
|
||||||
// 如果 reportData 不为空,则将其赋值给变量
|
const getStatusText = (value) => {
|
||||||
if (reportData) {
|
|
||||||
console.log(`${componentName} 组件接收到的数据:`, reportData);
|
|
||||||
} else {
|
|
||||||
console.log(`${componentName} 组件未接收到数据`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取状态描述文本
|
|
||||||
const getStatusText = (value: number) => {
|
|
||||||
if (value === 1) return '未命中';
|
if (value === 1) return '未命中';
|
||||||
if (value === 2) return '命中';
|
if (value === 2) return '命中';
|
||||||
return '未知';
|
return '—';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取通知函状态描述文本
|
// 获取通知函期间描述文本(支持数字或字符串如 "2")
|
||||||
const getNoticeLetterStatusText = (value: number) => {
|
const getNoticeLetterPeriodText = (period) => {
|
||||||
if (value === 1) return '未命中';
|
const p = Number(period);
|
||||||
if (value === 2) return '命中';
|
const periodMap = { 0: '没有被发送通知函', 1: '近2年内', 2: '2-4年', 3: '5年以上' };
|
||||||
return '未知';
|
return periodMap[p] ?? '—';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取通知函期间描述文本
|
|
||||||
const getNoticeLetterPeriodText = (period: number) => {
|
|
||||||
const periodMap: Record<number, string> = {
|
|
||||||
0: '没有被发送通知函',
|
|
||||||
1: '近2年内',
|
|
||||||
2: '2-4年',
|
|
||||||
3: '5年以上'
|
|
||||||
};
|
|
||||||
|
|
||||||
return periodMap[period] || '未知期间';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取背景颜色
|
|
||||||
const getBackgroundColor = (value: number) => {
|
|
||||||
if (value === 1) return '#e8f5e8'; // 浅绿色
|
|
||||||
if (value === 2) return '#ffe8e8'; // 浅红色
|
|
||||||
return '#f5f5f5'; // 默认灰色
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取边框颜色
|
|
||||||
const getBorderColor = (value: number) => {
|
|
||||||
if (value === 1) return '#4caf50'; // 绿色边框
|
|
||||||
if (value === 2) return '#f44336'; // 红色边框
|
|
||||||
return '#ccc'; // 默认灰色边框
|
|
||||||
};
|
|
||||||
|
|
||||||
// 判断是否应该隐藏该条目(如果是带时间范围的"未命中")
|
|
||||||
const shouldHideItem = (itemText: string) => {
|
|
||||||
// 检查是否包含时间范围关键词并且结果是"未命中"
|
|
||||||
const timeRangeKeywords = ['近2年', '近3年', '近4年', '近5年', '2-4年', '5年以上'];
|
|
||||||
const isTimeRangeItem = timeRangeKeywords.some(keyword => itemText.includes(keyword));
|
|
||||||
const isNoRisk = itemText.includes('未命中');
|
|
||||||
|
|
||||||
// 如果是时间范围项目且结果是"未命中",则隐藏
|
|
||||||
return isTimeRangeItem && isNoRisk;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取风险类型数组 - 所有模块都显示
|
|
||||||
const riskTypes = computed(() => {
|
|
||||||
const risks: {title: string, value: number, details: string | string[], bgColor: string, borderColor: string}[] = [];
|
|
||||||
|
|
||||||
// 总体风险
|
|
||||||
if (reportData.risk_flag !== undefined) {
|
|
||||||
risks.push({
|
|
||||||
title: '总体风险',
|
|
||||||
value: reportData.risk_flag,
|
|
||||||
details: getStatusText(reportData.risk_flag),
|
|
||||||
bgColor: getBackgroundColor(reportData.risk_flag),
|
|
||||||
borderColor: getBorderColor(reportData.risk_flag)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 失信风险
|
|
||||||
if (reportData.dishonesty && reportData.dishonesty.dishonesty !== undefined) {
|
|
||||||
risks.push({
|
|
||||||
title: '失信风险',
|
|
||||||
value: reportData.dishonesty.dishonesty,
|
|
||||||
details: getStatusText(reportData.dishonesty.dishonesty),
|
|
||||||
bgColor: getBackgroundColor(reportData.dishonesty.dishonesty),
|
|
||||||
borderColor: getBorderColor(reportData.dishonesty.dishonesty)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 高消费限制风险
|
|
||||||
if (reportData.high_consumption && reportData.high_consumption.high_consumption !== undefined) {
|
|
||||||
risks.push({
|
|
||||||
title: '高消费限制风险',
|
|
||||||
value: reportData.high_consumption.high_consumption,
|
|
||||||
details: getStatusText(reportData.high_consumption.high_consumption),
|
|
||||||
bgColor: getBackgroundColor(reportData.high_consumption.high_consumption),
|
|
||||||
borderColor: getBorderColor(reportData.high_consumption.high_consumption)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 劳动争议风险
|
|
||||||
if (reportData.labor_disputes) {
|
|
||||||
let details: string[] = [];
|
|
||||||
if (reportData.labor_disputes.labor_disputes !== undefined) {
|
|
||||||
details.push(`当前: ${getStatusText(reportData.labor_disputes.labor_disputes)}`);
|
|
||||||
}
|
|
||||||
if (reportData.labor_disputes.labor_disputes_3y !== undefined) {
|
|
||||||
const detail = `近3年: ${getStatusText(reportData.labor_disputes.labor_disputes_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.labor_disputes.labor_disputes_5y !== undefined) {
|
|
||||||
const detail = `近5年: ${getStatusText(reportData.labor_disputes.labor_disputes_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.labor_disputes.labor_contract !== undefined) {
|
|
||||||
details.push(`劳动合同: ${getStatusText(reportData.labor_disputes.labor_contract)}`);
|
|
||||||
}
|
|
||||||
if (reportData.labor_disputes.labor_relation !== undefined) {
|
|
||||||
details.push(`劳动关系: ${getStatusText(reportData.labor_disputes.labor_relation)}`);
|
|
||||||
}
|
|
||||||
if (reportData.labor_disputes.labor_relation_3y !== undefined) {
|
|
||||||
const detail = `近3年劳动关系: ${getStatusText(reportData.labor_disputes.labor_relation_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.labor_disputes.labor_relation_5y !== undefined) {
|
|
||||||
const detail = `近5年劳动关系: ${getStatusText(reportData.labor_disputes.labor_relation_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (details.length > 0) {
|
|
||||||
risks.push({
|
|
||||||
title: '劳动争议风险',
|
|
||||||
value: Math.max(...Object.values(reportData.labor_disputes).filter(v => typeof v === 'number')),
|
|
||||||
details: details,
|
|
||||||
bgColor: getBackgroundColor(Math.max(...Object.values(reportData.labor_disputes).filter(v => typeof v === 'number'))),
|
|
||||||
borderColor: getBorderColor(Math.max(...Object.values(reportData.labor_disputes).filter(v => typeof v === 'number')))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 社会保险纠纷风险
|
|
||||||
if (reportData.social_insurance) {
|
|
||||||
let details: string[] = [];
|
|
||||||
if (reportData.social_insurance.social_insurance !== undefined) {
|
|
||||||
details.push(`社保纠纷: ${getStatusText(reportData.social_insurance.social_insurance)}`);
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.pension !== undefined) {
|
|
||||||
details.push(`养老纠纷: ${getStatusText(reportData.social_insurance.pension)}`);
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.pension_3y !== undefined) {
|
|
||||||
const detail = `近3年养老: ${getStatusText(reportData.social_insurance.pension_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.pension_5y !== undefined) {
|
|
||||||
const detail = `近5年养老: ${getStatusText(reportData.social_insurance.pension_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.injury_insurance !== undefined) {
|
|
||||||
details.push(`工伤纠纷: ${getStatusText(reportData.social_insurance.injury_insurance)}`);
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.injury_insurance_3y !== undefined) {
|
|
||||||
const detail = `近3年工伤: ${getStatusText(reportData.social_insurance.injury_insurance_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.injury_insurance_5y !== undefined) {
|
|
||||||
const detail = `近5年工伤: ${getStatusText(reportData.social_insurance.injury_insurance_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.unemployment_insurance !== undefined) {
|
|
||||||
details.push(`失业纠纷: ${getStatusText(reportData.social_insurance.unemployment_insurance)}`);
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.unemployment_insurance_3y !== undefined) {
|
|
||||||
const detail = `近3年失业: ${getStatusText(reportData.social_insurance.unemployment_insurance_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.unemployment_insurance_5y !== undefined) {
|
|
||||||
const detail = `近5年失业: ${getStatusText(reportData.social_insurance.unemployment_insurance_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.medical_insurance !== undefined) {
|
|
||||||
details.push(`医疗纠纷: ${getStatusText(reportData.social_insurance.medical_insurance)}`);
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.medical_insurance_3y !== undefined) {
|
|
||||||
const detail = `近3年医疗: ${getStatusText(reportData.social_insurance.medical_insurance_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.medical_insurance_5y !== undefined) {
|
|
||||||
const detail = `近5年医疗: ${getStatusText(reportData.social_insurance.medical_insurance_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.maternity_insurance !== undefined) {
|
|
||||||
details.push(`生育纠纷: ${getStatusText(reportData.social_insurance.maternity_insurance)}`);
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.maternity_insurance_3y !== undefined) {
|
|
||||||
const detail = `近3年生育: ${getStatusText(reportData.social_insurance.maternity_insurance_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.social_insurance.maternity_insurance_5y !== undefined) {
|
|
||||||
const detail = `近5年生育: ${getStatusText(reportData.social_insurance.maternity_insurance_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (details.length > 0) {
|
|
||||||
risks.push({
|
|
||||||
title: '社会保险纠纷风险',
|
|
||||||
value: Math.max(...Object.values(reportData.social_insurance).filter(v => typeof v === 'number')),
|
|
||||||
details: details,
|
|
||||||
bgColor: getBackgroundColor(Math.max(...Object.values(reportData.social_insurance).filter(v => typeof v === 'number'))),
|
|
||||||
borderColor: getBorderColor(Math.max(...Object.values(reportData.social_insurance).filter(v => typeof v === 'number')))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 福利待遇纠纷
|
|
||||||
if (reportData.welfare_disputes && reportData.welfare_disputes.welfare !== undefined) {
|
|
||||||
risks.push({
|
|
||||||
title: '福利待遇纠纷',
|
|
||||||
value: reportData.welfare_disputes.welfare,
|
|
||||||
details: getStatusText(reportData.welfare_disputes.welfare),
|
|
||||||
bgColor: getBackgroundColor(reportData.welfare_disputes.welfare),
|
|
||||||
borderColor: getBorderColor(reportData.welfare_disputes.welfare)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 人事争议类纠纷
|
|
||||||
if (reportData.personnel_disputes) {
|
|
||||||
let details: string[] = [];
|
|
||||||
if (reportData.personnel_disputes.personnel_dispute !== undefined) {
|
|
||||||
details.push(`人事争议: ${getStatusText(reportData.personnel_disputes.personnel_dispute)}`);
|
|
||||||
}
|
|
||||||
if (reportData.personnel_disputes.resignation_dispute !== undefined) {
|
|
||||||
details.push(`辞职争议: ${getStatusText(reportData.personnel_disputes.resignation_dispute)}`);
|
|
||||||
}
|
|
||||||
if (reportData.personnel_disputes.resignation_dispute_3y !== undefined) {
|
|
||||||
const detail = `近3年辞职: ${getStatusText(reportData.personnel_disputes.resignation_dispute_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.personnel_disputes.resignation_dispute_5y !== undefined) {
|
|
||||||
const detail = `近5年辞职: ${getStatusText(reportData.personnel_disputes.resignation_dispute_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.personnel_disputes.dismissal_dispute !== undefined) {
|
|
||||||
details.push(`辞退争议: ${getStatusText(reportData.personnel_disputes.dismissal_dispute)}`);
|
|
||||||
}
|
|
||||||
if (reportData.personnel_disputes.dismissal_dispute_3y !== undefined) {
|
|
||||||
const detail = `近3年辞退: ${getStatusText(reportData.personnel_disputes.dismissal_dispute_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.personnel_disputes.dismissal_dispute_5y !== undefined) {
|
|
||||||
const detail = `近5年辞退: ${getStatusText(reportData.personnel_disputes.dismissal_dispute_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (details.length > 0) {
|
|
||||||
risks.push({
|
|
||||||
title: '人事争议类纠纷',
|
|
||||||
value: Math.max(...Object.values(reportData.personnel_disputes).filter(v => typeof v === 'number')),
|
|
||||||
details: details,
|
|
||||||
bgColor: getBackgroundColor(Math.max(...Object.values(reportData.personnel_disputes).filter(v => typeof v === 'number'))),
|
|
||||||
borderColor: getBorderColor(Math.max(...Object.values(reportData.personnel_disputes).filter(v => typeof v === 'number')))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 仲裁相关案件
|
|
||||||
if (reportData.arbitration) {
|
|
||||||
let details: string[] = [];
|
|
||||||
if (reportData.arbitration.arbitration_confirmation !== undefined) {
|
|
||||||
details.push(`仲裁确认: ${getStatusText(reportData.arbitration.arbitration_confirmation)}`);
|
|
||||||
}
|
|
||||||
if (reportData.arbitration.arbitration_confirmation_3y !== undefined) {
|
|
||||||
const detail = `近3年仲裁确认: ${getStatusText(reportData.arbitration.arbitration_confirmation_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.arbitration.arbitration_confirmation_5y !== undefined) {
|
|
||||||
const detail = `近5年仲裁确认: ${getStatusText(reportData.arbitration.arbitration_confirmation_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.arbitration.arbitration_revocation !== undefined) {
|
|
||||||
details.push(`仲裁撤销: ${getStatusText(reportData.arbitration.arbitration_revocation)}`);
|
|
||||||
}
|
|
||||||
if (reportData.arbitration.arbitration_revocation_3y !== undefined) {
|
|
||||||
const detail = `近3年仲裁撤销: ${getStatusText(reportData.arbitration.arbitration_revocation_3y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reportData.arbitration.arbitration_revocation_5y !== undefined) {
|
|
||||||
const detail = `近5年仲裁撤销: ${getStatusText(reportData.arbitration.arbitration_revocation_5y)}`;
|
|
||||||
if (!shouldHideItem(detail)) {
|
|
||||||
details.push(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (details.length > 0) {
|
|
||||||
risks.push({
|
|
||||||
title: '仲裁相关案件',
|
|
||||||
value: Math.max(...Object.values(reportData.arbitration).filter(v => typeof v === 'number')),
|
|
||||||
details: details,
|
|
||||||
bgColor: getBackgroundColor(Math.max(...Object.values(reportData.arbitration).filter(v => typeof v === 'number'))),
|
|
||||||
borderColor: getBorderColor(Math.max(...Object.values(reportData.arbitration).filter(v => typeof v === 'number')))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通知函触达
|
|
||||||
if (reportData.notice_letter && reportData.notice_letter.notice_letter !== undefined) {
|
|
||||||
let statusText = getNoticeLetterStatusText(reportData.notice_letter.notice_letter);
|
|
||||||
let periodText = '';
|
|
||||||
|
|
||||||
if (reportData.notice_letter.notice_letter_period !== undefined) {
|
|
||||||
periodText = `期间: ${getNoticeLetterPeriodText(reportData.notice_letter.notice_letter_period)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const detailParts = [`状态: ${statusText}`];
|
|
||||||
if (periodText) {
|
|
||||||
detailParts.push(periodText);
|
|
||||||
}
|
|
||||||
|
|
||||||
risks.push({
|
|
||||||
title: '通知函触达',
|
|
||||||
value: reportData.notice_letter.notice_letter,
|
|
||||||
details: detailParts,
|
|
||||||
bgColor: getBackgroundColor(reportData.notice_letter.notice_letter),
|
|
||||||
borderColor: getBorderColor(reportData.notice_letter.notice_letter)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return risks;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 检查是否至少有一个数据类别有内容
|
// 检查是否至少有一个数据类别有内容
|
||||||
const hasAnyData = computed(() => {
|
const hasAnyData = computed(() => {
|
||||||
return riskTypes.value.length > 0;
|
const r = result.value;
|
||||||
|
return Object.keys(r).length > 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 汇总数据 - 按分类分组 { key, title, rows }
|
||||||
|
const summaryGroups = computed(() => {
|
||||||
|
const groups = [];
|
||||||
|
const basic = result.value.basic_info;
|
||||||
|
if (basic?.risk_flag !== undefined) {
|
||||||
|
groups.push({ key: 'basic', title: '基础风险', rows: [{ label: '该人员是否有风险', value: basic.risk_flag }] });
|
||||||
|
}
|
||||||
|
const dishonesty = result.value.dishonesty?.dishonesty;
|
||||||
|
const highConsumption = result.value.high_consumption?.high_consumption;
|
||||||
|
if (dishonesty !== undefined || highConsumption !== undefined) {
|
||||||
|
const rows = [];
|
||||||
|
if (dishonesty !== undefined) rows.push({ label: '失信人员风险', value: dishonesty });
|
||||||
|
if (highConsumption !== undefined) rows.push({ label: '限制高消费人员风险', value: highConsumption });
|
||||||
|
groups.push({ key: 'credit', title: '失信限高', rows });
|
||||||
|
}
|
||||||
|
const labor = result.value.labor_disputes;
|
||||||
|
if (labor) {
|
||||||
|
const items = [['劳动争议', labor.labor_disputes], ['劳动合同纠纷', labor.labor_contract], ['劳动关系纠纷', labor.labor_relation], ['追索劳动报酬纠纷', labor.wage_claim], ['经济补偿金纠纷', labor.compensation], ['集体合同纠纷', labor.collective_contract], ['劳务派遣合同纠纷', labor.dispatch_contract], ['非全日制用工纠纷', labor.part_time], ['竞业限制纠纷', labor.non_compete]];
|
||||||
|
const rows = items.filter((item) => item[1] !== undefined).map((item) => ({ label: item[0], value: item[1] }));
|
||||||
|
if (rows.length) groups.push({ key: 'labor', title: '劳动争议', rows });
|
||||||
|
}
|
||||||
|
const social = result.value.social_insurance;
|
||||||
|
if (social) {
|
||||||
|
const items = [['社会保险纠纷', social.social_insurance], ['养老保险待遇纠纷', social.pension], ['工伤保险待遇纠纷', social.injury_insurance], ['医疗保险待遇纠纷', social.medical_insurance], ['生育保险待遇纠纷', social.maternity_insurance], ['商业保险待遇纠纷', social.commercial_insurance]];
|
||||||
|
const rows = items.filter((item) => item[1] !== undefined).map((item) => ({ label: item[0], value: item[1] }));
|
||||||
|
if (rows.length) groups.push({ key: 'social', title: '社会保险', rows });
|
||||||
|
}
|
||||||
|
if (result.value.welfare_disputes?.welfare !== undefined) {
|
||||||
|
groups.push({ key: 'welfare', title: '福利待遇', rows: [{ label: '福利待遇纠纷', value: result.value.welfare_disputes.welfare }] });
|
||||||
|
}
|
||||||
|
const personnel = result.value.personnel_disputes;
|
||||||
|
if (personnel) {
|
||||||
|
const items = [['人事争议类纠纷', personnel.personnel_dispute], ['辞职争议纠纷', personnel.resignation_dispute], ['辞退争议纠纷', personnel.dismissal_dispute], ['聘用合同争议纠纷', personnel.employment_contract]];
|
||||||
|
const rows = items.filter((item) => item[1] !== undefined).map((item) => ({ label: item[0], value: item[1] }));
|
||||||
|
if (rows.length) groups.push({ key: 'personnel', title: '人事争议', rows });
|
||||||
|
}
|
||||||
|
const arb = result.value.arbitration;
|
||||||
|
if (arb && (arb.arbitration_confirmation !== undefined || arb.arbitration_revocation !== undefined)) {
|
||||||
|
const rows = [];
|
||||||
|
if (arb.arbitration_confirmation !== undefined) rows.push({ label: '申请仲裁确认', value: arb.arbitration_confirmation });
|
||||||
|
if (arb.arbitration_revocation !== undefined) rows.push({ label: '撤销仲裁裁决', value: arb.arbitration_revocation });
|
||||||
|
groups.push({ key: 'arbitration', title: '仲裁流程', rows });
|
||||||
|
}
|
||||||
|
const notice = result.value.notice_letter;
|
||||||
|
if (notice?.notice_letter !== undefined) {
|
||||||
|
const rows = [{ label: '通知函触达', value: notice.notice_letter }];
|
||||||
|
if (notice.notice_letter_period !== undefined && notice.notice_letter === 2) rows.push({ label: '通知函发送时间', value: null, period: notice.notice_letter_period });
|
||||||
|
groups.push({ key: 'notice', title: '通知函触达', rows });
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
});
|
||||||
|
|
||||||
|
const summaryRows = computed(() => summaryGroups.value.flatMap((g) => g.rows));
|
||||||
|
|
||||||
|
// 真正的风险项(文档:失信限高、劳动争议、社会保险、福利待遇、人事争议、仲裁流程、通知函触达)
|
||||||
|
// 排除 basic_info.risk_flag(汇总结论)和 notice_letter_period(非风险项)
|
||||||
|
const riskItemRows = computed(() =>
|
||||||
|
summaryGroups.value
|
||||||
|
.filter((g) => g.key !== 'basic')
|
||||||
|
.flatMap((g) => g.rows)
|
||||||
|
.filter((r) => r.value === 1 || r.value === 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 近三年/近五年 - 按分类分组
|
||||||
|
const periodGroups = computed(() => {
|
||||||
|
const suffix = periodTab.value === 'threeYears' ? '_3y' : '_5y';
|
||||||
|
const groups = [];
|
||||||
|
const labor = result.value.labor_disputes;
|
||||||
|
if (labor) {
|
||||||
|
const keys = ['labor_disputes', 'labor_relation', 'wage_claim', 'compensation', 'collective_contract', 'dispatch_contract', 'part_time', 'non_compete'];
|
||||||
|
const labels = ['劳动争议', '劳动关系', '追索劳动报酬', '经济补偿金', '集体合同', '劳务派遣', '非全日制用工', '竞业限制'];
|
||||||
|
const rows = keys.map((k, i) => ({ label: labels[i], value: labor[k + suffix] })).filter((r) => r.value === 2).map((r) => ({ label: r.label, value: 2 }));
|
||||||
|
if (rows.length) groups.push({ key: 'labor', title: '劳动争议', rows });
|
||||||
|
}
|
||||||
|
const social = result.value.social_insurance;
|
||||||
|
if (social) {
|
||||||
|
const keys = ['pension', 'injury_insurance', 'medical_insurance', 'maternity_insurance', 'commercial_insurance'];
|
||||||
|
const labels = ['养老保险', '工伤保险', '医疗保险', '生育保险', '商业保险'];
|
||||||
|
const rows = keys.map((k, i) => ({ label: labels[i], value: social[k + suffix] })).filter((r) => r.value === 2).map((r) => ({ label: r.label, value: 2 }));
|
||||||
|
if (rows.length) groups.push({ key: 'social', title: '社会保险', rows });
|
||||||
|
}
|
||||||
|
const personnel = result.value.personnel_disputes;
|
||||||
|
if (personnel) {
|
||||||
|
const keys = ['resignation_dispute', 'dismissal_dispute', 'employment_contract'];
|
||||||
|
const labels = ['辞职争议', '辞退争议', '聘用合同'];
|
||||||
|
const rows = keys.map((k, i) => ({ label: labels[i], value: personnel[k + suffix] })).filter((r) => r.value === 2).map((r) => ({ label: r.label, value: 2 }));
|
||||||
|
if (rows.length) groups.push({ key: 'personnel', title: '人事争议', rows });
|
||||||
|
}
|
||||||
|
const arb = result.value.arbitration;
|
||||||
|
if (arb) {
|
||||||
|
const rows = [];
|
||||||
|
if (arb[`arbitration_confirmation${suffix}`] === 2) rows.push({ label: '申请仲裁确认', value: 2 });
|
||||||
|
if (arb[`arbitration_revocation${suffix}`] === 2) rows.push({ label: '撤销仲裁裁决', value: 2 });
|
||||||
|
if (rows.length) groups.push({ key: 'arbitration', title: '仲裁流程', rows });
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
});
|
||||||
|
|
||||||
|
const periodRows = computed(() => periodGroups.value.flatMap((g) => g.rows));
|
||||||
|
|
||||||
|
// 用于 riskScore:需要近三年+近五年全部数据
|
||||||
|
const recentThreeYearsRows = computed(() => {
|
||||||
|
const r = result.value;
|
||||||
|
const rows = [];
|
||||||
|
const labor = r.labor_disputes;
|
||||||
|
if (labor) {
|
||||||
|
[['labor_disputes_3y'], ['labor_relation_3y'], ['wage_claim_3y'], ['compensation_3y'], ['collective_contract_3y'], ['dispatch_contract_3y'], ['part_time_3y'], ['non_compete_3y']].forEach(([k]) => { if (labor[k] === 2) rows.push({ value: 2 }); });
|
||||||
|
}
|
||||||
|
const social = r.social_insurance;
|
||||||
|
if (social) {
|
||||||
|
['pension_3y', 'injury_insurance_3y', 'medical_insurance_3y', 'maternity_insurance_3y', 'commercial_insurance_3y'].forEach((k) => { if (social[k] === 2) rows.push({ value: 2 }); });
|
||||||
|
}
|
||||||
|
const personnel = r.personnel_disputes;
|
||||||
|
if (personnel) {
|
||||||
|
['resignation_dispute_3y', 'dismissal_dispute_3y', 'employment_contract_3y'].forEach((k) => { if (personnel[k] === 2) rows.push({ value: 2 }); });
|
||||||
|
}
|
||||||
|
const arb = r.arbitration;
|
||||||
|
if (arb) {
|
||||||
|
if (arb.arbitration_confirmation_3y === 2) rows.push({ value: 2 });
|
||||||
|
if (arb.arbitration_revocation_3y === 2) rows.push({ value: 2 });
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
});
|
||||||
|
const recentFiveYearsRows = computed(() => {
|
||||||
|
const r = result.value;
|
||||||
|
const rows = [];
|
||||||
|
const labor = r.labor_disputes;
|
||||||
|
if (labor) {
|
||||||
|
[['labor_disputes_5y'], ['labor_relation_5y'], ['wage_claim_5y'], ['compensation_5y'], ['collective_contract_5y'], ['dispatch_contract_5y'], ['part_time_5y'], ['non_compete_5y']].forEach(([k]) => { if (labor[k] === 2) rows.push({ value: 2 }); });
|
||||||
|
}
|
||||||
|
const social = r.social_insurance;
|
||||||
|
if (social) {
|
||||||
|
['pension_5y', 'injury_insurance_5y', 'medical_insurance_5y', 'maternity_insurance_5y', 'commercial_insurance_5y'].forEach((k) => { if (social[k] === 2) rows.push({ value: 2 }); });
|
||||||
|
}
|
||||||
|
const personnel = r.personnel_disputes;
|
||||||
|
if (personnel) {
|
||||||
|
['resignation_dispute_5y', 'dismissal_dispute_5y', 'employment_contract_5y'].forEach((k) => { if (personnel[k] === 2) rows.push({ value: 2 }); });
|
||||||
|
}
|
||||||
|
const arb = r.arbitration;
|
||||||
|
if (arb) {
|
||||||
|
if (arb.arbitration_confirmation_5y === 2) rows.push({ value: 2 });
|
||||||
|
if (arb.arbitration_revocation_5y === 2) rows.push({ value: 2 });
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 头部风险总结:风险类型、建议、命中统计(仅真正的风险项)
|
||||||
|
const riskSummary = computed(() => {
|
||||||
|
const basic = result.value.basic_info;
|
||||||
|
const hasRisk = basic?.risk_flag === 2;
|
||||||
|
|
||||||
|
// 真正的风险项:总项数、命中数(文档:失信限高、劳动争议、社会保险、福利待遇、人事争议、仲裁流程、通知函触达)
|
||||||
|
const totalItems = riskItemRows.value.length;
|
||||||
|
const hitItems = riskItemRows.value.filter((r) => r.value === 2).length;
|
||||||
|
|
||||||
|
// 命中的风险分类(汇总中 value=2 的 group)
|
||||||
|
const riskCategories = summaryGroups.value
|
||||||
|
.filter((g) => g.key !== 'basic' && g.rows.some((r) => r.value === 2))
|
||||||
|
.map((g) => g.title);
|
||||||
|
|
||||||
|
// 精简建议(取主要类型合并为一句)
|
||||||
|
const suggestionMap = {
|
||||||
|
'失信限高': '征信修复与限高事项',
|
||||||
|
'劳动争议': '劳动纠纷与薪酬离职',
|
||||||
|
'社会保险': '社保缴纳与补缴',
|
||||||
|
'福利待遇': '福利待遇合规',
|
||||||
|
'人事争议': '辞职辞退与聘用合同',
|
||||||
|
'仲裁流程': '仲裁案件进展',
|
||||||
|
'通知函触达': '仲裁调解涉诉通知',
|
||||||
|
};
|
||||||
|
const suggestionParts = riskCategories.map((c) => suggestionMap[c]).filter(Boolean);
|
||||||
|
const suggestion = suggestionParts.length ? `建议关注${suggestionParts.slice(0, 3).join('、')}。` : '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasRisk,
|
||||||
|
label: hasRisk ? '有风险' : '无风险',
|
||||||
|
riskCategories,
|
||||||
|
suggestion,
|
||||||
|
totalItems,
|
||||||
|
hitItems,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 风险评分 0-100,越高越安全(供 BaseReport 分析指数)
|
||||||
|
// 基于真正的风险项(riskItemRows),与展示逻辑一致,通过 useRiskNotifier 递交 BaseReport
|
||||||
|
const riskScore = computed(() => {
|
||||||
|
const basic = result.value.basic_info;
|
||||||
|
if (!basic || basic.risk_flag === 1) return 100;
|
||||||
|
const hitItems = riskItemRows.value.filter((r) => r.value === 2).length;
|
||||||
|
const score = 100 - hitItems * 2; // 每命中 1 项扣 2 分
|
||||||
|
return Math.max(0, Math.min(100, score));
|
||||||
|
});
|
||||||
|
useRiskNotifier(props, riskScore);
|
||||||
|
defineExpose({ riskScore });
|
||||||
|
|
||||||
|
// 借鉴司法涉诉概览:风险图标与背景样式
|
||||||
|
const getRiskIcon = () => {
|
||||||
|
if (riskSummary.value.hasRisk) return new URL('@/assets/images/report/gfx.png', import.meta.url).href;
|
||||||
|
return new URL('@/assets/images/report/zq.png', import.meta.url).href;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="ivyz0s0d-container">
|
<div class="report-wrap">
|
||||||
<!-- 风险卡片网格 -->
|
<!-- 头部风险总结(底色固定白色,命中项用内嵌 card 展现) -->
|
||||||
<div v-if="hasAnyData" class="risk-cards-grid">
|
<div v-if="hasAnyData" class="risk-summary card">
|
||||||
<div
|
<div class="flex items-center mb-4">
|
||||||
v-for="(risk, index) in riskTypes"
|
<div class="w-12 h-12 mr-3 flex-shrink-0">
|
||||||
:key="index"
|
<img :src="getRiskIcon()" alt="风险" class="w-12 h-12 object-contain" />
|
||||||
class="risk-card"
|
</div>
|
||||||
:style="{ backgroundColor: risk.bgColor, borderLeft: `4px solid ${risk.borderColor}` }"
|
<div class="text-gray-700 text-[15px] leading-relaxed">
|
||||||
>
|
<template v-if="riskSummary.hasRisk">
|
||||||
<div class="risk-card__content">
|
<span v-if="riskSummary.riskCategories.length">涉及{{ riskSummary.riskCategories.join('、')
|
||||||
<h4 class="risk-card__title">{{ risk.title }}</h4>
|
}};</span>
|
||||||
<div class="risk-card__status">
|
<span v-if="riskSummary.suggestion">{{ riskSummary.suggestion }}</span>
|
||||||
<!-- 当 details 是字符串时显示单行 -->
|
</template>
|
||||||
<p v-if="typeof risk.details === 'string'" class="risk-detail-item">{{ risk.details }}</p>
|
<template v-else>未检测到相关风险</template>
|
||||||
<!-- 当 details 是数组时,每项占一行 -->
|
</div>
|
||||||
<p
|
</div>
|
||||||
v-else
|
<!-- 命中项:仅显示总项数 / 命中数(真正的风险项:失信限高、劳动争议、社会保险、福利待遇、人事争议、仲裁流程、通知函触达) -->
|
||||||
v-for="(detail, idx) in risk.details"
|
<div v-if="riskSummary.totalItems > 0" class="inner-card p-4 rounded-xl text-center"
|
||||||
:key="idx"
|
:class="riskSummary.hitItems > 0 ? 'inner-card-risk' : 'inner-card-safe'">
|
||||||
class="risk-detail-item"
|
<div class="text-2xl font-bold mb-1"
|
||||||
>{{ detail }}</p>
|
:class="riskSummary.hitItems > 0 ? 'text-[#EB3C3C]' : 'text-[#10b981]'">
|
||||||
</div>
|
{{ riskSummary.hitItems }}/{{ riskSummary.totalItems }}
|
||||||
|
</div>
|
||||||
|
<div class="text-sm font-medium text-gray-800">命中项</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 无数据提示 -->
|
<!-- Card 1: 汇总 -->
|
||||||
<div v-if="!hasAnyData" class="no-data">
|
<section class="card">
|
||||||
<p>暂无相关风险数据</p>
|
<header class="card-header">
|
||||||
|
<span class="card-title">风险概览</span>
|
||||||
|
<span class="card-subtitle">综合评估结果</span>
|
||||||
|
</header>
|
||||||
|
<div v-if="hasAnyData" class="group-list">
|
||||||
|
<div v-for="(group, gi) in summaryGroups" :key="group.key" class="group-box">
|
||||||
|
<div class="group-header">
|
||||||
|
<span class="group-title">{{ group.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="group-body">
|
||||||
|
<div v-for="(row, ri) in group.rows" :key="ri" class="data-row">
|
||||||
|
<span class="data-label">{{ row.label }}</span>
|
||||||
|
<span v-if="row.period !== undefined" class="data-value data-value-text">{{
|
||||||
|
getNoticeLetterPeriodText(row.period) }}</span>
|
||||||
|
<span v-else
|
||||||
|
:class="['data-value', 'data-badge', row.value === 2 ? 'badge-risk' : 'badge-safe']">
|
||||||
|
<span class="badge-dot" :class="row.value === 2 ? 'dot-risk' : 'dot-safe'" />
|
||||||
|
{{ getStatusText(row.value) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="empty-state">
|
||||||
|
<span class="empty-icon">—</span>
|
||||||
|
<span class="empty-text">暂无相关风险数据</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Card 2: 近三年 / 近五年 -->
|
||||||
|
<section class="card">
|
||||||
|
<header class="card-header">
|
||||||
|
<span class="card-title">时间维度</span>
|
||||||
|
<span class="card-subtitle">按周期查看命中情况</span>
|
||||||
|
</header>
|
||||||
|
<div class="period-tabs">
|
||||||
|
<button type="button" :class="['period-tab', periodTab === 'threeYears' && 'active']"
|
||||||
|
@click="periodTab = 'threeYears'">近三年</button>
|
||||||
|
<button type="button" :class="['period-tab', periodTab === 'fiveYears' && 'active']"
|
||||||
|
@click="periodTab = 'fiveYears'">近五年</button>
|
||||||
|
</div>
|
||||||
|
<div v-if="periodGroups.length" class="group-list">
|
||||||
|
<div v-for="(group, gi) in periodGroups" :key="group.key" class="group-box">
|
||||||
|
<div class="group-header">
|
||||||
|
<span class="group-title">{{ group.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="group-body">
|
||||||
|
<div v-for="(row, ri) in group.rows" :key="ri" class="data-row">
|
||||||
|
<span class="data-label">{{ row.label }}</span>
|
||||||
|
<span class="data-value data-badge badge-risk">
|
||||||
|
<span class="badge-dot dot-risk" />
|
||||||
|
{{ getStatusText(row.value) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="empty-state">
|
||||||
|
<span class="empty-icon">—</span>
|
||||||
|
<span class="empty-text">暂无{{ periodTab === 'threeYears' ? '近三年' : '近五年' }}命中数据</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.ivyz0s0d-container {
|
.report-wrap {
|
||||||
padding: 20px;
|
display: flex;
|
||||||
font-family: Arial, sans-serif;
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-cards-grid {
|
.card {
|
||||||
display: grid;
|
background: #fff;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
border-radius: 12px;
|
||||||
gap: 15px;
|
padding: 16px;
|
||||||
margin-bottom: 20px;
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-card {
|
.inner-card {
|
||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 8px;
|
|
||||||
padding: 15px;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-card:hover {
|
.inner-card-risk {
|
||||||
transform: translateY(-2px);
|
background: rgba(235, 60, 60, 0.1);
|
||||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
border-color: rgba(235, 60, 60, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-card__content {
|
.inner-card-safe {
|
||||||
display: flex;
|
background: rgba(16, 185, 129, 0.1);
|
||||||
flex-direction: column;
|
border-color: rgba(16, 185, 129, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-card__title {
|
.card-header {
|
||||||
margin: 0 0 8px 0;
|
display: flex;
|
||||||
font-size: 16px;
|
flex-direction: column;
|
||||||
font-weight: bold;
|
gap: 2px;
|
||||||
color: #333;
|
margin-bottom: 14px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 1px solid #f1f5f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-card__status {
|
.card-title {
|
||||||
margin: 0;
|
font-size: 16px;
|
||||||
font-size: 14px;
|
font-weight: 600;
|
||||||
color: #666;
|
color: #1e293b;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-detail-item {
|
.card-subtitle {
|
||||||
margin: 0 0 4px 0;
|
font-size: 13px;
|
||||||
line-height: 1.4;
|
color: #94a3b8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.risk-detail-item:last-child {
|
.period-tabs {
|
||||||
margin-bottom: 0;
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
padding: 4px;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-data {
|
.period-tab {
|
||||||
text-align: center;
|
flex: 1;
|
||||||
color: #999;
|
padding: 10px 16px;
|
||||||
font-style: italic;
|
font-size: 15px;
|
||||||
padding: 20px;
|
color: #64748b;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.period-tab.active {
|
||||||
|
color: #1e293b;
|
||||||
|
font-weight: 500;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-box {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-header {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #475569;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-row:not(:last-child) {
|
||||||
|
border-bottom: 1px solid #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-label {
|
||||||
|
color: #475569;
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 12px;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-value {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-value-text {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-dot {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-risk {
|
||||||
|
background: #fff1f2;
|
||||||
|
color: #be123c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot-risk {
|
||||||
|
background: #e11d48;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-safe {
|
||||||
|
background: #f0fdf4;
|
||||||
|
color: #047857;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot-safe {
|
||||||
|
background: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 28px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #cbd5e1;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #94a3b8;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user