fix historic-stock 375,press-releases 375
This commit is contained in:
parent
ad91c54d8d
commit
4f59eb52e1
397
src/components/DateWheelPicker.vue
Normal file
397
src/components/DateWheelPicker.vue
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
<template>
|
||||||
|
<div class="picker-mask" @click.self="emit('close')">
|
||||||
|
<div class="picker-panel">
|
||||||
|
<div class="picker-title">
|
||||||
|
Select Time
|
||||||
|
<svg
|
||||||
|
@click="emit('close')"
|
||||||
|
style="cursor: pointer"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M0.666016 9.74935C0.666016 4.59469 4.84469 0.416016 9.99935 0.416016C15.154 0.416016 19.3327 4.59469 19.3327 9.74935C19.3327 14.904 15.154 19.0827 9.99935 19.0827C4.84469 19.0827 0.666016 14.904 0.666016 9.74935Z"
|
||||||
|
fill="#CCCCCC"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M12.833 5.84961C13.1273 5.55596 13.6042 5.55565 13.8965 5.84863C14.1907 6.14223 14.1893 6.61848 13.8965 6.91211L11.0615 9.74609L13.9043 12.5898C14.1973 12.8848 14.1986 13.3607 13.9043 13.6543C13.6114 13.947 13.1344 13.9471 12.8408 13.6543L9.99707 10.8105L7.1582 13.6504C6.86386 13.9444 6.38729 13.9446 6.09375 13.6504C5.8002 13.3574 5.80045 12.8809 6.09473 12.5859L8.93359 9.74707L6.10254 6.91602C5.80956 6.62236 5.80889 6.1452 6.10254 5.85156C6.39486 5.55817 6.87209 5.55802 7.16699 5.85156L9.99805 8.68262L12.833 5.84961Z"
|
||||||
|
fill="white"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="picker-columns"
|
||||||
|
:style="{ height: wheelViewportHeight + 'px' }"
|
||||||
|
>
|
||||||
|
<div class="center-lines" :style="{ height: wheelItemHeight + 'px' }">
|
||||||
|
<div class="line"></div>
|
||||||
|
<div class="line"></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="picker-col year-col"
|
||||||
|
ref="yearColRef"
|
||||||
|
@scroll.passive="(e) => handleWheelScroll('year', e)"
|
||||||
|
@wheel.prevent="(e) => handleWheelStep('year', e)"
|
||||||
|
:style="{
|
||||||
|
scrollPaddingTop: wheelCenterPad + 'px',
|
||||||
|
scrollPaddingBottom: wheelCenterPad + 'px',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div :style="{ height: wheelCenterPad + 'px' }"></div>
|
||||||
|
<div
|
||||||
|
v-for="y in years"
|
||||||
|
:key="'y' + y"
|
||||||
|
class="picker-item"
|
||||||
|
:class="{ active: y === localYear }"
|
||||||
|
:style="{
|
||||||
|
height: wheelItemHeight + 'px',
|
||||||
|
}"
|
||||||
|
@click="localYear = y"
|
||||||
|
>
|
||||||
|
{{ y }}
|
||||||
|
</div>
|
||||||
|
<div :style="{ height: wheelCenterPad + 'px' }"></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="picker-col month-col"
|
||||||
|
ref="monthColRef"
|
||||||
|
@scroll.passive="(e) => handleWheelScroll('month', e)"
|
||||||
|
@wheel.prevent="(e) => handleWheelStep('month', e)"
|
||||||
|
:style="{
|
||||||
|
scrollPaddingTop: wheelCenterPad + 'px',
|
||||||
|
scrollPaddingBottom: wheelCenterPad + 'px',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div :style="{ height: wheelCenterPad + 'px' }"></div>
|
||||||
|
<div
|
||||||
|
v-for="m in months"
|
||||||
|
:key="'m' + m"
|
||||||
|
class="picker-item"
|
||||||
|
:class="{ active: m === localMonth }"
|
||||||
|
:style="{
|
||||||
|
height: wheelItemHeight + 'px',
|
||||||
|
}"
|
||||||
|
@click="localMonth = m"
|
||||||
|
>
|
||||||
|
{{ m }}
|
||||||
|
</div>
|
||||||
|
<div :style="{ height: wheelCenterPad + 'px' }"></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="picker-col day-col"
|
||||||
|
ref="dayColRef"
|
||||||
|
@scroll.passive="(e) => handleWheelScroll('day', e)"
|
||||||
|
@wheel.prevent="(e) => handleWheelStep('day', e)"
|
||||||
|
:style="{
|
||||||
|
scrollPaddingTop: wheelCenterPad + 'px',
|
||||||
|
scrollPaddingBottom: wheelCenterPad + 'px',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div :style="{ height: wheelCenterPad + 'px' }"></div>
|
||||||
|
<div
|
||||||
|
v-for="d in daysInMonth(localYear, localMonth)"
|
||||||
|
:key="'d' + d"
|
||||||
|
class="picker-item"
|
||||||
|
:class="{ active: d === localDay }"
|
||||||
|
:style="{
|
||||||
|
height: wheelItemHeight + 'px',
|
||||||
|
}"
|
||||||
|
@click="localDay = d"
|
||||||
|
>
|
||||||
|
{{ d }}
|
||||||
|
</div>
|
||||||
|
<div :style="{ height: wheelCenterPad + 'px' }"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="picker-actions">
|
||||||
|
<button class="picker-confirm" @click="confirm">
|
||||||
|
Confirm Selection
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch, nextTick } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: { type: Object, required: true }, // { year, month, day }
|
||||||
|
minYear: { type: Number, default: 2009 },
|
||||||
|
maxYear: { type: Number, default: new Date().getFullYear() },
|
||||||
|
});
|
||||||
|
const emit = defineEmits(["update:modelValue", "close", "confirm"]);
|
||||||
|
|
||||||
|
const wheelItemBase = 8 * 5.12;
|
||||||
|
const wheelItemHeight = Math.round(wheelItemBase); // use integer px to avoid fractional rounding
|
||||||
|
const wheelViewportHeight = wheelItemHeight * 5;
|
||||||
|
const wheelCenterPad = (wheelViewportHeight - wheelItemHeight) / 2;
|
||||||
|
const isUserScrolling = ref(false);
|
||||||
|
|
||||||
|
const years = computed(() =>
|
||||||
|
Array.from(
|
||||||
|
{ length: props.maxYear - props.minYear + 1 },
|
||||||
|
(_, i) => props.minYear + i
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const months = Array.from({ length: 12 }, (_, i) => i + 1);
|
||||||
|
|
||||||
|
const localYear = ref(props.modelValue.year);
|
||||||
|
const localMonth = ref(props.modelValue.month);
|
||||||
|
const localDay = ref(props.modelValue.day);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(v) => {
|
||||||
|
localYear.value = v.year;
|
||||||
|
localMonth.value = v.month;
|
||||||
|
localDay.value = v.day;
|
||||||
|
nextTick(syncWheelPositions);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const yearColRef = ref(null);
|
||||||
|
const monthColRef = ref(null);
|
||||||
|
const dayColRef = ref(null);
|
||||||
|
|
||||||
|
function daysInMonth(year, month) {
|
||||||
|
return new Date(year, month, 0).getDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([localYear, localMonth], () => {
|
||||||
|
const dim = daysInMonth(localYear.value, localMonth.value);
|
||||||
|
if (localDay.value > dim) localDay.value = dim;
|
||||||
|
if (!isUserScrolling.value) {
|
||||||
|
nextTick(syncWheelPositions);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function syncWheelPositions() {
|
||||||
|
const yearIdx = years.value.indexOf(localYear.value);
|
||||||
|
const monthIdx = localMonth.value - 1;
|
||||||
|
const dayIdx = localDay.value - 1;
|
||||||
|
if (yearColRef.value) yearColRef.value.scrollTop = yearIdx * wheelItemHeight;
|
||||||
|
if (monthColRef.value)
|
||||||
|
monthColRef.value.scrollTop = monthIdx * wheelItemHeight;
|
||||||
|
if (dayColRef.value) dayColRef.value.scrollTop = dayIdx * wheelItemHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scrollTimers = { year: null, month: null, day: null };
|
||||||
|
const isAnimating = { year: false, month: false, day: false };
|
||||||
|
function getCenteredIndex(el) {
|
||||||
|
if (!el) return 0;
|
||||||
|
const raw = (el.scrollTop - wheelCenterPad) / wheelItemHeight;
|
||||||
|
return Math.round(raw);
|
||||||
|
}
|
||||||
|
function clamp(n, min, max) {
|
||||||
|
return Math.max(min, Math.min(n, max));
|
||||||
|
}
|
||||||
|
function getCenteredIndexByRect(el) {
|
||||||
|
if (!el) return 0;
|
||||||
|
const items = el.querySelectorAll(".picker-item");
|
||||||
|
if (!items || items.length === 0) return 0;
|
||||||
|
const containerRect = el.getBoundingClientRect();
|
||||||
|
const centerY = containerRect.top + containerRect.height / 2;
|
||||||
|
let nearestIdx = 0;
|
||||||
|
let nearestDist = Number.POSITIVE_INFINITY;
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const r = items[i].getBoundingClientRect();
|
||||||
|
const mid = r.top + r.height / 2;
|
||||||
|
const dist = Math.abs(mid - centerY);
|
||||||
|
if (dist < nearestDist) {
|
||||||
|
nearestDist = dist;
|
||||||
|
nearestIdx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearestIdx;
|
||||||
|
}
|
||||||
|
function handleWheelStep(type, e) {
|
||||||
|
const refMap = { year: yearColRef, month: monthColRef, day: dayColRef };
|
||||||
|
const el = refMap[type].value;
|
||||||
|
if (!el || isAnimating[type]) return;
|
||||||
|
const direction = e.deltaY > 0 ? 1 : -1;
|
||||||
|
let idx = getCenteredIndexByRect(el);
|
||||||
|
if (type === "year") {
|
||||||
|
idx = clamp(idx + direction, 0, years.value.length - 1);
|
||||||
|
localYear.value = years.value[idx];
|
||||||
|
} else if (type === "month") {
|
||||||
|
idx = clamp(idx + direction, 0, 11);
|
||||||
|
localMonth.value = idx + 1;
|
||||||
|
} else {
|
||||||
|
const dim = daysInMonth(localYear.value, localMonth.value);
|
||||||
|
idx = clamp(idx + direction, 0, dim - 1);
|
||||||
|
localDay.value = idx + 1;
|
||||||
|
}
|
||||||
|
isAnimating[type] = true;
|
||||||
|
isUserScrolling.value = true;
|
||||||
|
el.scrollTo({ top: idx * wheelItemHeight, behavior: "smooth" });
|
||||||
|
setTimeout(() => {
|
||||||
|
isAnimating[type] = false;
|
||||||
|
isUserScrolling.value = false;
|
||||||
|
}, 180);
|
||||||
|
}
|
||||||
|
function handleWheelScroll(type, e) {
|
||||||
|
clearTimeout(scrollTimers[type]);
|
||||||
|
isUserScrolling.value = true;
|
||||||
|
scrollTimers[type] = setTimeout(() => {
|
||||||
|
const el = e.target;
|
||||||
|
const idx = getCenteredIndexByRect(el);
|
||||||
|
if (type === "year") {
|
||||||
|
localYear.value = years.value[clamp(idx, 0, years.value.length - 1)];
|
||||||
|
} else if (type === "month") {
|
||||||
|
localMonth.value = clamp(idx + 1, 1, 12);
|
||||||
|
} else if (type === "day") {
|
||||||
|
const dim = daysInMonth(localYear.value, localMonth.value);
|
||||||
|
localDay.value = clamp(idx + 1, 1, dim);
|
||||||
|
}
|
||||||
|
isUserScrolling.value = false;
|
||||||
|
}, 120);
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirm() {
|
||||||
|
// 以滚轮当前“水平线”居中项为最终值(基于 DOM 位置,避免像素取整误差)
|
||||||
|
if (yearColRef.value) {
|
||||||
|
const idx = clamp(
|
||||||
|
getCenteredIndexByRect(yearColRef.value),
|
||||||
|
0,
|
||||||
|
years.value.length - 1
|
||||||
|
);
|
||||||
|
localYear.value = years.value[idx];
|
||||||
|
}
|
||||||
|
if (monthColRef.value) {
|
||||||
|
const idx = clamp(getCenteredIndexByRect(monthColRef.value) + 1, 1, 12);
|
||||||
|
localMonth.value = idx;
|
||||||
|
}
|
||||||
|
if (dayColRef.value) {
|
||||||
|
const dim = daysInMonth(localYear.value, localMonth.value);
|
||||||
|
const idx = clamp(getCenteredIndexByRect(dayColRef.value) + 1, 1, dim);
|
||||||
|
localDay.value = idx;
|
||||||
|
}
|
||||||
|
// 输出固定为本地日期,不跨时区
|
||||||
|
const payload = {
|
||||||
|
year: localYear.value,
|
||||||
|
month: localMonth.value,
|
||||||
|
day: localDay.value,
|
||||||
|
};
|
||||||
|
emit("update:modelValue", payload);
|
||||||
|
nextTick(() => emit("confirm", payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
nextTick(syncWheelPositions);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.picker-mask {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.picker-panel {
|
||||||
|
width: 311 * 5.12px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8 * 5.12px;
|
||||||
|
box-shadow: 0 3 * 5.12px 14 * 5.12px rgba(0, 0, 0, 0.16);
|
||||||
|
padding: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
.picker-title {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
color: #455363;
|
||||||
|
margin-bottom: 16 * 5.12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.picker-columns {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
column-gap: 32 * 5.12px;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-items: stretch;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.center-lines {
|
||||||
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
.center-lines .line {
|
||||||
|
position: absolute;
|
||||||
|
left: 16 * 5.12px; /* align with design padding */
|
||||||
|
right: 16 * 5.12px;
|
||||||
|
height: 1px; /* crisp hairline */
|
||||||
|
background: #ededed;
|
||||||
|
}
|
||||||
|
.center-lines .line:first-child {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.center-lines .line:last-child {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.picker-col {
|
||||||
|
position: relative;
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: 1; /* paint above guide lines */
|
||||||
|
scroll-snap-type: y mandatory;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
.picker-col::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
.picker-item {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
color: #9da3ad;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
scroll-snap-align: center;
|
||||||
|
scroll-snap-stop: always;
|
||||||
|
}
|
||||||
|
.year-col .picker-item {
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding-left: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
.month-col .picker-item {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.day-col .picker-item {
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-right: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
.picker-item.active {
|
||||||
|
color: #000;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.picker-actions {
|
||||||
|
margin-top: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
.picker-confirm {
|
||||||
|
width: 100%;
|
||||||
|
height: 44 * 5.12px;
|
||||||
|
background: #ff7bac;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because it is too large
Load Diff
@ -1,94 +1,184 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="historic-data-container" style="margin-bottom: 40px">
|
<div class="historic-data-container">
|
||||||
<div class="echarts-container">
|
<div class="echarts-container">
|
||||||
<customEcharts></customEcharts>
|
<customEcharts></customEcharts>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="header">
|
||||||
<div class="header mt-[80px]">
|
<!-- 标题区域 -->
|
||||||
<div class="title">Historical Data</div>
|
<div class="title-section">
|
||||||
<div class="filter-container">
|
<div class="title-decoration"></div>
|
||||||
<!-- <n-dropdown
|
<div class="title-text">Historical Data</div>
|
||||||
trigger="click"
|
|
||||||
:options="periodOptions"
|
|
||||||
@select="handlePeriodChange"
|
|
||||||
:value="state.selectedPeriod"
|
|
||||||
>
|
|
||||||
<n-button>
|
|
||||||
{{ state.selectedPeriod }}
|
|
||||||
<n-icon><chevron-down-outline /></n-icon>
|
|
||||||
</n-button>
|
|
||||||
</n-dropdown> -->
|
|
||||||
|
|
||||||
<n-dropdown
|
|
||||||
trigger="click"
|
|
||||||
:options="durationOptions"
|
|
||||||
@select="handleDurationChange"
|
|
||||||
:value="state.selectedDuration"
|
|
||||||
>
|
|
||||||
<n-button>
|
|
||||||
{{ state.selectedDuration }}
|
|
||||||
<n-icon><chevron-down-outline /></n-icon>
|
|
||||||
</n-button>
|
|
||||||
</n-dropdown>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<n-data-table
|
<div class="filter-container">
|
||||||
:columns="columns"
|
<span class="range-label">Range</span>
|
||||||
:data="paginatedData"
|
<div class="filter-row">
|
||||||
:bordered="false"
|
<div
|
||||||
:single-line="false"
|
v-for="option in durationOptions"
|
||||||
:scroll-x="600"
|
: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>
|
||||||
|
</div>
|
||||||
|
<!-- reports-table from annualreports -->
|
||||||
|
<div class="reports-table">
|
||||||
|
<div class="table-container">
|
||||||
|
<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 ? '0 0 ' + col.width + 'px' : '1 0 116px',
|
||||||
|
'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 ? '0 0 ' + col.width + 'px' : '1 0 116px',
|
||||||
|
'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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- pagination-container from annualreports -->
|
||||||
<div class="pagination-container">
|
<div class="pagination-container">
|
||||||
<n-button class="page-btn prev-btn" @click="handlePrevPage">
|
<div class="pagination-controls">
|
||||||
<n-icon><chevron-back-outline /></n-icon>
|
<div class="pagination-buttons">
|
||||||
</n-button>
|
<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>
|
||||||
|
|
||||||
<div class="page-info mr-[40px]">
|
<template v-for="page in getVisiblePages()" :key="page">
|
||||||
{{ state.currentPage }} of {{ totalPages }}
|
<button
|
||||||
</div>
|
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>
|
||||||
|
|
||||||
<div class="right-controls">
|
<button
|
||||||
<n-dropdown
|
class="page-btn next-btn"
|
||||||
trigger="click"
|
:disabled="state.currentPage === totalPages"
|
||||||
:options="pageSizeOptions"
|
@click="goToNextPage"
|
||||||
@select="handlePageSizeChange"
|
>
|
||||||
>
|
<svg width="5" height="9" viewBox="0 0 5 9" fill="none">
|
||||||
<n-button class="rows-dropdown">
|
<path
|
||||||
{{ state.pageSize }} Rows
|
d="M1 1L4 4.5L1 8"
|
||||||
<n-icon><chevron-down-outline /></n-icon>
|
stroke="#455363"
|
||||||
</n-button>
|
stroke-width="1.5"
|
||||||
</n-dropdown>
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
<n-button class="page-btn next-btn" @click="handleNextPage">
|
/>
|
||||||
<n-icon><chevron-forward-outline /></n-icon>
|
</svg>
|
||||||
</n-button>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pagination-info">
|
||||||
|
Displaying {{ displayRange.start }} - {{ displayRange.end }} of
|
||||||
|
{{ state.tableData.length }} results
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="back-to-top-link">
|
<!-- <div class="back-to-top-link">
|
||||||
<a href="#" @click.prevent="scrollToTop">
|
<a href="#" @click.prevent="scrollToTop">
|
||||||
Back to Top
|
Back to Top
|
||||||
<n-icon><arrow-up-outline /></n-icon>
|
<n-icon><arrow-up-outline /></n-icon>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { NDataTable, NButton, NDropdown, NIcon } from "naive-ui";
|
import { NDropdown, NIcon } from "naive-ui";
|
||||||
import { reactive, onMounted, h, computed } from "vue";
|
import { reactive, onMounted, h, computed, ref, watch, onUnmounted } from "vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {
|
import { ChevronDownOutline, ArrowUpOutline } from "@vicons/ionicons5";
|
||||||
ChevronDownOutline,
|
|
||||||
ChevronBackOutline,
|
|
||||||
ChevronForwardOutline,
|
|
||||||
ArrowUpOutline,
|
|
||||||
} from "@vicons/ionicons5";
|
|
||||||
import defaultTableData from "../data";
|
import defaultTableData from "../data";
|
||||||
// console.log('defaultTableData', defaultTableData)
|
|
||||||
import customEcharts from "@/components/customEcharts/index.vue";
|
import customEcharts from "@/components/customEcharts/index.vue";
|
||||||
|
|
||||||
// 数据筛选选项
|
// 数据筛选选项
|
||||||
@ -103,15 +193,15 @@ const periodOptions = [
|
|||||||
const durationOptions = [
|
const durationOptions = [
|
||||||
{ label: "3 Months", key: "3 Months" },
|
{ label: "3 Months", key: "3 Months" },
|
||||||
{ label: "6 Months", key: "6 Months" },
|
{ label: "6 Months", key: "6 Months" },
|
||||||
{ label: "Year to Date", key: "Year to Date" },
|
{ label: "YTD", key: "Year to Date" },
|
||||||
{ label: "1 Year", key: "1 Year" },
|
{ label: "1 Year", key: "1 Year" },
|
||||||
{ label: "5 Years", key: "5 Years" },
|
{ label: "5 Years", key: "5 Years" },
|
||||||
{ label: "10 Years", key: "10 Years" },
|
{ label: "10 Years", key: "10 Years" },
|
||||||
// { label: 'Full History', key: 'Full History', disabled: true },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 分页大小选项
|
// 分页大小选项
|
||||||
const pageSizeOptions = [
|
const pageSizeOptions = [
|
||||||
|
{ label: "10", key: 10 },
|
||||||
{ label: "50", key: 50 },
|
{ label: "50", key: 50 },
|
||||||
{ label: "100", key: 100 },
|
{ label: "100", key: 100 },
|
||||||
{ label: "500", key: 500 },
|
{ label: "500", key: 500 },
|
||||||
@ -123,9 +213,12 @@ const state = reactive({
|
|||||||
selectedDuration: "6 Months",
|
selectedDuration: "6 Months",
|
||||||
tableData: [],
|
tableData: [],
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 50,
|
pageSize: 10,
|
||||||
|
gotoPage: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showPageSizeMenu = ref(false);
|
||||||
|
|
||||||
// 计算总页数
|
// 计算总页数
|
||||||
const totalPages = computed(() => {
|
const totalPages = computed(() => {
|
||||||
return Math.ceil(state.tableData.length / state.pageSize);
|
return Math.ceil(state.tableData.length / state.pageSize);
|
||||||
@ -145,47 +238,49 @@ const columns = [
|
|||||||
key: "date",
|
key: "date",
|
||||||
align: "left",
|
align: "left",
|
||||||
fixed: "left",
|
fixed: "left",
|
||||||
width: 150,
|
width: 152,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Open",
|
title: "Open",
|
||||||
key: "open",
|
key: "open",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
width: 116,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "High",
|
title: "High",
|
||||||
key: "high",
|
key: "high",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
width: 116,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Low",
|
title: "Low",
|
||||||
key: "low",
|
key: "low",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
width: 116,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Close",
|
title: "Close",
|
||||||
key: "close",
|
key: "close",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
width: 116,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Adj. Close",
|
title: "Adj. Close",
|
||||||
key: "adjClose",
|
key: "adjClose",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
width: 116,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Change",
|
title: "Change",
|
||||||
key: "change",
|
key: "change",
|
||||||
align: "center",
|
align: "center",
|
||||||
render(row) {
|
width: 116,
|
||||||
const value = parseFloat(row.change);
|
|
||||||
const color = value < 0 ? "#ff4d4f" : value > 0 ? "#52c41a" : "";
|
|
||||||
return h("span", { style: { color } }, row.change);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Volume",
|
title: "Volume",
|
||||||
key: "volume",
|
key: "volume",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
width: 116,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -213,26 +308,62 @@ const handleDurationChange = (key) => {
|
|||||||
getPageData();
|
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 handlePrevPage = () => {
|
|
||||||
if (state.currentPage === 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state.currentPage--;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleNextPage = () => {
|
|
||||||
if (state.currentPage >= totalPages.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state.currentPage++;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePageSizeChange = (size) => {
|
const handlePageSizeChange = (size) => {
|
||||||
state.pageSize = size;
|
state.pageSize = size;
|
||||||
state.currentPage = 1; // 重置到第一页
|
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 total = totalPages.value;
|
||||||
|
if (total <= 4) {
|
||||||
|
const pages = [];
|
||||||
|
for (let i = 1; i <= total; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
}
|
||||||
|
return [1, 2, "...", total];
|
||||||
|
};
|
||||||
|
|
||||||
// 回到顶部
|
// 回到顶部
|
||||||
const scrollToTop = () => {
|
const scrollToTop = () => {
|
||||||
// 尝试多种方法
|
// 尝试多种方法
|
||||||
@ -248,8 +379,32 @@ const scrollToTop = () => {
|
|||||||
};
|
};
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getPageData();
|
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 () => {
|
const getPageDefaultData = async () => {
|
||||||
try {
|
try {
|
||||||
let url =
|
let url =
|
||||||
@ -341,24 +496,25 @@ const getPageData = async () => {
|
|||||||
String(fromDate.getMonth() + 1).padStart(2, "0") +
|
String(fromDate.getMonth() + 1).padStart(2, "0") +
|
||||||
"-" +
|
"-" +
|
||||||
String(fromDate.getDate()).padStart(2, "0");
|
String(fromDate.getDate()).padStart(2, "0");
|
||||||
// let url = `https://stockanalysis.com/api/symbol/a/OTC-MINM/history?period=${state.selectedPeriod}&range=${range}`
|
|
||||||
let url =
|
let url =
|
||||||
"https://common.szjixun.cn/api/stock/history/list?from=" +
|
"https://common.szjixun.cn/api/stock/history/list?from=" +
|
||||||
finalFromDate +
|
finalFromDate +
|
||||||
"&to=" +
|
"&to=" +
|
||||||
toDate;
|
toDate;
|
||||||
const res = await axios.get(url);
|
const res = await axios.get(url);
|
||||||
// console.error(res)
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
if (res.data.status === 0) {
|
if (res.data.status === 0) {
|
||||||
// 转换为日期格式:"Nov 26, 2024"
|
// 转换为日期格式:"Nov 26, 2024"
|
||||||
let resultData = res.data.data.map((item) => {
|
let resultData = res.data.data.map((item) => {
|
||||||
return {
|
return {
|
||||||
date: new Date(item.date).toLocaleDateString("en-US", {
|
date: new Date(item.date.replace(/-/g, "/")).toLocaleDateString(
|
||||||
month: "short",
|
"en-US",
|
||||||
day: "numeric",
|
{
|
||||||
year: "numeric",
|
month: "short",
|
||||||
}),
|
day: "numeric",
|
||||||
|
year: "numeric",
|
||||||
|
}
|
||||||
|
),
|
||||||
open: item.open != null ? Number(item.open).toFixed(2) : "",
|
open: item.open != null ? Number(item.open).toFixed(2) : "",
|
||||||
high: item.high != null ? Number(item.high).toFixed(2) : "",
|
high: item.high != null ? Number(item.high).toFixed(2) : "",
|
||||||
low: item.low != null ? Number(item.low).toFixed(2) : "",
|
low: item.low != null ? Number(item.low).toFixed(2) : "",
|
||||||
@ -379,82 +535,83 @@ const getPageData = async () => {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.historic-data-container {
|
.historic-data-container {
|
||||||
padding: 80px;
|
width: 343 * 5.12px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 80px;
|
font-size: 40 * 2.5 * 5.12px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-container {
|
|
||||||
display: flex;
|
|
||||||
gap: 40px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-container {
|
.filter-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
margin-top: 60px;
|
gap: 8 * 5.12px;
|
||||||
padding: 10px 16px;
|
padding: 0 16 * 5.12px;
|
||||||
border-radius: 4px;
|
margin-bottom: 32 * 5.12px;
|
||||||
background-color: #ffffff;
|
|
||||||
|
|
||||||
.page-btn {
|
.range-label {
|
||||||
display: flex;
|
font-family: "PingFang SC", sans-serif;
|
||||||
align-items: center;
|
font-weight: 400;
|
||||||
gap: 5px;
|
font-size: 14 * 5.12px;
|
||||||
padding: 6px 12px;
|
line-height: 1.4;
|
||||||
font-size: 92px;
|
letter-spacing: 0.48 * 5.12px;
|
||||||
|
color: #455363;
|
||||||
&.prev-btn {
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.next-btn {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
opacity: 0.5;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-info {
|
.filter-row {
|
||||||
font-size: 72px;
|
width: 311 * 5.12px;
|
||||||
color: #374151;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
column-gap: 16 * 5.12px;
|
||||||
|
row-gap: 8 * 5.12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-controls {
|
.filter-option {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 34 * 5.12px;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
background-color: #efefef;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #000000;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
width: 93 * 5.12px;
|
||||||
|
|
||||||
.rows-dropdown {
|
&:hover {
|
||||||
font-size: 72px;
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #ff7bac;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-top-link {
|
.back-to-top-link {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 56px;
|
margin-top: 16 * 5.12px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 5px;
|
gap: 5 * 5.12px;
|
||||||
color: #2563eb;
|
color: #2563eb;
|
||||||
font-size: 92px;
|
font-size: 20 * 5.12px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
@ -463,11 +620,300 @@ const getPageData = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.n-data-table) {
|
.reports-table {
|
||||||
.n-data-table-td {
|
width: 100%;
|
||||||
padding: 12px 8px;
|
background: #ffffff;
|
||||||
}
|
border-radius: 16 * 5.12px;
|
||||||
|
box-shadow: 0 * 5.12px 3 * 5.12px 14 * 5.12px 0 * 5.12px rgba(0, 0, 0, 0.16);
|
||||||
|
padding: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container::-webkit-scrollbar {
|
||||||
|
height: 8 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1;
|
||||||
|
border-radius: 4 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container::-webkit-scrollbar-thumb {
|
||||||
|
background: #ccc;
|
||||||
|
border-radius: 4 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #fff0f5;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.column {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0.48 * 5.12px;
|
||||||
|
color: #455363;
|
||||||
|
padding: 16 * 5.12px;
|
||||||
|
position: relative;
|
||||||
|
font-variant-numeric: tabular-nums; /* 让数字等宽对齐 */
|
||||||
|
}
|
||||||
|
.table-header {
|
||||||
|
display: flex;
|
||||||
|
border-radius: 8 * 5.12px;
|
||||||
|
margin-bottom: 4 * 5.12px;
|
||||||
|
align-items: center;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.column {
|
||||||
|
background: #fff0f5;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0.48 * 5.12px;
|
||||||
|
color: #000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 8 * 5.12px;
|
||||||
|
&:hover .column {
|
||||||
|
background: #fff8fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// &:last-child {
|
||||||
|
// border-bottom: none;
|
||||||
|
// }
|
||||||
|
|
||||||
|
&:nth-child(even) {
|
||||||
|
margin: 4 * 5.12px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.reports-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row .column:not(:last-child)::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
height: 40 * 5.12px;
|
||||||
|
border-right: 1 * 5.12px dashed #e0e0e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-header .column:first-child {
|
||||||
|
border-radius: 8 * 5.12px 0 0 8 * 5.12px;
|
||||||
|
}
|
||||||
|
.table-header .column:last-child,
|
||||||
|
.table-row .column:last-child {
|
||||||
|
border-radius: 0 8 * 5.12px 8 * 5.12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row .column:first-child {
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row:hover .column:first-child {
|
||||||
|
background: #fff8fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页器样式
|
||||||
|
.pagination-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 16 * 5.12px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 0 4 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-info {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #455363;
|
||||||
|
text-align: right;
|
||||||
|
margin-top: 16 * 5.12px;
|
||||||
|
margin-bottom: 16 * 5.12px;
|
||||||
|
padding: 0 4 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8 * 5.12px;
|
||||||
|
}
|
||||||
|
.page-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 28 * 5.12px;
|
||||||
|
height: 28 * 5.12px;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
background: #ffffff;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
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: 18 * 5.12px;
|
||||||
|
padding: 4 * 5.12px 12 * 5.12px;
|
||||||
|
height: 28 * 5.12px;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
background: #ffffff;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #455363;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #ff7bac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-size-menu {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
box-shadow: 0 2 * 5.12px 8 * 5.12px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 1000;
|
||||||
|
margin-bottom: 5 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-size-option {
|
||||||
|
padding: 8 * 5.12px 12 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
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: 8 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #455363;
|
||||||
|
margin-right: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goto-input {
|
||||||
|
width: 60 * 5.12px;
|
||||||
|
height: 28 * 5.12px;
|
||||||
|
padding: 4 * 5.12px 12 * 5.12px;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #455363;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #ff7bac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16 * 5.12px;
|
||||||
|
margin-bottom: 32 * 5.12px;
|
||||||
|
margin-top: 43 * 5.12px;
|
||||||
|
padding: 0 16 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-decoration {
|
||||||
|
width: 58 * 5.12px;
|
||||||
|
height: 7 * 5.12px;
|
||||||
|
background: #ff7bac;
|
||||||
|
margin: auto 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 24 * 5.12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,59 +1,80 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="press-releases-page">
|
<div class="press-releases-page">
|
||||||
<n-infinite-scroll :distance="0" @load="doLoadMore">
|
<div class="title-section">
|
||||||
<main class="p-[80px] mx-auto" style="max-width: 100vw; min-width: 285px">
|
<div class="title-decoration"></div>
|
||||||
<div class="title mb-[24px]">
|
<div class="title">
|
||||||
{{ t("press_releases.title") }}
|
{{ t("press_releases.title") }}
|
||||||
</div>
|
</div>
|
||||||
<div class="search-container">
|
</div>
|
||||||
<n-select
|
<div class="search-container">
|
||||||
:options="state.selectOptions"
|
<n-select
|
||||||
v-model:value="state.selectedValue"
|
:options="state.selectOptions"
|
||||||
class="search-select"
|
v-model:value="state.selectedValue"
|
||||||
:font-size="72"
|
class="search-select"
|
||||||
/>
|
/>
|
||||||
<n-input
|
<input
|
||||||
v-model:value="state.inputValue"
|
v-model="state.inputValue"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="t('press_releases.search.placeholder')"
|
:placeholder="t('press_releases.search.placeholder')"
|
||||||
class="search-input"
|
class="search-input"
|
||||||
clearable
|
/>
|
||||||
:font-size="72"
|
<button @click="handleSearch" class="search-button">
|
||||||
/>
|
{{ t("press_releases.search.button") }}
|
||||||
<n-button @click="handleSearch" class="search-button" :font-size="72">
|
</button>
|
||||||
{{ t("press_releases.search.button") }}
|
</div>
|
||||||
</n-button>
|
<div class="reports-list">
|
||||||
</div>
|
<div
|
||||||
<div v-for="(item, idx) in state.filterNewsData" :key="idx">
|
v-for="(item, idx) in state.filterNewsData"
|
||||||
<div class="news-item mt-[10px]">
|
:key="idx"
|
||||||
<div class="news-item-date">{{ item.date }}</div>
|
class="news-item table-row"
|
||||||
<div
|
>
|
||||||
class="news-item-title text-[#0078d7] cursor-pointer"
|
<div class="content">
|
||||||
style="
|
<div class="file-content">
|
||||||
word-break: break-word;
|
<div class="file-info">
|
||||||
display: -webkit-box;
|
<div class="vertical-line"></div>
|
||||||
-webkit-line-clamp: 2;
|
<div
|
||||||
-webkit-box-orient: vertical;
|
class="news-item-title text-[#000] cursor-pointer"
|
||||||
overflow: hidden;
|
style="
|
||||||
text-overflow: ellipsis;
|
word-break: break-all;
|
||||||
"
|
display: -webkit-box;
|
||||||
@click="handleNewClick(item)"
|
-webkit-line-clamp: 1;
|
||||||
>
|
line-clamp: 1;
|
||||||
{{ item.title }}
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
"
|
||||||
|
@click="handleNewClick(item)"
|
||||||
|
>
|
||||||
|
{{ item.title }}
|
||||||
|
</div>
|
||||||
|
<svg
|
||||||
|
class="arrow-icon"
|
||||||
|
width="7"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 7 14"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
@click="handleNewClick(item)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M1 1L6 7L1 13"
|
||||||
|
stroke="#FF7BAC"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<n-tooltip
|
<n-tooltip trigger="hover" :disabled="true" width="trigger">
|
||||||
trigger="click"
|
|
||||||
:disabled="!item.showTooltip"
|
|
||||||
width="trigger"
|
|
||||||
>
|
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<div
|
<div
|
||||||
:ref="(el) => setTitleRef(el, idx)"
|
:ref="(el) => setTitleRef(el, idx)"
|
||||||
class="news-item-content"
|
class="news-item-content file-description"
|
||||||
style="
|
style="
|
||||||
word-break: break-word;
|
word-break: break-all;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@ -66,17 +87,118 @@
|
|||||||
{{ item.summary }}
|
{{ item.summary }}
|
||||||
</div>
|
</div>
|
||||||
</n-tooltip>
|
</n-tooltip>
|
||||||
|
<div class="download-section">
|
||||||
|
<div class="news-item-date">{{ item.date }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
<div class="separator-line"></div>
|
||||||
</n-infinite-scroll>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分页器 -->
|
||||||
|
<div class="pagination-container" v-if="state.total > 0">
|
||||||
|
<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 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, 20, 50]"
|
||||||
|
:key="size"
|
||||||
|
class="page-size-option"
|
||||||
|
:class="{ active: state.pageSize === size }"
|
||||||
|
@click="changePageSize(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="pagination-info" v-if="state.total > 0">
|
||||||
|
Displaying {{ displayRange.start }} - {{ displayRange.end }} of
|
||||||
|
{{ state.total }} results
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import customDefaultPage from "@/components/customDefaultPage/index.vue";
|
import customDefaultPage from "@/components/customDefaultPage/index.vue";
|
||||||
import { reactive, onMounted, watch, nextTick, ref } from "vue";
|
import {
|
||||||
import { NSelect, NInput, NButton, NInfiniteScroll, NTooltip } from "naive-ui";
|
reactive,
|
||||||
|
onMounted,
|
||||||
|
watch,
|
||||||
|
nextTick,
|
||||||
|
ref,
|
||||||
|
computed,
|
||||||
|
onUnmounted,
|
||||||
|
} from "vue";
|
||||||
|
import { NSelect, NInput, NButton, NTooltip } from "naive-ui";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
@ -97,32 +219,16 @@ const state = reactive({
|
|||||||
}),
|
}),
|
||||||
], //下拉选项
|
], //下拉选项
|
||||||
inputValue: "", //输入值
|
inputValue: "", //输入值
|
||||||
newsData: [
|
|
||||||
{
|
|
||||||
date: "June 3, 2025",
|
|
||||||
title: "FiEE, Inc. seized market opportunities through 2025 Osaka Expo",
|
|
||||||
content:
|
|
||||||
"Hong Kong, 3 June 2025 — FiEE, Inc. (NASDAQ:FIEE) (“FiEE, Inc.” or the “Company”), a technology company integrating IoT, connectivity and AI to redefine brand management solutions in the digital era, is pleased to announce significant business updates....",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
date: "June 2, 2025",
|
|
||||||
title: "FiEE, Inc. Closes Its First Day of Trading on NASDAQ",
|
|
||||||
content:
|
|
||||||
"Hong Kong, 2 June 2025 — FiEE, Inc. (NASDAQ:FIEE) (“FiEE, Inc.” or the “Company”), a technology company integrating IoT, connectivity and AI to redefine brand management solutions in the digital era, commenced...",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
date: "May 30, 2025",
|
|
||||||
title: "FiEE, Inc. Announces Reinitiation of Trading on Nasdaq",
|
|
||||||
content:
|
|
||||||
"Hong Kong, May 30, 2025 — FiEE, Inc. (“FiEE, Inc.” or the “Company”), a technology company integrating IoT, connectivity and AI to redefine brand management solutions...",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
filterNewsData: [],
|
filterNewsData: [],
|
||||||
loading: false, //是否正在加载数据
|
loading: false, //是否正在加载数据
|
||||||
hasMore: true, //是否还有更多数据
|
|
||||||
currentPage: 1, //当前页码
|
currentPage: 1, //当前页码
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
gotoPage: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showPageSizeMenu = ref(false);
|
||||||
|
|
||||||
const titleRefs = ref([]);
|
const titleRefs = ref([]);
|
||||||
|
|
||||||
const setTitleRef = (el, idx) => {
|
const setTitleRef = (el, idx) => {
|
||||||
@ -142,14 +248,18 @@ const checkAllTitleOverflow = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// state.filterNewsData = state.newsData;
|
|
||||||
getPressReleasesDisplay();
|
getPressReleasesDisplay();
|
||||||
|
document.addEventListener("click", handleClickOutside);
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
checkAllTitleOverflow();
|
checkAllTitleOverflow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener("click", handleClickOutside);
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => state.filterNewsData,
|
() => state.filterNewsData,
|
||||||
() => {
|
() => {
|
||||||
@ -162,93 +272,68 @@ watch(
|
|||||||
|
|
||||||
// 获取新闻列表
|
// 获取新闻列表
|
||||||
const getPressReleasesDisplay = () => {
|
const getPressReleasesDisplay = () => {
|
||||||
|
state.loading = true;
|
||||||
let url = "https://erpapi.fiee.com/api/fiee/pressreleases/display";
|
let url = "https://erpapi.fiee.com/api/fiee/pressreleases/display";
|
||||||
let params = {
|
let params = {
|
||||||
query: state.inputValue,
|
query: state.inputValue,
|
||||||
page: state.currentPage,
|
page: state.currentPage,
|
||||||
pageSize: 10,
|
pageSize: state.pageSize,
|
||||||
timeStart: state.selectedValue
|
timeStart: state.selectedValue
|
||||||
? state.selectedValue === "all_years"
|
? state.selectedValue === "all_years"
|
||||||
? null
|
? null
|
||||||
: new Date(state.selectedValue).getTime()
|
: new Date(state.selectedValue).getTime()
|
||||||
: null,
|
: null,
|
||||||
};
|
};
|
||||||
// console.log(params)
|
axios
|
||||||
axios.post(url, params).then((res) => {
|
.post(url, params)
|
||||||
// console.log(res)
|
.then((res) => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
if (res.data.status === 0) {
|
if (res.data.status === 0) {
|
||||||
res.data.data?.data?.forEach((item) => {
|
res.data.data?.data?.forEach((item) => {
|
||||||
item.date = new Date(item.createdAt).toLocaleDateString("en-US", {
|
item.date = new Date(item.createdAt).toLocaleDateString("en-US", {
|
||||||
month: "short",
|
month: "short",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
if (state.currentPage === 1) {
|
|
||||||
state.filterNewsData = res.data.data?.data || [];
|
state.filterNewsData = res.data.data?.data || [];
|
||||||
} else {
|
state.total = res.data.data?.total || 0;
|
||||||
state.filterNewsData = [
|
|
||||||
...state.filterNewsData,
|
|
||||||
...(res.data.data?.data || []),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (state.filterNewsData.length < (res.data.data?.total || 0)) {
|
|
||||||
state.hasMore = true;
|
|
||||||
} else {
|
|
||||||
state.hasMore = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
});
|
.finally(() => {
|
||||||
};
|
state.loading = false;
|
||||||
|
|
||||||
const handleFilter = () => {
|
|
||||||
// 筛选逻辑
|
|
||||||
let filteredData = [...state.newsData];
|
|
||||||
|
|
||||||
// 按年份筛选
|
|
||||||
if (state.selectedValue !== "all_years") {
|
|
||||||
filteredData = filteredData.filter((item) => {
|
|
||||||
// 从日期字符串中提取年份,假设日期格式为 "May 30, 2025"
|
|
||||||
const dateMatch = item.date.match(/\b\d{4}\b/);
|
|
||||||
if (dateMatch) {
|
|
||||||
const year = dateMatch[0];
|
|
||||||
return year === state.selectedValue;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// 按输入内容进行模糊查询(title 和 content)
|
|
||||||
if (state.inputValue && state.inputValue.trim() !== "") {
|
|
||||||
const searchText = state.inputValue.toLowerCase().trim();
|
|
||||||
filteredData = filteredData.filter((item) => {
|
|
||||||
const titleMatch = item.title.toLowerCase().includes(searchText);
|
|
||||||
const contentMatch = item.content.toLowerCase().includes(searchText);
|
|
||||||
return titleMatch || contentMatch;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
state.filterNewsData = filteredData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加 watcher 来实现自动筛选
|
// 添加 watcher 来实现自动筛选
|
||||||
watch(
|
watch(
|
||||||
() => [state.selectedValue, state.inputValue],
|
() => [state.selectedValue, state.inputValue],
|
||||||
() => {
|
() => {
|
||||||
// handleFilter();
|
|
||||||
state.currentPage = 1;
|
state.currentPage = 1;
|
||||||
getPressReleasesDisplay();
|
getPressReleasesDisplay();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => state.pageSize,
|
||||||
|
() => {
|
||||||
|
state.currentPage = 1;
|
||||||
|
getPressReleasesDisplay();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => state.currentPage,
|
||||||
|
(newPage) => {
|
||||||
|
state.gotoPage = newPage;
|
||||||
|
getPressReleasesDisplay();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
// 手动触发筛选(保留这个函数以保持兼容性)
|
|
||||||
// handleFilter();
|
|
||||||
state.currentPage = 1;
|
state.currentPage = 1;
|
||||||
getPressReleasesDisplay();
|
getPressReleasesDisplay();
|
||||||
// console.log("筛选结果:", state.filterNewsData);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNewClick = (item) => {
|
const handleNewClick = (item) => {
|
||||||
@ -260,102 +345,468 @@ const handleNewClick = (item) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
//加载更多数据
|
const totalPages = computed(() => {
|
||||||
const doLoadMore = () => {
|
return Math.ceil(state.total / state.pageSize) || 1;
|
||||||
if (!state.hasMore || state.loading) {
|
});
|
||||||
return;
|
|
||||||
|
const displayRange = computed(() => {
|
||||||
|
if (state.total === 0) return { start: 0, end: 0 };
|
||||||
|
const start = (state.currentPage - 1) * state.pageSize + 1;
|
||||||
|
const end = Math.min(state.currentPage * state.pageSize, state.total);
|
||||||
|
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 changePageSize = (size) => {
|
||||||
|
state.pageSize = size;
|
||||||
|
};
|
||||||
|
|
||||||
|
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) {
|
||||||
|
for (let i = 1; i <= total; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pages.push(1);
|
||||||
|
|
||||||
|
if (current <= 4) {
|
||||||
|
for (let i = 2; i <= 5; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
pages.push("...");
|
||||||
|
pages.push(total);
|
||||||
|
} else if (current >= total - 3) {
|
||||||
|
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 handleClickOutside = (event) => {
|
||||||
|
if (!event.target.closest || !event.target.closest(".page-size-selector")) {
|
||||||
|
showPageSizeMenu.value = false;
|
||||||
}
|
}
|
||||||
// console.log('触底了')
|
|
||||||
state.loading = true;
|
|
||||||
state.currentPage++;
|
|
||||||
getPressReleasesDisplay().finally(() => {
|
|
||||||
state.loading = false;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.press-releases-page {
|
||||||
|
width: 343 * 5.12px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.title-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16 * 5.12px;
|
||||||
|
padding: 0 16 * 5.12px;
|
||||||
|
}
|
||||||
|
.title-decoration {
|
||||||
|
width: 58 * 5.12px;
|
||||||
|
height: 7 * 5.12px;
|
||||||
|
background: #ff7bac;
|
||||||
|
margin-top: 43 * 5.12px;
|
||||||
|
}
|
||||||
.title {
|
.title {
|
||||||
font-size: 113px;
|
font-size: 32 * 5.12px;
|
||||||
font-weight: bold;
|
color: #000;
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-container {
|
.search-container {
|
||||||
margin-bottom: 24px;
|
margin-top: 32 * 5.12px;
|
||||||
|
margin-bottom: 20 * 5.12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #f6f7f9;
|
justify-content: flex-start;
|
||||||
border-radius: 8px;
|
gap: 16 * 5.12px;
|
||||||
padding: 8px;
|
padding: 0 16 * 5.12px;
|
||||||
gap: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-select {
|
.search-select {
|
||||||
width: 1000px;
|
width: 100%;
|
||||||
:deep(.n-base-selection) {
|
height: 34 * 5.12px;
|
||||||
padding: 4px 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-input {
|
.search-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 34 * 5.12px;
|
||||||
|
padding: 7 * 5.12px 12 * 5.12px;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.375em;
|
||||||
|
letter-spacing: 0.48 * 5.12px;
|
||||||
|
color: #455363;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: #b6b6b6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.n-input) {
|
:deep(.n-input) {
|
||||||
.n-input__input {
|
.n-input__input {
|
||||||
padding: 4px 0;
|
padding: 4 * 5.12px 0;
|
||||||
border-radius: 4px;
|
// border: 1*5.12px solid #ccc;
|
||||||
|
border-radius: 4 * 5.12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.n-select) {
|
:deep(.n-select) {
|
||||||
.n-select__input {
|
.n-select__input {
|
||||||
padding: 8px 12px;
|
padding: 8 * 5.12px 12 * 5.12px;
|
||||||
border: 1px solid #ccc;
|
border: 1 * 5.12px solid #ccc;
|
||||||
border-radius: 4px;
|
border-radius: 4 * 5.12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.n-button) {
|
:deep(.n-button) {
|
||||||
width: 260px;
|
padding: 20 * 5.12px 16 * 5.12px;
|
||||||
padding: 20px 16px;
|
border-radius: 4 * 5.12px;
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.news-item {
|
|
||||||
padding: 16px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.news-item-date {
|
|
||||||
font-size: 72px;
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.news-item-title {
|
|
||||||
font-size: 92px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.news-item-content {
|
|
||||||
font-size: 72px;
|
|
||||||
color: #333;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
}
|
||||||
.search-button {
|
.search-button {
|
||||||
|
width: 100%;
|
||||||
|
height: 34 * 5.12px;
|
||||||
|
padding: 7 * 5.12px 12 * 5.12px;
|
||||||
background: #ff7bac;
|
background: #ff7bac;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.375em;
|
||||||
|
letter-spacing: 0.48 * 5.12px;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #ff7bac;
|
background: #ff7bac;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reports-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4 * 5.12px;
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 16 * 5.12px;
|
||||||
|
margin-top: 40 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 8 * 5.12px;
|
||||||
|
|
||||||
|
// &:last-child {
|
||||||
|
// .separator-line {
|
||||||
|
// display: none;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row .content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0;
|
||||||
|
&:hover {
|
||||||
|
background: #fff8fb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16 * 5.12px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-item-title {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.375em;
|
||||||
|
letter-spacing: 0.48 * 5.12px;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow-icon {
|
||||||
|
margin-left: auto;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical-line {
|
||||||
|
width: 1 * 5.12px;
|
||||||
|
height: 20 * 5.12px;
|
||||||
|
background: #ff7bac;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-description {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.375em;
|
||||||
|
letter-spacing: 0.48 * 5.12px;
|
||||||
|
color: #455363;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin-top: 8 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-item-date {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.375em;
|
||||||
|
letter-spacing: 0.48 * 5.12px;
|
||||||
|
color: #455363;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
padding: 4 * 5.12px 0 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator-line {
|
||||||
|
width: 100%;
|
||||||
|
height: 1 * 5.12px;
|
||||||
|
background: repeating-linear-gradient(
|
||||||
|
to right,
|
||||||
|
#e6eaee 0 * 5.12px,
|
||||||
|
#e6eaee 2 * 5.12px,
|
||||||
|
transparent 2 * 5.12px,
|
||||||
|
transparent 4 * 5.12px
|
||||||
|
);
|
||||||
|
margin-top: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页器样式
|
||||||
|
.pagination-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 40 * 5.12px 0;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 0 16 * 5.12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-info {
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.4375em;
|
||||||
|
color: #455363;
|
||||||
|
text-align: right;
|
||||||
|
margin-bottom: 30 * 5.12px;
|
||||||
|
padding: 0 16 * 5.12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8 * 5.12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8 * 5.12px;
|
||||||
|
}
|
||||||
|
.page-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 28 * 5.12px;
|
||||||
|
height: 28 * 5.12px;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
background: #ffffff;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
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: 18 * 5.12px;
|
||||||
|
padding: 4 * 5.12px 12 * 5.12px;
|
||||||
|
height: 28 * 5.12px;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
background: #ffffff;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
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: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
box-shadow: 0 2 * 5.12px 8 * 5.12px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 1000;
|
||||||
|
margin-bottom: 2 * 5.12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-size-option {
|
||||||
|
padding: 8 * 5.12px 12 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
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: 8 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.428em;
|
||||||
|
color: #455363;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goto-input {
|
||||||
|
width: 60 * 5.12px;
|
||||||
|
height: 28 * 5.12px;
|
||||||
|
padding: 4 * 5.12px 12 * 5.12px;
|
||||||
|
border: 1 * 5.12px solid #e0e0e6;
|
||||||
|
border-radius: 3 * 5.12px;
|
||||||
|
font-family: "PingFang SC", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14 * 5.12px;
|
||||||
|
line-height: 1.428em;
|
||||||
|
color: #455363;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #ff7bac;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user