894 lines
20 KiB
Vue
894 lines
20 KiB
Vue
<template>
|
||
<div class="historic-data-container w-[1240px]">
|
||
<div class="echarts-container">
|
||
<customEcharts></customEcharts>
|
||
</div>
|
||
<div class="header">
|
||
<!-- 标题区域 -->
|
||
<div class="title-section">
|
||
<div class="title-decoration"></div>
|
||
<div class="historic-title">Historical Data</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="filter-container">
|
||
<span class="range-label">Range</span>
|
||
<div
|
||
v-for="option in durationOptions"
|
||
:key="option.key"
|
||
class="filter-option"
|
||
:class="{ active: state.selectedDuration === option.key }"
|
||
@click="handleDurationChange(option.key)"
|
||
>
|
||
{{
|
||
option.label
|
||
.replace(" Months", "m")
|
||
.replace(" Years", "Y")
|
||
.replace(" Year", "Y")
|
||
.replace(" to Date", "TD")
|
||
}}
|
||
</div>
|
||
</div>
|
||
<!-- reports-table from annualreports -->
|
||
<div class="reports-table">
|
||
<div class="table-header">
|
||
<div
|
||
class="column"
|
||
v-for="col in columns"
|
||
:key="col.key"
|
||
:style="{
|
||
width: col.width ? col.width + 'px' : 'auto',
|
||
flex: col.width ? 'none' : 1,
|
||
'text-align': col.align,
|
||
}"
|
||
>
|
||
{{ col.title }}
|
||
</div>
|
||
</div>
|
||
<div class="reports-list">
|
||
<div
|
||
class="table-row"
|
||
v-for="(row, index) in paginatedData"
|
||
:key="index"
|
||
>
|
||
<div
|
||
class="column"
|
||
v-for="col in columns"
|
||
:key="col.key"
|
||
:style="{
|
||
width: col.width ? col.width + 'px' : 'auto',
|
||
flex: col.width ? 'none' : 1,
|
||
'text-align': col.align,
|
||
}"
|
||
>
|
||
<span
|
||
v-if="col.key === 'change'"
|
||
:style="{
|
||
color:
|
||
parseFloat(row.change) < 0
|
||
? '#cf3050'
|
||
: parseFloat(row.change) > 0
|
||
? '#18a058'
|
||
: '',
|
||
}"
|
||
>
|
||
{{ row[col.key] }}
|
||
</span>
|
||
<span v-else>
|
||
{{ row[col.key] }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- pagination-container from annualreports -->
|
||
<div class="pagination-container">
|
||
<div class="pagination-info">
|
||
Displaying {{ displayRange.start }} - {{ displayRange.end }} of
|
||
{{ state.tableData.length }} results
|
||
</div>
|
||
<div class="pagination-controls">
|
||
<div class="pagination-buttons">
|
||
<button
|
||
class="page-btn prev-btn"
|
||
:disabled="state.currentPage === 1"
|
||
@click="goToPrevPage"
|
||
>
|
||
<svg width="5" height="9" viewBox="0 0 5 9" fill="none">
|
||
<path
|
||
d="M4 1L1 4.5L4 8"
|
||
stroke="#455363"
|
||
stroke-width="1.5"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
|
||
<template v-for="page in getVisiblePages()" :key="page">
|
||
<button
|
||
v-if="page !== '...'"
|
||
class="page-btn"
|
||
:class="{ active: page === state.currentPage }"
|
||
@click="goToPage(page)"
|
||
>
|
||
{{ page }}
|
||
</button>
|
||
<button v-else class="page-btn disabled" disabled>...</button>
|
||
</template>
|
||
|
||
<button
|
||
class="page-btn next-btn"
|
||
:disabled="state.currentPage === totalPages"
|
||
@click="goToNextPage"
|
||
>
|
||
<svg width="5" height="9" viewBox="0 0 5 9" fill="none">
|
||
<path
|
||
d="M1 1L4 4.5L1 8"
|
||
stroke="#455363"
|
||
stroke-width="1.5"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div class="page-size-selector" @click="togglePageSizeMenu">
|
||
<span>{{ state.pageSize }}/page</span>
|
||
<svg width="10" height="5" viewBox="0 0 10 5" fill="none">
|
||
<path
|
||
d="M1 1L5 4L9 1"
|
||
stroke="#455363"
|
||
stroke-width="1.5"
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
/>
|
||
</svg>
|
||
<div v-if="showPageSizeMenu" class="page-size-menu">
|
||
<div
|
||
v-for="size in [10, 50, 100, 500, 1000]"
|
||
:key="size"
|
||
class="page-size-option"
|
||
:class="{ active: state.pageSize === size }"
|
||
@click="handlePageSizeChange(size)"
|
||
>
|
||
{{ size }}/page
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="goto-section">
|
||
<span>Goto</span>
|
||
<input
|
||
type="number"
|
||
v-model="state.gotoPage"
|
||
class="goto-input"
|
||
:min="1"
|
||
:max="totalPages"
|
||
@keyup.enter="handleGoto"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- <div class="back-to-top-link">
|
||
<a href="#" @click.prevent="scrollToTop">
|
||
Back to Top
|
||
<n-icon><arrow-up-outline /></n-icon>
|
||
</a>
|
||
</div> -->
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { NDropdown, NIcon } from "naive-ui";
|
||
import { reactive, onMounted, h, computed, ref, watch, onUnmounted } from "vue";
|
||
import axios from "axios";
|
||
import { ChevronDownOutline, ArrowUpOutline } from "@vicons/ionicons5";
|
||
import defaultTableData from "../data";
|
||
import customEcharts from "@/components/customEcharts/index.vue";
|
||
|
||
// 数据筛选选项
|
||
const periodOptions = [
|
||
{ label: "Daily", key: "Daily" },
|
||
{ label: "Weekly", key: "Weekly" },
|
||
{ label: "Monthly", key: "Monthly" },
|
||
{ label: "Quarterly", key: "Quarterly" },
|
||
{ label: "Annual", key: "Annual" },
|
||
];
|
||
|
||
const durationOptions = [
|
||
{ label: "3 Months", key: "3 Months" },
|
||
{ label: "6 Months", key: "6 Months" },
|
||
{ label: "YTD", key: "Year to Date" },
|
||
{ label: "1 Year", key: "1 Year" },
|
||
{ label: "5 Years", key: "5 Years" },
|
||
{ label: "10 Years", key: "10 Years" },
|
||
];
|
||
|
||
// 分页大小选项
|
||
const pageSizeOptions = [
|
||
{ label: "10", key: 10 },
|
||
{ label: "50", key: 50 },
|
||
{ label: "100", key: 100 },
|
||
{ label: "500", key: 500 },
|
||
{ label: "1000", key: 1000 },
|
||
];
|
||
|
||
const state = reactive({
|
||
selectedPeriod: "Daily",
|
||
selectedDuration: "6 Months",
|
||
tableData: [],
|
||
currentPage: 1,
|
||
pageSize: 10,
|
||
gotoPage: 1,
|
||
});
|
||
|
||
const showPageSizeMenu = ref(false);
|
||
|
||
// 计算总页数
|
||
const totalPages = computed(() => {
|
||
return Math.ceil(state.tableData.length / state.pageSize);
|
||
});
|
||
|
||
// 计算当前页的数据
|
||
const paginatedData = computed(() => {
|
||
const start = (state.currentPage - 1) * state.pageSize;
|
||
const end = start + state.pageSize;
|
||
return state.tableData.slice(start, end);
|
||
});
|
||
|
||
// 表格列定义
|
||
const columns = [
|
||
{
|
||
title: "Date",
|
||
key: "date",
|
||
align: "left",
|
||
fixed: "left",
|
||
width: 150,
|
||
},
|
||
{
|
||
title: "Open",
|
||
key: "open",
|
||
align: "center",
|
||
},
|
||
{
|
||
title: "High",
|
||
key: "high",
|
||
align: "center",
|
||
},
|
||
{
|
||
title: "Low",
|
||
key: "low",
|
||
align: "center",
|
||
},
|
||
{
|
||
title: "Close",
|
||
key: "close",
|
||
align: "center",
|
||
},
|
||
{
|
||
title: "Adj. Close",
|
||
key: "adjClose",
|
||
align: "center",
|
||
width: 115,
|
||
},
|
||
{
|
||
title: "Change",
|
||
key: "change",
|
||
align: "center",
|
||
},
|
||
{
|
||
title: "Volume",
|
||
key: "volume",
|
||
align: "center",
|
||
},
|
||
];
|
||
|
||
// 处理下拉选项变更
|
||
const handlePeriodChange = (key) => {
|
||
state.selectedPeriod = key;
|
||
if (key === "Annual") {
|
||
handleDurationChange("Full History");
|
||
return;
|
||
}
|
||
if (key === "Monthly") {
|
||
handleDurationChange("10 Years");
|
||
return;
|
||
}
|
||
if (key === "Quarterly") {
|
||
handleDurationChange("10 Years");
|
||
return;
|
||
}
|
||
getPageData();
|
||
};
|
||
|
||
const handleDurationChange = (key) => {
|
||
state.selectedDuration = key;
|
||
state.currentPage = 1;
|
||
getPageData();
|
||
};
|
||
|
||
const displayRange = computed(() => {
|
||
const start = (state.currentPage - 1) * state.pageSize + 1;
|
||
const end = Math.min(
|
||
state.currentPage * state.pageSize,
|
||
state.tableData.length
|
||
);
|
||
return { start, end };
|
||
});
|
||
|
||
const goToPage = (page) => {
|
||
if (page >= 1 && page <= totalPages.value) {
|
||
state.currentPage = page;
|
||
}
|
||
};
|
||
|
||
const goToPrevPage = () => {
|
||
if (state.currentPage > 1) {
|
||
state.currentPage--;
|
||
}
|
||
};
|
||
|
||
const goToNextPage = () => {
|
||
if (state.currentPage < totalPages.value) {
|
||
state.currentPage++;
|
||
}
|
||
};
|
||
|
||
// 处理分页
|
||
const handlePageSizeChange = (size) => {
|
||
state.pageSize = size;
|
||
state.currentPage = 1; // 重置到第一页
|
||
};
|
||
|
||
const handleGoto = () => {
|
||
const page = parseInt(state.gotoPage);
|
||
if (page >= 1 && page <= totalPages.value) {
|
||
state.currentPage = page;
|
||
}
|
||
};
|
||
|
||
const togglePageSizeMenu = () => {
|
||
showPageSizeMenu.value = !showPageSizeMenu.value;
|
||
};
|
||
|
||
const getVisiblePages = () => {
|
||
const current = state.currentPage;
|
||
const total = totalPages.value;
|
||
const pages = [];
|
||
|
||
if (total <= 7) {
|
||
// 如果总页数小于等于7,显示所有页码
|
||
for (let i = 1; i <= total; i++) {
|
||
pages.push(i);
|
||
}
|
||
} else {
|
||
// 显示第一页
|
||
pages.push(1);
|
||
|
||
if (current <= 4) {
|
||
// 当前页在前4页
|
||
for (let i = 2; i <= 5; i++) {
|
||
pages.push(i);
|
||
}
|
||
pages.push("...");
|
||
pages.push(total);
|
||
} else if (current >= total - 3) {
|
||
// 当前页在后4页
|
||
pages.push("...");
|
||
for (let i = total - 4; i <= total; i++) {
|
||
pages.push(i);
|
||
}
|
||
} else {
|
||
// 当前页在中间
|
||
pages.push("...");
|
||
for (let i = current - 1; i <= current + 1; i++) {
|
||
pages.push(i);
|
||
}
|
||
pages.push("...");
|
||
pages.push(total);
|
||
}
|
||
}
|
||
|
||
return pages;
|
||
};
|
||
|
||
// 回到顶部
|
||
const scrollToTop = () => {
|
||
// 尝试多种方法
|
||
// 1. 使用document.body
|
||
document.body.scrollTop = 0;
|
||
// 2. 使用document.documentElement (HTML元素)
|
||
document.documentElement.scrollTop = 0;
|
||
// 3. 使用scrollIntoView
|
||
document.querySelector(".historic-data-container").scrollIntoView({
|
||
behavior: "smooth",
|
||
block: "start",
|
||
});
|
||
};
|
||
onMounted(() => {
|
||
getPageData();
|
||
document.addEventListener("click", handleClickOutside);
|
||
});
|
||
|
||
onUnmounted(() => {
|
||
document.removeEventListener("click", handleClickOutside);
|
||
});
|
||
|
||
const handleClickOutside = (event) => {
|
||
if (!event.target.closest(".page-size-selector")) {
|
||
showPageSizeMenu.value = false;
|
||
}
|
||
};
|
||
|
||
watch(
|
||
() => state.pageSize,
|
||
() => {
|
||
state.currentPage = 1;
|
||
}
|
||
);
|
||
watch(
|
||
() => state.currentPage,
|
||
(newPage) => {
|
||
state.gotoPage = newPage;
|
||
}
|
||
);
|
||
|
||
const getPageDefaultData = async () => {
|
||
try {
|
||
let url =
|
||
"https://stockanalysis.com/api/symbol/a/OTC-MINM/history?period=Daily&range=3M";
|
||
const res = await axios.get(url);
|
||
let originalData = res.data.data;
|
||
|
||
// 转换为日期格式:"Nov 26, 2024"
|
||
let calcApiData = originalData.map((item) => [
|
||
new Date(item[0]).toLocaleDateString("en-US", {
|
||
month: "short",
|
||
day: "numeric",
|
||
year: "numeric",
|
||
}),
|
||
item[1],
|
||
]);
|
||
// console.log('接口数据', calcApiData)
|
||
|
||
// 使用API数据更新defaultTableData中的close和adjClose值
|
||
const updatedTableData = defaultTableData.map((tableItem) => {
|
||
// 查找对应日期的API数据
|
||
const matchedApiData = calcApiData.find(
|
||
(apiItem) => apiItem[0] === tableItem.date
|
||
);
|
||
|
||
if (matchedApiData) {
|
||
// 更新close和adjClose值
|
||
return {
|
||
...tableItem,
|
||
close: matchedApiData[1].toFixed(2),
|
||
adjClose: matchedApiData[1].toFixed(2),
|
||
};
|
||
}
|
||
return tableItem;
|
||
});
|
||
|
||
state.tableData = updatedTableData;
|
||
} catch (error) {
|
||
// console.error('获取数据失败', error)
|
||
}
|
||
};
|
||
const getPageData = async () => {
|
||
let range = "";
|
||
let now = new Date();
|
||
const last = new Date(now);
|
||
last.setMonth(now.getMonth() - 6);
|
||
let fromDate = last;
|
||
let toDate =
|
||
now.getFullYear() +
|
||
"-" +
|
||
String(now.getMonth() + 1).padStart(2, "0") +
|
||
"-" +
|
||
String(now.getDate()).padStart(2, "0");
|
||
if (state.selectedDuration === "3 Months") {
|
||
range = "3M";
|
||
const last = new Date(now);
|
||
last.setMonth(now.getMonth() - 3);
|
||
fromDate = last;
|
||
} else if (state.selectedDuration === "6 Months") {
|
||
range = "6M";
|
||
const last = new Date(now);
|
||
last.setMonth(now.getMonth() - 6);
|
||
fromDate = last;
|
||
} else if (state.selectedDuration === "Year to Date") {
|
||
range = "YTD";
|
||
fromDate = new Date(now.getFullYear(), 0, 1);
|
||
} else if (state.selectedDuration === "1 Year") {
|
||
range = "1Y";
|
||
const last = new Date(now);
|
||
last.setFullYear(now.getFullYear() - 1);
|
||
fromDate = last;
|
||
} else if (state.selectedDuration === "5 Years") {
|
||
range = "5Y";
|
||
const last = new Date(now);
|
||
last.setFullYear(now.getFullYear() - 5);
|
||
fromDate = last;
|
||
} else if (state.selectedDuration === "10 Years") {
|
||
range = "10Y";
|
||
const last = new Date(now);
|
||
last.setFullYear(now.getFullYear() - 10);
|
||
fromDate = last;
|
||
} else if (state.selectedDuration === "Full History") {
|
||
range = "Max";
|
||
fromDate = new Date("2009-10-07");
|
||
}
|
||
let finalFromDate =
|
||
fromDate.getFullYear() +
|
||
"-" +
|
||
String(fromDate.getMonth() + 1).padStart(2, "0") +
|
||
"-" +
|
||
String(fromDate.getDate()).padStart(2, "0");
|
||
let url =
|
||
"https://common.szjixun.cn/api/stock/history/list?from=" +
|
||
finalFromDate +
|
||
"&to=" +
|
||
toDate;
|
||
const res = await axios.get(url);
|
||
if (res.status === 200) {
|
||
if (res.data.status === 0) {
|
||
// 转换为日期格式:"Nov 26, 2024"
|
||
let resultData = res.data.data.map((item) => {
|
||
return {
|
||
date: new Date(item.date).toLocaleDateString("en-US", {
|
||
month: "short",
|
||
day: "numeric",
|
||
year: "numeric",
|
||
}),
|
||
open: item.open != null ? Number(item.open).toFixed(2) : "",
|
||
high: item.high != null ? Number(item.high).toFixed(2) : "",
|
||
low: item.low != null ? Number(item.low).toFixed(2) : "",
|
||
close: item.close != null ? Number(item.close).toFixed(2) : "",
|
||
adjClose: item.close != null ? Number(item.close).toFixed(2) : "",
|
||
change:
|
||
item.changePercent != null
|
||
? Number(item.changePercent).toFixed(2) + "%"
|
||
: "",
|
||
volume: item.volume,
|
||
};
|
||
});
|
||
state.tableData = resultData;
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.historic-data-container {
|
||
// width: 932px;
|
||
margin: 0 auto;
|
||
|
||
.header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 40px;
|
||
|
||
.title {
|
||
font-size: 40px;
|
||
font-weight: bold;
|
||
margin: 0;
|
||
}
|
||
}
|
||
|
||
.filter-container {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
padding: 0 16px;
|
||
margin-bottom: 32px;
|
||
margin-top: 32px;
|
||
|
||
.range-label {
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
line-height: 1.375em;
|
||
letter-spacing: 3%;
|
||
color: #455363;
|
||
}
|
||
|
||
.filter-option {
|
||
padding: 7px 12px;
|
||
border-radius: 3px;
|
||
background-color: #efefef;
|
||
cursor: pointer;
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
line-height: 1.375em;
|
||
color: #000000;
|
||
transition: all 0.2s ease;
|
||
|
||
&:hover {
|
||
background-color: #e0e0e0;
|
||
}
|
||
|
||
&.active {
|
||
background-color: #ff7bac;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
}
|
||
.back-to-top-link {
|
||
display: flex;
|
||
justify-content: center;
|
||
margin-top: 16px;
|
||
|
||
a {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
color: #2563eb;
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
text-decoration: none;
|
||
|
||
&:hover {
|
||
text-decoration: underline;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.reports-table {
|
||
width: 100%;
|
||
background: #ffffff;
|
||
border-radius: 16px;
|
||
box-shadow: 0px 3px 14px 0px rgba(0, 0, 0, 0.16);
|
||
padding: 16px;
|
||
}
|
||
|
||
.table-header {
|
||
display: flex;
|
||
background: #fff0f5;
|
||
border-radius: 8px;
|
||
padding: 16px 0;
|
||
margin-bottom: 4px;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.column {
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 500;
|
||
font-size: 16px;
|
||
line-height: 1.375em;
|
||
letter-spacing: 3%;
|
||
color: #000000;
|
||
padding: 0 16px;
|
||
}
|
||
}
|
||
|
||
.table-row {
|
||
display: flex;
|
||
padding: 16px 0;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
position: relative;
|
||
border-radius: 8px;
|
||
&:hover {
|
||
background: #fff8fb;
|
||
}
|
||
|
||
// &:last-child {
|
||
// border-bottom: none;
|
||
// }
|
||
|
||
&:nth-child(even) {
|
||
margin: 4px 0;
|
||
}
|
||
}
|
||
|
||
.reports-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
.column {
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
line-height: 1.375em;
|
||
letter-spacing: 3%;
|
||
color: #455363;
|
||
padding: 0 16px;
|
||
position: relative;
|
||
}
|
||
|
||
.table-row .column:not(:last-child)::after {
|
||
content: "";
|
||
position: absolute;
|
||
right: 0;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
height: 24px;
|
||
border-right: 1px dashed #e0e0e6;
|
||
}
|
||
|
||
// 分页器样式
|
||
.pagination-container {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-top: 20px;
|
||
justify-content: flex-end;
|
||
margin-bottom: 30px;
|
||
gap: 21px;
|
||
}
|
||
|
||
.pagination-info {
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 16px;
|
||
line-height: 1.4375em;
|
||
color: #455363;
|
||
text-align: right;
|
||
}
|
||
|
||
.pagination-controls {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.pagination-buttons {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.page-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 28px;
|
||
height: 28px;
|
||
border: 1px solid #e0e0e6;
|
||
border-radius: 3px;
|
||
background: #ffffff;
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
line-height: 1.428em;
|
||
color: #455363;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
|
||
&:hover:not(:disabled) {
|
||
border-color: #ff7bac;
|
||
color: #ff7bac;
|
||
}
|
||
|
||
&.active {
|
||
border-color: #ff7bac;
|
||
color: #ff7bac;
|
||
background: #fff0f5;
|
||
}
|
||
|
||
&:disabled {
|
||
cursor: not-allowed;
|
||
opacity: 0.5;
|
||
}
|
||
|
||
&.disabled {
|
||
cursor: not-allowed;
|
||
opacity: 0.5;
|
||
}
|
||
}
|
||
|
||
.page-size-selector {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 18px;
|
||
padding: 4px 12px;
|
||
height: 28px;
|
||
border: 1px solid #e0e0e6;
|
||
border-radius: 3px;
|
||
background: #ffffff;
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
line-height: 1.428em;
|
||
color: #455363;
|
||
cursor: pointer;
|
||
|
||
&:hover {
|
||
border-color: #ff7bac;
|
||
}
|
||
}
|
||
|
||
.page-size-menu {
|
||
position: absolute;
|
||
bottom: 100%;
|
||
left: 0;
|
||
right: 0;
|
||
background: #ffffff;
|
||
border: 1px solid #e0e0e6;
|
||
border-radius: 3px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
z-index: 1000;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.page-size-option {
|
||
padding: 8px 12px;
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
line-height: 1.428em;
|
||
color: #455363;
|
||
cursor: pointer;
|
||
transition: background-color 0.2s ease;
|
||
|
||
&:hover {
|
||
background: #fff0f5;
|
||
}
|
||
|
||
&.active {
|
||
background: #fff0f5;
|
||
color: #ff7bac;
|
||
}
|
||
}
|
||
|
||
.goto-section {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
line-height: 1.428em;
|
||
color: #455363;
|
||
margin-right: 16px;
|
||
}
|
||
|
||
.goto-input {
|
||
width: 60px;
|
||
height: 28px;
|
||
padding: 4px 12px;
|
||
border: 1px solid #e0e0e6;
|
||
border-radius: 3px;
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
line-height: 1.428em;
|
||
color: #455363;
|
||
text-align: center;
|
||
|
||
&:focus {
|
||
outline: none;
|
||
border-color: #ff7bac;
|
||
}
|
||
}
|
||
|
||
.title-section {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
padding: 0 16px;
|
||
}
|
||
|
||
.title-decoration {
|
||
width: 58px;
|
||
height: 7px;
|
||
background: #ff7bac;
|
||
margin: auto 0;
|
||
margin-top: 43px;
|
||
}
|
||
|
||
.historic-title {
|
||
font-family: "PingFang SC", sans-serif;
|
||
font-weight: 500;
|
||
font-size: 40px;
|
||
line-height: 1.4em;
|
||
letter-spacing: 3%;
|
||
color: #000000;
|
||
}
|
||
</style>
|