2025-06-02 21:36:36 +08:00

801 lines
22 KiB
Vue

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { getPageList, getBaseUrl } from '../services/api';
import QRCodeDisplay from '../components/QRCodeDisplay.vue';
import TheNavbar from '../components/TheNavbar.vue';
import SearchBar from '../components/SearchBar.vue';
interface PageItem {
id: number;
formatId: string;
title: string;
content: string;
pageType: string;
pageUrl: string;
createTime: string;
updateTime: string;
status: number;
sortOrder: number;
viewCount: number;
author?: string;
keywords?: string;
description?: string;
attachmentUrl?: string;
}
// 移除默认数据,只使用后端提供的真实数据
const lawList = ref<PageItem[]>([]);
const caseList = ref<PageItem[]>([]);
const formList = ref<PageItem[]>([]);
const loading = ref({
law: true,
case: true,
form: true
});
// 根据不同类型构建不同的URL
const buildQRCodeUrl = (id: string, type: string): string => {
const baseUrl = getBaseUrl();
let path = '';
if (type === 'law') {
path = `/show.html?Id=${id}`;
} else if (type === 'case') {
path = `/showcase.html?Id=${id}`;
} else if (type === 'form') {
path = `/table.html?Id=${id}`;
} else {
path = `/show.html?Id=${id}`;
}
return `${baseUrl}${path}`;
};
// 预设的二维码链接
const qrCodeLinks = {
law: [
{ id: '000001', title: '法律规定1', url: buildQRCodeUrl('000001', 'law') },
{ id: '000002', title: '法律规定2', url: buildQRCodeUrl('000002', 'law') },
{ id: '000003', title: '法律规定3', url: buildQRCodeUrl('000003', 'law') },
],
case: [
{ id: '000001', title: '典型案例1', url: buildQRCodeUrl('000001', 'case') },
{ id: '000002', title: '典型案例2', url: buildQRCodeUrl('000002', 'case') },
{ id: '000003', title: '典型案例3', url: buildQRCodeUrl('000003', 'case') },
],
form: [
{ id: '000001', title: '表单下载1', url: buildQRCodeUrl('000001', 'form') },
{ id: '000002', title: '表单下载2', url: buildQRCodeUrl('000002', 'form') },
{ id: '000003', title: '表单下载3', url: buildQRCodeUrl('000003', 'form') },
]
};
// 格式化日期,处理无效日期情况
const formatDate = (dateStr: string | null | undefined): string => {
if (!dateStr) return '--/--';
try {
const date = new Date(dateStr);
// 检查日期是否有效
if (isNaN(date.getTime())) {
return '--/--';
}
return `${date.getMonth() + 1}/${date.getDate()}`;
} catch (e) {
console.error('日期格式化错误:', e);
return '--/--';
}
};
onMounted(async () => {
// 获取法律规定列表
try {
console.log("开始请求法律规定列表...");
const result = await getPageList('law', 1, 6);
console.log("法律规定列表请求结果:", result);
// 详细检查返回数据
if (!result) {
console.error("法律规定请求结果为空");
return;
}
console.log("法律规定返回数据类型:", typeof result);
console.log("法律规定返回数据结构:", Object.keys(result));
if (result && result.code === 200) {
if (Array.isArray(result.rows) && result.rows.length > 0) {
lawList.value = result.rows;
console.log("成功获取法律规定数据:", lawList.value);
} else {
console.warn("法律规定数据为空或格式不正确:", result);
console.warn("rows是否为数组:", Array.isArray(result.rows));
console.warn("rows长度:", result.rows ? result.rows.length : 0);
// 尝试从其他字段获取数据
if (result.data && Array.isArray(result.data)) {
lawList.value = result.data;
console.log("从data字段获取法律规定数据:", lawList.value);
} else if (result.list && Array.isArray(result.list)) {
lawList.value = result.list;
console.log("从list字段获取法律规定数据:", lawList.value);
} else if (Array.isArray(result)) {
lawList.value = result;
console.log("直接使用结果数组作为法律规定数据:", lawList.value);
}
}
} else {
console.error("请求法律规定列表失败:", result?.msg || "未知错误");
}
} catch (error) {
console.error('获取法律规定列表失败:', error);
} finally {
loading.value.law = false;
}
// 获取典型案例列表
try {
console.log("开始请求典型案例列表...");
const result = await getPageList('case', 1, 6);
console.log("典型案例列表请求结果:", result);
// 详细检查返回数据
if (!result) {
console.error("典型案例请求结果为空");
return;
}
console.log("典型案例返回数据类型:", typeof result);
console.log("典型案例返回数据结构:", Object.keys(result));
if (result && result.code === 200) {
if (Array.isArray(result.rows) && result.rows.length > 0) {
caseList.value = result.rows;
console.log("成功获取典型案例数据:", caseList.value);
} else {
console.warn("典型案例数据为空或格式不正确:", result);
console.warn("rows是否为数组:", Array.isArray(result.rows));
console.warn("rows长度:", result.rows ? result.rows.length : 0);
// 尝试从其他字段获取数据
if (result.data && Array.isArray(result.data)) {
caseList.value = result.data;
console.log("从data字段获取典型案例数据:", caseList.value);
} else if (result.list && Array.isArray(result.list)) {
caseList.value = result.list;
console.log("从list字段获取典型案例数据:", caseList.value);
} else if (Array.isArray(result)) {
caseList.value = result;
console.log("直接使用结果数组作为典型案例数据:", caseList.value);
}
}
} else {
console.error("请求典型案例列表失败:", result?.msg || "未知错误");
}
} catch (error) {
console.error('获取典型案例列表失败:', error);
} finally {
loading.value.case = false;
}
// 获取表单下载列表
try {
console.log("开始请求表单下载列表...");
const result = await getPageList('form', 1, 6);
console.log("表单下载列表请求结果:", result);
// 详细检查返回数据
if (!result) {
console.error("表单下载请求结果为空");
return;
}
console.log("表单下载返回数据类型:", typeof result);
console.log("表单下载返回数据结构:", Object.keys(result));
if (result && result.code === 200) {
if (Array.isArray(result.rows) && result.rows.length > 0) {
formList.value = result.rows;
console.log("成功获取表单下载数据:", formList.value);
} else {
console.warn("表单下载数据为空或格式不正确:", result);
console.warn("rows是否为数组:", Array.isArray(result.rows));
console.warn("rows长度:", result.rows ? result.rows.length : 0);
// 尝试从其他字段获取数据
if (result.data && Array.isArray(result.data)) {
formList.value = result.data;
console.log("从data字段获取表单下载数据:", formList.value);
} else if (result.list && Array.isArray(result.list)) {
formList.value = result.list;
console.log("从list字段获取表单下载数据:", formList.value);
} else if (Array.isArray(result)) {
formList.value = result;
console.log("直接使用结果数组作为表单下载数据:", formList.value);
}
}
} else {
console.error("请求表单下载列表失败:", result?.msg || "未知错误");
}
} catch (error) {
console.error('获取表单下载列表失败:', error);
} finally {
loading.value.form = false;
}
// 更新二维码链接,使用实际数据
try {
if (lawList.value.length > 0) {
qrCodeLinks.law = lawList.value.slice(0, 3).map(item => ({
id: item.formatId,
title: item.title,
url: buildQRCodeUrl(item.formatId, 'law')
}));
}
if (caseList.value.length > 0) {
qrCodeLinks.case = caseList.value.slice(0, 3).map(item => ({
id: item.formatId,
title: item.title,
url: buildQRCodeUrl(item.formatId, 'case')
}));
}
if (formList.value.length > 0) {
qrCodeLinks.form = formList.value.slice(0, 3).map(item => ({
id: item.formatId,
title: item.title,
url: buildQRCodeUrl(item.formatId, 'form')
}));
}
console.log("二维码链接已更新:", qrCodeLinks);
} catch (error) {
console.error('更新二维码链接失败:', error);
}
});
</script>
<template>
<div class="home">
<TheNavbar />
<header class="header">
<div class="container">
<h1>淮安市司法局百问百答</h1>
<p class="subtitle">法律法规典型案例表单下载</p>
</div>
</header>
<div class="container main-container">
<!-- 主要内容区域 -->
<div class="content-row">
<!-- 法律规定区块 -->
<div class="content-card">
<div class="card-header">
<h2><i class="card-icon law-icon"></i>法律规定</h2>
<router-link to="/hasfjlaw" class="view-more">查看更多</router-link>
</div>
<div v-if="loading.law" class="loading">
<div class="spinner"></div>
<span>加载中...</span>
</div>
<div v-else-if="lawList.length === 0" class="empty">暂无法律规定</div>
<ul v-else class="content-list">
<li v-for="item in lawList.slice(0, 6)" :key="item.formatId">
<router-link :to="`/show.html?Id=${item.formatId}`" class="list-item-link">
<span class="item-dot"></span>
{{ item.title }}
</router-link>
<span class="date">{{ formatDate(item.createTime) }}</span>
</li>
</ul>
</div>
<!-- 典型案例区块 -->
<div class="content-card">
<div class="card-header">
<h2><i class="card-icon case-icon"></i>典型案例</h2>
<router-link to="/hasfjcase" class="view-more">查看更多</router-link>
</div>
<div v-if="loading.case" class="loading">
<div class="spinner"></div>
<span>加载中...</span>
</div>
<div v-else-if="caseList.length === 0" class="empty">暂无典型案例</div>
<ul v-else class="content-list">
<li v-for="item in caseList.slice(0, 6)" :key="item.formatId">
<router-link :to="`/showcase.html?Id=${item.formatId}`" class="list-item-link">
<span class="item-dot"></span>
{{ item.title }}
</router-link>
<span class="date">{{ formatDate(item.createTime) }}</span>
</li>
</ul>
</div>
<!-- 表单下载区块 -->
<div class="content-card">
<div class="card-header">
<h2><i class="card-icon form-icon"></i>表单下载</h2>
<router-link to="/hasfjform" class="view-more">查看更多</router-link>
</div>
<div v-if="loading.form" class="loading">
<div class="spinner"></div>
<span>加载中...</span>
</div>
<div v-else-if="formList.length === 0" class="empty">暂无表单</div>
<ul v-else class="content-list">
<li v-for="item in formList.slice(0, 6)" :key="item.formatId">
<router-link :to="`/table.html?Id=${item.formatId}`" class="list-item-link">
<span class="item-dot"></span>
{{ item.title }}
</router-link>
<span class="date">{{ formatDate(item.createTime) }}</span>
</li>
</ul>
</div>
</div>
<!-- 二维码区域 -->
<div class="qrcode-section">
<div class="section-header">
<h2><i class="section-icon qrcode-icon"></i>二维码入口</h2>
<router-link to="/qrcodes" class="view-more">查看更多</router-link>
</div>
<div class="qrcode-list">
<!-- 法律规定二维码 -->
<div class="qrcode-group">
<h3>法律规定</h3>
<div class="qrcode-container">
<QRCodeDisplay
v-for="item in qrCodeLinks.law"
:key="item.id"
:url="item.url"
:title="item.title"
:id="item.id"
/>
</div>
</div>
<!-- 典型案例二维码 -->
<div class="qrcode-group">
<h3>典型案例</h3>
<div class="qrcode-container">
<QRCodeDisplay
v-for="item in qrCodeLinks.case"
:key="item.id"
:url="item.url"
:title="item.title"
:id="item.id"
/>
</div>
</div>
<!-- 表单下载二维码 -->
<div class="qrcode-group">
<h3>表单下载</h3>
<div class="qrcode-container">
<QRCodeDisplay
v-for="item in qrCodeLinks.form"
:key="item.id"
:url="item.url"
:title="item.title"
:id="item.id"
/>
</div>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<p>© 2025 博越科技. 版权所有.</p>
</div>
</footer>
</div>
</template>
<style scoped>
.home {
min-height: 100vh;
display: flex;
flex-direction: column;
width: 100%;
}
html, body {
overflow-y: auto !important;
height: auto !important;
position: static !important;
}
.header {
background-color: var(--color-primary);
color: white;
padding: 3rem 0;
text-align: center;
margin-bottom: 0;
position: relative;
overflow: hidden;
background-image: linear-gradient(135deg, #0072ff 0%, #00c6ff 100%);
width: 100%;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiPjxkZWZzPjxwYXR0ZXJuIGlkPSJwYXR0ZXJuIiB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiIHBhdHRlcm5UcmFuc2Zvcm09InJvdGF0ZSg0NSkiPjxyZWN0IGlkPSJwYXR0ZXJuLWJhY2tncm91bmQiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InRyYW5zcGFyZW50Ij48L3JlY3Q+PHBhdGggZD0iTSAwIDAgTCAxMCAwIiBzdHJva2U9IiNmZmZmZmYxMCIgc3Ryb2tlLXdpZHRoPSIxIj48L3BhdGg+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI3BhdHRlcm4pIj48L3JlY3Q+PC9zdmc+');
opacity: 0.4;
z-index: 1;
}
.header .container {
position: relative;
z-index: 2;
max-width: 1200px;
padding: 0 2rem;
margin: 0 auto;
}
.header h1 {
font-size: 2.6rem;
margin-bottom: 1rem;
font-weight: 700;
letter-spacing: 1px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.subtitle {
font-size: 1.5rem;
opacity: 0.9;
max-width: 700px;
margin: 0 auto;
line-height: 1.4;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
.main-container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem 1rem;
width: 100%;
flex: 1;
display: flex;
flex-direction: column;
gap: 2rem;
}
.content-row {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
justify-content: space-between;
width: 100%;
}
.content-card {
flex: 1;
min-width: 300px;
background-color: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
padding: 1.5rem;
display: flex;
flex-direction: column;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 2px solid #f0f0f0;
position: relative;
z-index: 1;
}
.card-header h2 {
font-size: 1.5rem;
color: var(--color-text);
font-weight: 600;
display: flex;
align-items: center;
margin: 0;
}
.card-icon {
display: inline-block;
width: 24px;
height: 24px;
margin-right: 10px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.law-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%230072ff' viewBox='0 0 16 16'%3E%3Cpath d='M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0zM4.5 7.5a.5.5 0 0 1 0 1H3.5a.5.5 0 0 1 0-1h1zm2 0a.5.5 0 0 1 0 1h-1a.5.5 0 0 1 0-1h1zm1 0a.5.5 0 0 1 0 1V8h1v.5a.5.5 0 0 1 0 1V8h1v.5a.5.5 0 1 1 0 1V8a.5.5 0 0 1-.5-.5H9v.5a.5.5 0 0 1-1 0V8h-1v.5zM8 9a.5.5 0 0 1 0 1H4.5a.5.5 0 0 1 0-1zm2.5 0a.5.5 0 0 1 0 1h-1a.5.5 0 0 1 0-1z'/%3E%3C/svg%3E");
}
.case-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%230072ff' viewBox='0 0 16 16'%3E%3Cpath d='M5.5 2A3.5 3.5 0 0 0 2 5.5v5A3.5 3.5 0 0 0 5.5 14h5a3.5 3.5 0 0 0 3.5-3.5V8a.5.5 0 0 1 1 0v2.5a4.5 4.5 0 0 1-4.5 4.5h-5A4.5 4.5 0 0 1 1 10.5v-5A4.5 4.5 0 0 1 5.5 1H8a.5.5 0 0 1 0 1z'/%3E%3Cpath d='M16 3a3 3 0 1 1-6 0 3 3 0 0 1 6 0'/%3E%3C/svg%3E");
}
.form-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%230072ff' viewBox='0 0 16 16'%3E%3Cpath d='M13 0H6a2 2 0 0 0-2 2 2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2 2 2 0 0 0 2-2V2a2 2 0 0 0-2-2m0 13V4a2 2 0 0 0-2-2H5a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1M3 4a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1z'/%3E%3C/svg%3E");
}
.section-icon, .qrcode-icon {
display: inline-block;
width: 24px;
height: 24px;
margin-right: 10px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.qrcode-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%230072ff' viewBox='0 0 16 16'%3E%3Cpath d='M2 2h2v2H2V2Z'/%3E%3Cpath d='M6 0v6H0V0h6ZM5 1H1v4h4V1ZM4 12H2v2h2v-2Z'/%3E%3Cpath d='M6 10v6H0v-6h6Zm-5 1v4h4v-4H1Zm11-9h2v2h-2V2Z'/%3E%3Cpath d='M10 0v6h6V0h-6Zm5 1v4h-4V1h4ZM8 1V0h1v2H8v2H7V1h1Zm0 5V4h1v2H8ZM6 8V7h1V6h1v2h1V7h5v1h-4v1H7V8H6Zm0 0v1H2V8H1v1H0V7h3v1h3Zm10 1h-1V7h1v2Zm-1 0h-1v2h2v-1h-1V9Zm-4 0h2v1h-1v1h-1V9Zm2 3v-1h-1v1h-1v1H9v1h3v-2h1Zm0 0h3v1h-2v1h-1v-2Zm-4-1v1h1v-2H7v1h2Z'/%3E%3Cpath d='M7 12h1v3h4v1H7v-4Zm9 2v2h-3v-1h2v-1h1Z'/%3E%3C/svg%3E");
}
.view-more {
color: var(--color-primary);
text-decoration: none;
font-size: 0.9rem;
display: flex;
align-items: center;
transition: transform 0.3s;
white-space: nowrap;
}
.view-more::after {
content: '→';
margin-left: 5px;
display: inline-block;
}
.view-more:hover {
transform: translateX(5px);
}
.loading, .empty {
text-align: center;
padding: 2rem;
color: var(--color-text-light);
font-size: 1rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
}
.spinner {
width: 30px;
height: 30px;
border: 3px solid rgba(0, 123, 255, 0.1);
border-radius: 50%;
border-top-color: var(--color-primary);
animation: spin 1s ease-in-out infinite;
margin-bottom: 1rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.content-list {
list-style: none;
padding: 0;
margin: 0;
flex: 1;
display: flex;
flex-direction: column;
}
.content-list li {
padding: 0.7rem 0;
border-bottom: 1px dashed #eee;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.3s;
}
.content-list li:hover {
background-color: rgba(0, 123, 255, 0.05);
padding-left: 10px;
padding-right: 10px;
}
.content-list li:last-child {
border-bottom: none;
}
.list-item-link {
color: var(--color-text);
text-decoration: none;
transition: all 0.3s;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
position: relative;
padding-left: 15px;
font-size: 1rem;
display: block;
}
.item-dot {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--color-primary);
display: block;
}
.list-item-link:hover {
color: var(--color-primary);
transform: translateX(5px);
}
.date {
color: var(--color-text-light);
font-size: 0.85rem;
margin-left: 1rem;
white-space: nowrap;
}
.qrcode-section {
margin: 0;
background-color: white;
border-radius: 12px;
padding: 2rem;
width: 100%;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.8rem;
padding-bottom: 1rem;
border-bottom: 2px solid #f0f0f0;
}
.section-header h2 {
font-size: 1.8rem;
font-weight: 600;
display: flex;
align-items: center;
margin: 0;
}
.qrcode-list {
display: flex;
flex-wrap: wrap;
gap: 2rem;
}
.qrcode-group {
flex: 1;
min-width: 300px;
}
.qrcode-group h3 {
margin-bottom: 1.5rem;
color: var(--color-text);
font-size: 1.4rem;
position: relative;
padding-left: 18px;
}
.qrcode-group h3::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6px;
height: 20px;
background-color: var(--color-primary);
border-radius: 3px;
}
.qrcode-container {
display: flex;
flex-wrap: wrap;
gap: 2rem;
justify-content: flex-start;
}
.footer {
margin-top: auto;
background-color: #2c3e50;
padding: 2rem 0;
text-align: center;
color: rgba(255, 255, 255, 0.8);
width: 100%;
}
.footer p {
margin: 0;
font-size: 1.1rem;
}
/* 移动端首页搜索框 */
.mobile-home-search {
display: none !important;
}
/* 响应式布局 */
@media (max-width: 992px) {
.content-row {
flex-direction: column;
}
.content-card {
width: 100%;
}
.qrcode-group {
width: 100%;
margin-bottom: 2rem;
}
}
@media (max-width: 768px) {
.header {
padding: 2rem 0;
}
.header h1 {
font-size: 2rem;
}
.subtitle {
font-size: 1.2rem;
}
.content-card {
padding: 1rem;
}
.qrcode-section {
padding: 1.5rem;
}
}
@media (max-width: 576px) {
.header h1 {
font-size: 1.6rem;
}
.subtitle {
font-size: 1rem;
}
.card-header h2,
.section-header h2 {
font-size: 1.3rem;
}
.qrcode-group h3 {
font-size: 1.2rem;
}
}
</style>