This commit is contained in:
Mrx
2026-05-13 11:01:42 +08:00
parent 5c4921b34e
commit 53284b6979
41 changed files with 10043 additions and 823 deletions

542
src/ui/CQYGL66SL.vue Normal file
View File

@@ -0,0 +1,542 @@
<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>