Files
report_viewer/src/ui/CQYGL66SL.vue
2026-05-13 11:01:42 +08:00

543 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="card">
<div class="header-box">
<h3 class="header-title">企业司法涉诉</h3>
<p class="header-desc">展示企业在全国法院公开信息中的涉诉情况</p>
<p v-if="entName" class="header-ent">被查询企业{{ entName }}</p>
</div>
<div v-if="hasCivilData" class="summary-section">
<div class="summary-row">
<div class="summary-card summary-risk">
<div class="summary-label">民事案件总数</div>
<div class="summary-value">{{ totalCivilCases }}</div>
<div class="summary-sub">
已结案 {{ civilClosedCases }} · 未结案 {{ civilPendingCases }}
</div>
</div>
<div class="summary-card summary-money">
<div class="summary-label">案件地域/案由概览</div>
<div class="summary-value small">
{{ civilAreaStat || '地域分布未知' }}
</div>
<div class="summary-sub">
{{ civilAyStat || '案由分布暂无统计' }}
</div>
</div>
</div>
<div class="tag-row" v-if="civilAreaStat || civilAyStat || civilJafsStat">
<span v-if="civilAreaStat" class="stat-tag">
涉案地域{{ civilAreaStat }}
</span>
<span v-if="civilAyStat" class="stat-tag">
案由分布{{ civilAyStat }}
</span>
<span v-if="civilJafsStat" class="stat-tag">
结案方式{{ civilJafsStat }}
</span>
</div>
</div>
<div v-if="civilCases.length" class="block">
<div class="block-title">民事案件列表</div>
<div class="case-list">
<div v-for="(item, index) in civilCases" :key="item.c_id || index" class="case-wrapper">
<div class="case-card">
<!-- 可点击的摘要区域参考 FLXG7E8F 样式 -->
<div class="case-summary" @click="toggleCaseExpand(item.c_id || index)">
<div class="summary-top">
<div class="summary-title">
<span class="case-no-text">
{{ item.c_ah || '暂无案号' }}
</span>
<span class="case-type-tag">
{{ item.n_ajlx || item.n_laay_tag || item.n_laay || '民事案件' }}
</span>
</div>
</div>
<div class="summary-middle">
<span class="summary-label">立案</span>
<span class="summary-value">{{ formatDate(item.d_larq) }}</span>
</div>
<div class="summary-bottom">
<span class="risk-tag" :class="statusClass(item.n_ajjzjd)">
{{ item.n_ajjzjd || '未知进展' }}
</span>
<span v-if="item.n_pj_victory" class="victory-tag">
胜诉估计{{ item.n_pj_victory }}
</span>
<span class="expand-indicator">
<span class="expand-text">
{{ isCaseExpanded(item.c_id || index) ? '收起详情' : '展开详情' }}
</span>
<img src="@/assets/images/report/zk.png" alt="展开" class="w-4 h-4"
:class="{ 'rotate-180': isCaseExpanded(item.c_id || index) }" />
</span>
</div>
</div>
<!-- 详情区域可展开/收起 -->
<div class="case-detail" :class="{
'detail-collapsed': !isCaseExpanded(item.c_id || index),
'detail-expanded': isCaseExpanded(item.c_id || index),
}">
<div class="case-body">
<div class="info-row">
<span class="info-label">立案时间</span>
<span class="info-value">{{ formatDate(item.d_larq) }}</span>
</div>
<div class="info-row">
<span class="info-label">结案时间</span>
<span class="info-value">{{ formatDate(item.d_jarq) }}</span>
</div>
<div class="info-row">
<span class="info-label">经办法院</span>
<span class="info-value">
{{ item.n_jbfy || '-' }}
</span>
</div>
<div class="info-row">
<span class="info-label">审理程序</span>
<span class="info-value">
{{ item.n_slcx || '-' }}
</span>
</div>
<div class="info-row">
<span class="info-label">结案案由</span>
<span class="info-value">
{{ item.n_jaay || '-' }}
</span>
</div>
<div class="info-row">
<span class="info-label">立案案由</span>
<span class="info-value">
{{ item.n_laay || '-' }}
</span>
</div>
<div class="info-row" v-if="item.c_gkws_pjjg">
<span class="info-label">判决结果</span>
<span class="info-value">
{{ item.c_gkws_pjjg }}
</span>
</div>
<div class="info-row" v-if="casePartiesText(item)">
<span class="info-label">当事人</span>
<span class="info-value">
{{ casePartiesText(item) }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else-if="hasAnyData" class="empty-tip">
暂未检索到民事案件记录可留意其他风险模块
</div>
<div v-else class="empty-tip">
暂无企业涉诉信息
</div>
</div>
</template>
<script setup>
import { computed, ref } from "vue";
const props = defineProps({
data: { type: Object, default: () => ({}) },
params: { type: Object, default: () => ({}) },
apiId: { type: String, default: "" },
index: { type: Number, default: 0 },
notifyRiskStatus: { type: Function, default: () => { } },
});
const entName = computed(() => {
return props.params?.ent_name || props.params?.entName || "";
});
// 提取 entout.data 结构
const entoutData = computed(() => {
const d = props.data || {};
// 优先使用 entout.data
if (d.entout && d.entout.data) return d.entout.data;
if (d.entout) return d.entout;
// 兼容 data.entout.data 结构
if (d.data && d.data.entout && d.data.entout.data) return d.data.entout.data;
return null;
});
const civil = computed(() => entoutData.value?.civil || {});
const civilCases = computed(() => civil.value.cases || []);
const civilCount = computed(() => civil.value.count || {});
const totalCivilCases = computed(() => civilCount.value.count_total ?? civilCases.value.length ?? 0);
const civilClosedCases = computed(() => civilCount.value.count_jie_total ?? 0);
const civilPendingCases = computed(() => civilCount.value.count_wei_total ?? 0);
const civilAreaStat = computed(() => civilCount.value.area_stat || "");
const civilAyStat = computed(() => civilCount.value.ay_stat || "");
const civilJafsStat = computed(() => civilCount.value.jafs_stat || "");
const hasCivilData = computed(() => totalCivilCases.value > 0);
const hasAnyData = computed(() => !!entoutData.value);
// 展开/收起案件详情,参考 FLXG7E8F 的交互
const expandedCases = ref({});
function toggleCaseExpand(key) {
const id = String(key);
expandedCases.value[id] = !expandedCases.value[id];
}
function isCaseExpanded(key) {
const id = String(key);
return !!expandedCases.value[id];
}
const moneySummary = computed(() => {
const total = civilCount.value.money_jie_total ?? null;
if (total == null) return "暂无金额统计";
if (typeof total === "number" && total === 0) return "金额较小或未公开";
return "已结案金额估计 " + formatMoney(total) + " 元";
});
function formatMoney(val) {
if (val == null || val === "") return "-";
const num = Number(val);
if (Number.isNaN(num)) return String(val);
if (num >= 1e8) {
return (num / 1e8).toFixed(2) + " 亿";
}
if (num >= 1e4) {
return (num / 1e4).toFixed(2) + " 万";
}
return num.toFixed(2);
}
function formatDate(str) {
if (!str) return "-";
// 支持 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss
if (str.length >= 10) {
return str.slice(0, 10);
}
return str;
}
function statusClass(status) {
if (!status) return "status-tag status-unknown";
if (String(status).includes("已结案")) return "status-tag status-closed";
if (String(status).includes("执行中") || String(status).includes("审理中")) {
return "status-tag status-processing";
}
return "status-tag status-unknown";
}
function casePartiesText(item) {
const list = item.c_dsrxx || [];
if (!Array.isArray(list) || list.length === 0) return "";
// 尝试优先提取与当前企业相关的角色
const name = entName.value;
const related = name
? list.filter((p) => typeof p.c_mc === "string" && p.c_mc.includes(name))
: [];
const targetList = related.length ? related : list;
const parts = targetList.map((p) => {
const n = p.c_mc || "";
const role = p.n_ssdw || "";
if (n && role) return `${n}${role}`;
return n || role || "";
}).filter(Boolean);
return parts.join("");
}
</script>
<style scoped>
.card {
padding: 1rem;
}
.header-box {
margin-bottom: 1rem;
}
.header-title {
font-size: 1.1rem;
font-weight: 600;
color: #333333;
}
.header-desc {
margin-top: 0.25rem;
font-size: 0.85rem;
color: #666666;
}
.header-ent {
margin-top: 0.25rem;
font-size: 0.85rem;
color: #333333;
}
.summary-section {
padding: 0.75rem 0;
border-top: 1px solid #f1f1f1;
border-bottom: 1px solid #f1f1f1;
margin-bottom: 1rem;
}
.summary-row {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
@media (min-width: 768px) {
.summary-row {
flex-direction: row;
}
}
.summary-card {
flex: 1;
padding: 0.75rem;
border-radius: 0.75rem;
}
.summary-risk {
background: rgba(235, 60, 60, 0.04);
border: 1px solid rgba(235, 60, 60, 0.3);
}
.summary-money {
background: rgba(214, 148, 62, 0.04);
border: 1px solid rgba(214, 148, 62, 0.3);
}
.summary-label {
font-size: 0.85rem;
color: #666666;
margin-bottom: 0.25rem;
}
.summary-value {
font-size: 1.4rem;
font-weight: 600;
color: #333333;
}
.summary-value.small {
font-size: 1rem;
}
.summary-sub {
margin-top: 0.25rem;
font-size: 0.75rem;
color: #999999;
}
.tag-row {
margin-top: 0.75rem;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.stat-tag {
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
border-radius: 999px;
background-color: #f5f5f5;
color: #666666;
}
.block {
margin-top: 1rem;
}
.block-title {
font-size: 0.95rem;
font-weight: 600;
color: #333333;
margin-bottom: 0.5rem;
}
.case-list {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.case-wrapper {
width: 100%;
}
.case-card {
border-radius: 0.75rem;
border: 1px solid #dddddd;
background-color: #ffffff;
overflow: hidden;
}
.case-summary {
padding: 0.75rem 0.75rem 0.5rem;
cursor: pointer;
position: relative;
}
.summary-top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.25rem;
}
.summary-title {
display: flex;
align-items: center;
gap: 0.5rem;
min-width: 0;
}
.case-no-text {
font-size: 0.9rem;
font-weight: 600;
color: #333333;
}
.case-type-tag {
padding: 0.1rem 0.4rem;
border-radius: 999px;
font-size: 0.75rem;
background-color: #f9ecec;
color: #eb3c3c;
}
.summary-middle {
font-size: 0.8rem;
padding-bottom: 0.25rem;
}
.summary-label {
color: #666666;
}
.summary-value {
color: #333333;
}
.summary-bottom {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
}
.risk-tag {
padding: 0.2rem 0.6rem;
border-radius: 999px;
font-size: 0.75rem;
font-weight: 500;
}
.status-closed {
background-color: rgba(31, 190, 93, 0.1);
color: #1fbe5d;
}
.status-processing {
background-color: rgba(235, 60, 60, 0.08);
color: #eb3c3c;
}
.status-unknown {
background-color: rgba(153, 153, 153, 0.1);
color: #666666;
}
.victory-tag {
font-size: 0.75rem;
color: #d6943e;
}
.expand-indicator {
display: flex;
align-items: center;
gap: 0.25rem;
font-size: 0.75rem;
color: #999999;
}
.expand-indicator img {
transition: transform 0.2s ease;
}
.expand-indicator img.rotate-180 {
transform: rotate(180deg);
}
.case-detail {
border-top: 1px dashed #eeeeee;
padding: 0 0.75rem 0.5rem;
max-height: 0;
opacity: 0;
overflow: hidden;
transition: max-height 0.25s ease, opacity 0.25s ease;
}
.case-detail.detail-expanded {
max-height: 500px;
opacity: 1;
}
.status-closed {
background-color: rgba(31, 190, 93, 0.1);
color: #1fbe5d;
}
.status-processing {
background-color: rgba(235, 60, 60, 0.08);
color: #eb3c3c;
}
.status-unknown {
background-color: rgba(153, 153, 153, 0.1);
color: #666666;
}
.case-body {
border-top: 1px dashed #e5e5e5;
padding-top: 0.5rem;
}
.info-row {
display: flex;
font-size: 0.8rem;
margin-bottom: 0.25rem;
}
.info-label {
width: 4.5rem;
color: #999999;
flex-shrink: 0;
}
.info-value {
color: #333333;
word-break: break-all;
}
.empty-tip {
margin-top: 0.75rem;
padding: 0.75rem;
text-align: center;
font-size: 0.85rem;
color: #999999;
background-color: #fafafa;
border-radius: 0.75rem;
}
</style>