|
|
|
@ -7,24 +7,419 @@ |
|
|
|
--> |
|
|
|
<template> |
|
|
|
<div class="service-applications-count"> |
|
|
|
<a-tabs v-model:activeKey="activeTab" type="card"> |
|
|
|
<div v-if="!loginInfo">加载中...</div> |
|
|
|
<div v-else-if="isAdmin" class="admin-excel-view"> |
|
|
|
<!-- 查询页面:只在没有显示结果时显示 --> |
|
|
|
<div v-if="!showResultView"> |
|
|
|
<a-card title="机构数据查询" class="admin-excel-card"> |
|
|
|
<div class="excel-description"> |
|
|
|
<p>作为协议,您可以查看机构级别的统计数据,数据以Excel表格样式展示。</p> |
|
|
|
<p>请选择需要查看的季度和年度,然后点击查询按钮。</p> |
|
|
|
</div> |
|
|
|
|
|
|
|
<a-form :model="queryForm" layout="horizontal" class="query-form"> |
|
|
|
<a-form-item label="季度" :label-col="{ span: 4 }" :wrapper-col="{ span: 8 }"> |
|
|
|
<a-select v-model:value="queryForm.quarter" placeholder="请选择季度" style="width: 200px"> |
|
|
|
<a-select-option :value="1">第一季度</a-select-option> |
|
|
|
<a-select-option :value="2">第二季度</a-select-option> |
|
|
|
<a-select-option :value="3">第三季度</a-select-option> |
|
|
|
<a-select-option :value="4">第四季度</a-select-option> |
|
|
|
</a-select> |
|
|
|
</a-form-item> |
|
|
|
|
|
|
|
<a-form-item label="年度" :label-col="{ span: 4 }" :wrapper-col="{ span: 8 }"> |
|
|
|
<a-select v-model:value="queryForm.year" placeholder="请选择年度" style="width: 200px"> |
|
|
|
<a-select-option :value="2026">2026年</a-select-option> |
|
|
|
<a-select-option :value="2027">2027年</a-select-option> |
|
|
|
<a-select-option :value="2028">2028年</a-select-option> |
|
|
|
<a-select-option :value="2029">2029年</a-select-option> |
|
|
|
<a-select-option :value="2030">2030年</a-select-option> |
|
|
|
</a-select> |
|
|
|
</a-form-item> |
|
|
|
|
|
|
|
<!--<a-form-item label="机构名称" :label-col="{ span: 4 }" :wrapper-col="{ span: 8 }"> |
|
|
|
<a-input v-model:value="queryForm.firmName" placeholder="请输入机构名称(可选)" style="width: 300px" /> |
|
|
|
</a-form-item>--> |
|
|
|
|
|
|
|
<a-form-item :wrapper-col="{ span: 8, offset: 4 }"> |
|
|
|
<a-button type="primary" @click="handleQuery" :loading="queryLoading" style="margin-right: 8px;"> |
|
|
|
<SearchOutlined /> |
|
|
|
查询数据 |
|
|
|
</a-button> |
|
|
|
<a-button @click="handleReset" style="margin-right: 8px;"> |
|
|
|
<ReloadOutlined /> |
|
|
|
重置 |
|
|
|
</a-button> |
|
|
|
<!--<a-button type="primary" @click="handleExport" :loading="exportLoading"> |
|
|
|
<ExportOutlined /> |
|
|
|
导出Excel |
|
|
|
</a-button>--> |
|
|
|
</a-form-item> |
|
|
|
</a-form> |
|
|
|
|
|
|
|
<!-- 空状态 --> |
|
|
|
<div v-if="hasQueried && !showResultView" class="empty-state"> |
|
|
|
<a-empty description="暂无数据" /> |
|
|
|
</div> |
|
|
|
</a-card> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 详情页面:查询成功后完全替换查询页面 --> |
|
|
|
<div v-else class="result-view"> |
|
|
|
<FirmStatisticsDetail |
|
|
|
:query-params="queryForm" |
|
|
|
:table-data="tableData" |
|
|
|
@back="handleBackToQuery" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<a-tabs v-else v-model:activeKey="activeTab" type="card"> |
|
|
|
<!-- 季度统计 --> |
|
|
|
<a-tab-pane key="quarter" tab="季度统计"> |
|
|
|
<QuarterStatistics /> |
|
|
|
<QuarterStatistics :is-admin="isAdmin" /> |
|
|
|
</a-tab-pane> |
|
|
|
</a-tabs> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script setup> |
|
|
|
import { ref } from 'vue'; |
|
|
|
import { ref, onMounted, reactive } from 'vue'; |
|
|
|
import { ExportOutlined, SearchOutlined, ReloadOutlined, ArrowLeftOutlined } from '@ant-design/icons-vue'; |
|
|
|
import { message } from 'ant-design-vue'; |
|
|
|
import QuarterStatistics from '/@/components/system/service-count/quarter-statistics.vue'; |
|
|
|
import FirmStatisticsDetail from '/@/components/system/service-count/firm-statistics-detail.vue'; |
|
|
|
import { loginApi } from '/@/api/system/login-api'; |
|
|
|
import { serviceApplicationsApi } from '/@/api/business/service-applications/service-applications-api'; |
|
|
|
|
|
|
|
const activeTab = ref('quarter'); |
|
|
|
const loginInfo = ref(null); |
|
|
|
const isAdmin = ref(false); |
|
|
|
const queryLoading = ref(false); |
|
|
|
const exportLoading = ref(false); |
|
|
|
const hasQueried = ref(false); |
|
|
|
const queryForm = reactive({ |
|
|
|
quarter: null, |
|
|
|
year: new Date().getFullYear(), |
|
|
|
//firmName: '' |
|
|
|
}); |
|
|
|
const tableData = ref([]); |
|
|
|
const summaryData = ref(null); |
|
|
|
const showResultView = ref(false); |
|
|
|
|
|
|
|
// 获取登录信息 |
|
|
|
async function getLoginInfo() { |
|
|
|
try { |
|
|
|
console.log('开始获取登录信息...'); |
|
|
|
const res = await loginApi.getLoginInfo(); |
|
|
|
console.log('登录接口返回:', res); |
|
|
|
loginInfo.value = res.data; |
|
|
|
console.log('登录信息:', res.data); |
|
|
|
|
|
|
|
// 判断是否为admin用户 |
|
|
|
const loginNameCheck = res.data?.loginName === 'admin'; |
|
|
|
const userTypeCheck = res.data?.userType === 1; |
|
|
|
isAdmin.value = loginNameCheck || userTypeCheck; |
|
|
|
|
|
|
|
console.log('管理员状态判断:'); |
|
|
|
console.log('- loginName:', res.data?.loginName); |
|
|
|
console.log('- loginName === "admin":', loginNameCheck); |
|
|
|
console.log('- userType:', res.data?.userType); |
|
|
|
console.log('- userType === 1:', userTypeCheck); |
|
|
|
console.log('- 最终isAdmin:', isAdmin.value); |
|
|
|
|
|
|
|
} catch (error) { |
|
|
|
console.error('获取登录信息失败:', error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 立即执行获取登录信息 |
|
|
|
getLoginInfo(); |
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
// 组件挂载时的逻辑已经在上面执行 |
|
|
|
}); |
|
|
|
|
|
|
|
// 查询数据 |
|
|
|
async function handleQuery() { |
|
|
|
//if (!queryForm.quarter) { |
|
|
|
// message.warning('请选择季度'); |
|
|
|
// return; |
|
|
|
//} |
|
|
|
|
|
|
|
if (!queryForm.year) { |
|
|
|
message.warning('请选择年度'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
queryLoading.value = true; |
|
|
|
try { |
|
|
|
console.log('开始查询机构数据...'); |
|
|
|
const queryParams = { |
|
|
|
quarter: queryForm.quarter, |
|
|
|
year: queryForm.year, |
|
|
|
firmName: queryForm.firmName, |
|
|
|
// 管理员接口默认分页参数 |
|
|
|
pageNum: 1, |
|
|
|
pageSize: 500 |
|
|
|
}; |
|
|
|
|
|
|
|
console.log('查询参数:', queryParams); |
|
|
|
|
|
|
|
const res = await serviceApplicationsApi.statisticsDepartment(queryParams); |
|
|
|
console.log('机构数据查询结果:', res); |
|
|
|
|
|
|
|
// 正确处理分页返回的数据结构 |
|
|
|
if (res.data && res.data.list && Array.isArray(res.data.list)) { |
|
|
|
const dataList = res.data.list; |
|
|
|
|
|
|
|
if (dataList.length > 0) { |
|
|
|
tableData.value = dataList.map(item => ({ |
|
|
|
...item, |
|
|
|
// 根据实际返回字段映射到表格显示字段 |
|
|
|
firmName: item.firmName || '-', |
|
|
|
lawyerCount: item.lawyerCount || 0, |
|
|
|
applicationCount: item.applicationCount || 0, |
|
|
|
approvedCount: item.approvedCount || 0, |
|
|
|
rejectedCount: item.rejectedCount || 0, |
|
|
|
approvalRate: item.approvalRate ? `${(item.approvalRate * 100).toFixed(2)}%` : '0%', |
|
|
|
statisticTime: item.statisticTime || '-', |
|
|
|
// 新增的服务时长和成本字段 |
|
|
|
quarterlyServiceDuration: item.quarterlyServiceDuration || 0, |
|
|
|
quarterlyServiceCost: item.quarterlyServiceCost || 0, |
|
|
|
annualServiceDuration: item.annualServiceDuration || 0, |
|
|
|
annualServiceCost: item.annualServiceCost || 0 |
|
|
|
})); |
|
|
|
|
|
|
|
// 显示结果页面 |
|
|
|
showResultView.value = true; |
|
|
|
hasQueried.value = true; |
|
|
|
message.success(`查询成功,共 ${res.data.total} 条数据`); |
|
|
|
} else { |
|
|
|
tableData.value = []; |
|
|
|
summaryData.value = null; |
|
|
|
showResultView.value = false; |
|
|
|
message.warning('暂无数据'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
tableData.value = []; |
|
|
|
summaryData.value = null; |
|
|
|
message.warning('暂无数据'); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('查询机构数据失败:', error); |
|
|
|
message.error('查询失败'); |
|
|
|
tableData.value = []; |
|
|
|
summaryData.value = null; |
|
|
|
} finally { |
|
|
|
queryLoading.value = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 重置查询条件 |
|
|
|
function handleReset() { |
|
|
|
queryForm.quarter = null; |
|
|
|
queryForm.year = new Date().getFullYear(); |
|
|
|
queryForm.firmName = ''; |
|
|
|
tableData.value = []; |
|
|
|
summaryData.value = null; |
|
|
|
hasQueried.value = false; |
|
|
|
} |
|
|
|
|
|
|
|
// 导出Excel |
|
|
|
async function handleExport() { |
|
|
|
if (tableData.value.length === 0) { |
|
|
|
message.warning('请先查询数据'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
exportLoading.value = true; |
|
|
|
try { |
|
|
|
console.log('开始导出机构数据...'); |
|
|
|
const exportParams = { |
|
|
|
quarter: queryForm.quarter, |
|
|
|
year: queryForm.year, |
|
|
|
firmName: queryForm.firmName |
|
|
|
}; |
|
|
|
|
|
|
|
await serviceApplicationsApi.exportFirm(exportParams); |
|
|
|
message.success('导出成功'); |
|
|
|
console.log('机构数据导出成功'); |
|
|
|
} catch (error) { |
|
|
|
message.error('导出失败'); |
|
|
|
console.error('机构数据导出失败:', error); |
|
|
|
} finally { |
|
|
|
exportLoading.value = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 计算汇总数据 |
|
|
|
function calculateSummary() { |
|
|
|
if (tableData.value.length === 0) { |
|
|
|
summaryData.value = null; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const summary = { |
|
|
|
totalLawyerCount: 0, |
|
|
|
totalApplicationCount: 0, |
|
|
|
totalApprovedCount: 0, |
|
|
|
totalRejectedCount: 0 |
|
|
|
}; |
|
|
|
|
|
|
|
tableData.value.forEach(item => { |
|
|
|
summary.totalLawyerCount += item.lawyerCount || 0; |
|
|
|
summary.totalApplicationCount += item.applicationCount || 0; |
|
|
|
summary.totalApprovedCount += item.approvedCount || 0; |
|
|
|
summary.totalRejectedCount += item.rejectedCount || 0; |
|
|
|
}); |
|
|
|
|
|
|
|
// 计算通过率 |
|
|
|
if (summary.totalApplicationCount > 0) { |
|
|
|
summary.totalApprovalRate = `${((summary.totalApprovedCount / summary.totalApplicationCount) * 100).toFixed(2)}%`; |
|
|
|
} else { |
|
|
|
summary.totalApprovalRate = '0%'; |
|
|
|
} |
|
|
|
|
|
|
|
summaryData.value = summary; |
|
|
|
} |
|
|
|
|
|
|
|
// 返回查询页面 |
|
|
|
function handleBackToQuery() { |
|
|
|
showResultView.value = false; |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped> |
|
|
|
.service-applications-count { |
|
|
|
padding: 16px; |
|
|
|
background: #fff; |
|
|
|
min-height: 600px; |
|
|
|
} |
|
|
|
|
|
|
|
.admin-excel-view { |
|
|
|
max-width: 1200px; |
|
|
|
margin: 0 auto; |
|
|
|
} |
|
|
|
|
|
|
|
.admin-excel-card { |
|
|
|
border-radius: 8px; |
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
|
|
|
} |
|
|
|
|
|
|
|
.excel-description { |
|
|
|
background: #f0f7ff; |
|
|
|
border: 1px solid #b3d8ff; |
|
|
|
border-radius: 4px; |
|
|
|
padding: 16px; |
|
|
|
margin-bottom: 24px; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-description p { |
|
|
|
margin: 0; |
|
|
|
line-height: 1.6; |
|
|
|
color: #333; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-description p:first-child { |
|
|
|
margin-bottom: 8px; |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
|
|
|
|
.query-form { |
|
|
|
margin-bottom: 24px; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-table-container { |
|
|
|
border: 2px solid #d9d9d9; |
|
|
|
border-radius: 4px; |
|
|
|
overflow: hidden; |
|
|
|
margin-top: 24px; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-table-header { |
|
|
|
background: #f5f5f5; |
|
|
|
padding: 16px; |
|
|
|
border-bottom: 1px solid #d9d9d9; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-table-title { |
|
|
|
font-size: 18px; |
|
|
|
font-weight: 600; |
|
|
|
color: #333; |
|
|
|
margin-bottom: 4px; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-table-subtitle { |
|
|
|
font-size: 14px; |
|
|
|
color: #666; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-table { |
|
|
|
width: 100%; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-row { |
|
|
|
display: flex; |
|
|
|
border-bottom: 1px solid #d9d9d9; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-row:last-child { |
|
|
|
border-bottom: none; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-header { |
|
|
|
background: #e6f7ff; |
|
|
|
font-weight: 600; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-summary { |
|
|
|
background: #f0f0f0; |
|
|
|
font-weight: 600; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-cell { |
|
|
|
padding: 8px 12px; |
|
|
|
border-right: 1px solid #d9d9d9; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
min-height: 40px; |
|
|
|
box-sizing: border-box; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-cell:last-child { |
|
|
|
border-right: none; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-header .excel-cell { |
|
|
|
background: #1890ff; |
|
|
|
color: white; |
|
|
|
border-right: 1px solid #40a9ff; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-data .excel-cell { |
|
|
|
background: white; |
|
|
|
color: #333; |
|
|
|
} |
|
|
|
|
|
|
|
.excel-summary .excel-cell { |
|
|
|
background: #fafafa; |
|
|
|
color: #333; |
|
|
|
} |
|
|
|
|
|
|
|
.empty-state { |
|
|
|
padding: 60px 0; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
:deep(.ant-form-item-label) { |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
|
|
|
|
:deep(.ant-card-head-title) { |
|
|
|
font-size: 18px; |
|
|
|
font-weight: 600; |
|
|
|
color: #1890ff; |
|
|
|
} |
|
|
|
</style> |