2025-05-22 12:33:26 +00:00
|
|
|
|
<template>
|
|
|
|
|
<div class="page-container">
|
2025-05-30 07:33:35 +00:00
|
|
|
|
<div class="sec-filings-container">
|
2025-05-22 12:33:26 +00:00
|
|
|
|
<!-- 标题 -->
|
2025-05-30 07:33:35 +00:00
|
|
|
|
<div class="page-title">SEC Filings</div>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
<!-- 筛选器 -->
|
|
|
|
|
<div class="filters">
|
|
|
|
|
<div class="filter-group">
|
|
|
|
|
<label class="filter-label">Filing year</label>
|
|
|
|
|
<n-select
|
|
|
|
|
v-model:value="state.selectedYear"
|
|
|
|
|
:options="state.yearOptions"
|
|
|
|
|
placeholder="- Any -"
|
|
|
|
|
style="width: 150px"
|
|
|
|
|
clearable
|
|
|
|
|
@update:value="handleYearChange"
|
|
|
|
|
/>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
</div>
|
2025-05-30 07:33:35 +00:00
|
|
|
|
|
|
|
|
|
<div class="filter-group">
|
|
|
|
|
<label class="filter-label">Items per page:</label>
|
|
|
|
|
<n-select
|
|
|
|
|
v-model:value="state.pageSize"
|
|
|
|
|
:options="state.pageSizeOptions"
|
|
|
|
|
style="width: 150px"
|
|
|
|
|
@update:value="handlePageSizeChange"
|
|
|
|
|
/>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
</div>
|
2025-05-30 07:33:35 +00:00
|
|
|
|
</div>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
<!-- 表格 -->
|
|
|
|
|
<div class="table-container">
|
|
|
|
|
<n-data-table
|
|
|
|
|
:columns="columns"
|
|
|
|
|
:data="paginatedData"
|
|
|
|
|
:pagination="false"
|
|
|
|
|
:bordered="false"
|
|
|
|
|
:size="'medium'"
|
|
|
|
|
:row-key="(row) => row.filingDate"
|
|
|
|
|
/>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
<!-- 分页器 -->
|
|
|
|
|
<div class="pagination-container">
|
|
|
|
|
<n-pagination
|
|
|
|
|
v-model:page="state.currentPage"
|
|
|
|
|
v-model:page-size="state.pageSize"
|
|
|
|
|
show-size-picker
|
|
|
|
|
show-quick-jumper
|
|
|
|
|
:item-count="filteredData.length"
|
|
|
|
|
:page-sizes="[10, 25, 50]"
|
|
|
|
|
@update:page="handlePageChange"
|
|
|
|
|
@update:page-size="handlePageSizeChange"
|
|
|
|
|
>
|
|
|
|
|
<template #prev>
|
|
|
|
|
<span>‹ Previous</span>
|
|
|
|
|
</template>
|
|
|
|
|
<template #next>
|
|
|
|
|
<span>Next ›</span>
|
|
|
|
|
</template>
|
|
|
|
|
</n-pagination>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
<div class="pagination-info">
|
|
|
|
|
Displaying {{ startIndex }} - {{ endIndex }} of
|
|
|
|
|
{{ filteredData.length }} results
|
|
|
|
|
</div>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
</div>
|
2025-05-30 07:33:35 +00:00
|
|
|
|
</div>
|
2025-05-22 12:33:26 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-05-30 07:33:35 +00:00
|
|
|
|
import { reactive, computed, h, onMounted } from "vue";
|
|
|
|
|
import { NSelect, NDataTable, NPagination, NButton, NIcon } from "naive-ui";
|
2025-05-22 12:33:26 +00:00
|
|
|
|
import { useI18n } from "vue-i18n";
|
2025-05-30 07:33:35 +00:00
|
|
|
|
import { useRouter } from "vue-router";
|
|
|
|
|
import { fileList } from "@/dict/secTestData.js";
|
2025-05-22 12:33:26 +00:00
|
|
|
|
const { t } = useI18n();
|
2025-05-30 07:33:35 +00:00
|
|
|
|
const router = useRouter();
|
|
|
|
|
import iconLink from "@/assets/image/icon/icon-link.png";
|
|
|
|
|
// 使用 reactive 管理所有状态
|
|
|
|
|
const state = reactive({
|
|
|
|
|
selectedYear: null,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
currentPage: 1,
|
|
|
|
|
|
|
|
|
|
// 年份选项
|
|
|
|
|
yearOptions: [
|
|
|
|
|
{ label: "- Any -", value: null },
|
|
|
|
|
{ label: "2025", value: 2025 },
|
|
|
|
|
{ label: "2024", value: 2024 },
|
|
|
|
|
{ label: "2023", value: 2023 },
|
|
|
|
|
{ label: "2022", value: 2022 },
|
|
|
|
|
{ label: "2021", value: 2021 },
|
|
|
|
|
{ label: "2020", value: 2020 },
|
|
|
|
|
{ label: "2019", value: 2019 },
|
|
|
|
|
{ label: "2018", value: 2018 },
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// 每页条数选项
|
|
|
|
|
pageSizeOptions: [
|
|
|
|
|
{ label: "10", value: 10 },
|
|
|
|
|
{ label: "25", value: 25 },
|
|
|
|
|
{ label: "50", value: 50 },
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// SEC文件数据
|
|
|
|
|
secFilingsData: [],
|
|
|
|
|
});
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
// 月份名称映射
|
|
|
|
|
const monthNames = [
|
|
|
|
|
"Jan",
|
|
|
|
|
"Feb",
|
|
|
|
|
"Mar",
|
|
|
|
|
"Apr",
|
|
|
|
|
"May",
|
|
|
|
|
"Jun",
|
|
|
|
|
"Jul",
|
|
|
|
|
"Aug",
|
|
|
|
|
"Sep",
|
|
|
|
|
"Oct",
|
|
|
|
|
"Nov",
|
|
|
|
|
"Dec",
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
state.secFilingsData = fileList.map((item) => {
|
|
|
|
|
// 从 filingDate 中提取年份,支持两种格式:
|
|
|
|
|
// 1. "Feb 04, 2019" 格式(英文)
|
|
|
|
|
// 2. "2025-10-24" 格式(ISO格式)转换为英文格式
|
|
|
|
|
let year = null;
|
|
|
|
|
let formattedDate = item.filingDate;
|
|
|
|
|
|
|
|
|
|
if (item.filingDate) {
|
|
|
|
|
if (item.filingDate.includes(", ")) {
|
|
|
|
|
// "Feb 04, 2019" 格式,已经是英文格式,保持不变
|
|
|
|
|
year = parseInt(item.filingDate.split(", ")[1]);
|
|
|
|
|
} else if (item.filingDate.includes("-")) {
|
|
|
|
|
// "2025-10-24" 格式,转换为 "Oct 24, 2025" 英文格式
|
|
|
|
|
const dateParts = item.filingDate.split("-");
|
|
|
|
|
const yearPart = parseInt(dateParts[0]);
|
|
|
|
|
const monthPart = parseInt(dateParts[1]);
|
|
|
|
|
const dayPart = parseInt(dateParts[2]);
|
|
|
|
|
|
|
|
|
|
year = yearPart;
|
|
|
|
|
const monthName = monthNames[monthPart - 1]; // 月份从1开始,数组从0开始
|
|
|
|
|
const dayFormatted = dayPart.toString().padStart(2, "0");
|
|
|
|
|
formattedDate = `${monthName} ${dayFormatted}, ${yearPart}`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...item,
|
|
|
|
|
formattedDate: formattedDate, // 更新为统一的英文格式
|
|
|
|
|
year: year,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
// 表格列定义
|
|
|
|
|
const columns = [
|
2025-05-22 12:33:26 +00:00
|
|
|
|
{
|
2025-05-30 07:33:35 +00:00
|
|
|
|
title: "Filing Date",
|
|
|
|
|
key: "formattedDate",
|
|
|
|
|
sorter: true,
|
|
|
|
|
width: 150,
|
2025-05-22 12:33:26 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
2025-05-30 07:33:35 +00:00
|
|
|
|
title: "Form",
|
|
|
|
|
key: "form",
|
|
|
|
|
width: 120,
|
|
|
|
|
render: (row) => {
|
|
|
|
|
return h(
|
|
|
|
|
"a",
|
|
|
|
|
{
|
|
|
|
|
href: "javascript:void(0)",
|
|
|
|
|
style: {
|
|
|
|
|
color: "#0078d7",
|
|
|
|
|
textDecoration: "none",
|
|
|
|
|
cursor: "pointer",
|
|
|
|
|
},
|
|
|
|
|
onClick: (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
router.push({
|
|
|
|
|
path: "/secfilingsDefail",
|
|
|
|
|
query: {
|
|
|
|
|
filingDate: row.filingDate,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
onMouseover: (e) => {
|
|
|
|
|
e.target.style.textDecoration = "underline";
|
|
|
|
|
},
|
|
|
|
|
onMouseout: (e) => {
|
|
|
|
|
e.target.style.textDecoration = "none";
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
row.form
|
|
|
|
|
);
|
|
|
|
|
},
|
2025-05-23 11:50:19 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
2025-05-30 07:33:35 +00:00
|
|
|
|
title: "Description",
|
|
|
|
|
key: "description",
|
|
|
|
|
ellipsis: {
|
|
|
|
|
tooltip: true,
|
|
|
|
|
},
|
2025-05-23 11:50:19 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
2025-05-30 07:33:35 +00:00
|
|
|
|
title: "View",
|
|
|
|
|
key: "view",
|
|
|
|
|
width: 150,
|
|
|
|
|
render: (row) => {
|
|
|
|
|
return h(
|
|
|
|
|
"div",
|
|
|
|
|
{
|
|
|
|
|
style: {
|
|
|
|
|
display: "flex",
|
|
|
|
|
gap: "8px",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
[
|
|
|
|
|
h(
|
|
|
|
|
"a",
|
|
|
|
|
{
|
|
|
|
|
href: row.link,
|
|
|
|
|
style: {
|
|
|
|
|
color: "#0078d7",
|
|
|
|
|
textDecoration: "none",
|
|
|
|
|
fontSize: "12px",
|
|
|
|
|
},
|
|
|
|
|
onMouseover: (e) => {
|
|
|
|
|
e.target.style.textDecoration = "underline";
|
|
|
|
|
},
|
|
|
|
|
onMouseout: (e) => {
|
|
|
|
|
e.target.style.textDecoration = "none";
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
h("img", {
|
|
|
|
|
src: iconLink,
|
|
|
|
|
alt: "link",
|
|
|
|
|
style: {
|
|
|
|
|
width: "24px",
|
|
|
|
|
height: "24px",
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
},
|
2025-05-22 12:33:26 +00:00
|
|
|
|
},
|
2025-05-30 07:33:35 +00:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// 筛选后的数据
|
|
|
|
|
const filteredData = computed(() => {
|
|
|
|
|
let data = state.secFilingsData;
|
|
|
|
|
|
|
|
|
|
if (state.selectedYear) {
|
|
|
|
|
data = data.filter((item) => item.year === state.selectedYear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 分页数据
|
|
|
|
|
const paginatedData = computed(() => {
|
|
|
|
|
const start = (state.currentPage - 1) * state.pageSize;
|
|
|
|
|
const end = start + state.pageSize;
|
|
|
|
|
return filteredData.value.slice(start, end);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 总页数
|
|
|
|
|
const totalPages = computed(() => {
|
|
|
|
|
return Math.ceil(filteredData.value.length / state.pageSize);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 当前页起始索引
|
|
|
|
|
const startIndex = computed(() => {
|
|
|
|
|
return (state.currentPage - 1) * state.pageSize + 1;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 当前页结束索引
|
|
|
|
|
const endIndex = computed(() => {
|
|
|
|
|
const end = state.currentPage * state.pageSize;
|
|
|
|
|
return Math.min(end, filteredData.value.length);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 处理年份变化
|
|
|
|
|
const handleYearChange = (value) => {
|
|
|
|
|
state.selectedYear = value;
|
|
|
|
|
state.currentPage = 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理页码变化
|
|
|
|
|
const handlePageChange = (page) => {
|
|
|
|
|
state.currentPage = page;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理每页条数变化
|
|
|
|
|
const handlePageSizeChange = (size) => {
|
|
|
|
|
state.pageSize = size;
|
|
|
|
|
state.currentPage = 1;
|
|
|
|
|
};
|
2025-05-22 12:33:26 +00:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.page-container {
|
|
|
|
|
background-image: url("@/assets/image/bg.png");
|
|
|
|
|
background-size: 100% 100%;
|
|
|
|
|
background-position: center;
|
|
|
|
|
background-repeat: no-repeat;
|
2025-05-30 07:33:35 +00:00
|
|
|
|
min-height: 100vh;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
padding: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.sec-filings-container {
|
|
|
|
|
max-width: 1200px;
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
background: white;
|
|
|
|
|
padding: 40px;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.page-title {
|
|
|
|
|
font-size: 32px;
|
|
|
|
|
font-weight: bold;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
color: #333;
|
2025-05-30 07:33:35 +00:00
|
|
|
|
margin-bottom: 40px;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.filters {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 40px;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
margin-bottom: 30px;
|
2025-05-30 07:33:35 +00:00
|
|
|
|
align-items: end;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.filter-group {
|
2025-05-22 12:33:26 +00:00
|
|
|
|
display: flex;
|
2025-05-30 07:33:35 +00:00
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 8px;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.filter-label {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-weight: 500;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.table-container {
|
|
|
|
|
.n-data-table {
|
|
|
|
|
--n-th-color: #f5f5f5;
|
|
|
|
|
--n-th-text-color: #333;
|
|
|
|
|
--n-td-color: #fff;
|
|
|
|
|
--n-border-color: #e0e0e0;
|
|
|
|
|
}
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.pagination-container {
|
2025-05-22 12:33:26 +00:00
|
|
|
|
display: flex;
|
2025-05-23 11:50:22 +00:00
|
|
|
|
justify-content: space-between;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
align-items: center;
|
2025-05-30 07:33:35 +00:00
|
|
|
|
margin-top: 20px;
|
|
|
|
|
padding: 20px 0;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
2025-05-30 07:33:35 +00:00
|
|
|
|
|
|
|
|
|
.pagination-info {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #666;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
:deep(.n-data-table-th) {
|
|
|
|
|
background-color: #9e9e9e !important;
|
|
|
|
|
color: white !important;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
text-align: left;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
:deep(.n-data-table-td) {
|
|
|
|
|
border-bottom: 1px solid #e0e0e0;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
:deep(.n-data-table-tr:hover .n-data-table-td) {
|
|
|
|
|
background-color: #f9f9f9;
|
|
|
|
|
}
|
2025-05-22 12:33:26 +00:00
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
:deep(.n-select) {
|
|
|
|
|
.n-base-selection {
|
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
|
border-radius: 4px;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
:deep(.n-pagination) {
|
|
|
|
|
.n-pagination-item {
|
|
|
|
|
border: 1px solid #ccc;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
&.n-pagination-item--active {
|
|
|
|
|
background-color: #969696;
|
|
|
|
|
border-color: #969696;
|
|
|
|
|
color: white;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.n-pagination-quick-jumper {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
2025-05-22 12:33:26 +00:00
|
|
|
|
|
2025-05-30 07:33:35 +00:00
|
|
|
|
.n-pagination-sizes {
|
|
|
|
|
font-size: 14px;
|
2025-05-22 12:33:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|