优化首页,增加专区
This commit is contained in:
@@ -68,6 +68,7 @@ const filters = reactive({
|
||||
maxFireLevel: undefined as number | undefined,
|
||||
});
|
||||
const sortBy = ref("recommended");
|
||||
const activeZone = ref("all");
|
||||
|
||||
const coinRangeOptions = [
|
||||
{ label: "全部区间", min: undefined, max: undefined },
|
||||
@@ -128,6 +129,8 @@ const skinChipLabel = computed(() => {
|
||||
const visibleListings = computed(() => {
|
||||
const keyword = filters.keyword.trim().toLowerCase();
|
||||
const filtered = listings.value.filter((item) => {
|
||||
if (!matchesZone(item, activeZone.value)) return false;
|
||||
|
||||
const text = [
|
||||
item.title,
|
||||
item.description,
|
||||
@@ -206,6 +209,45 @@ const statCards = computed(() => [
|
||||
},
|
||||
]);
|
||||
|
||||
const zoneOptions = computed(() => [
|
||||
{
|
||||
key: "all",
|
||||
label: "全部专区",
|
||||
hint: "当前可租账号",
|
||||
count: listings.value.length,
|
||||
},
|
||||
{
|
||||
key: "sale",
|
||||
label: "特惠专区",
|
||||
hint: "价格更划算",
|
||||
count: listings.value.filter((item) => matchesZone(item, "sale")).length,
|
||||
},
|
||||
{
|
||||
key: "gift",
|
||||
label: "赠送专区",
|
||||
hint: "含赠送物品",
|
||||
count: listings.value.filter((item) => matchesZone(item, "gift")).length,
|
||||
},
|
||||
{
|
||||
key: "night",
|
||||
label: "夜间专区",
|
||||
hint: "夜间也好上号",
|
||||
count: listings.value.filter((item) => matchesZone(item, "night")).length,
|
||||
},
|
||||
{
|
||||
key: "password",
|
||||
label: "账密专区",
|
||||
hint: "交接更快",
|
||||
count: listings.value.filter((item) => matchesZone(item, "password")).length,
|
||||
},
|
||||
{
|
||||
key: "highCoin",
|
||||
label: "高币专区",
|
||||
hint: "100M 以上",
|
||||
count: listings.value.filter((item) => matchesZone(item, "highCoin")).length,
|
||||
},
|
||||
]);
|
||||
|
||||
onMounted(loadHome);
|
||||
|
||||
async function loadHome() {
|
||||
@@ -249,9 +291,14 @@ function resetFilters() {
|
||||
filters.maxTotal = undefined;
|
||||
filters.minFireLevel = undefined;
|
||||
filters.maxFireLevel = undefined;
|
||||
activeZone.value = "all";
|
||||
sortBy.value = "recommended";
|
||||
}
|
||||
|
||||
function setActiveZone(zoneKey: string) {
|
||||
activeZone.value = zoneKey;
|
||||
}
|
||||
|
||||
function uniqueOptions(values: string[]) {
|
||||
return [...new Set(values.map((item) => item.trim()).filter(Boolean))];
|
||||
}
|
||||
@@ -306,6 +353,40 @@ function resetSkinFilter() {
|
||||
filters.skinGroup = "";
|
||||
filters.skinName = "";
|
||||
}
|
||||
|
||||
function matchesZone(item: Listing, zoneKey: string) {
|
||||
if (zoneKey === "all") return true;
|
||||
if (zoneKey === "sale") return hasAcceleratedSaleRatio(item);
|
||||
if (zoneKey === "gift") return hasGiftResources(item);
|
||||
if (zoneKey === "night") return isNightAvailable(item);
|
||||
if (zoneKey === "password") return /账密|账号密码/.test(getLoginMethod(item));
|
||||
if (zoneKey === "highCoin") return getCoinM(item) >= 100;
|
||||
return true;
|
||||
}
|
||||
|
||||
function isNightAvailable(item: Listing) {
|
||||
const onlineTime = item.asset_summary?.online_time;
|
||||
if (typeof onlineTime !== "object" || onlineTime === null) return false;
|
||||
const row = onlineTime as Record<string, unknown>;
|
||||
const start = parseTimeHour(row.start);
|
||||
const end = parseTimeHour(row.end);
|
||||
if (start === undefined || end === undefined) return false;
|
||||
return timeRangeCoversHour(start, end, 22) || timeRangeCoversHour(start, end, 23) || timeRangeCoversHour(start, end, 0);
|
||||
}
|
||||
|
||||
function parseTimeHour(value: unknown) {
|
||||
if (typeof value !== "string") return undefined;
|
||||
const [hourText] = value.split(":");
|
||||
const hour = Number(hourText);
|
||||
if (!Number.isFinite(hour) || hour < 0 || hour > 23) return undefined;
|
||||
return hour;
|
||||
}
|
||||
|
||||
function timeRangeCoversHour(start: number, end: number, hour: number) {
|
||||
if (start === end) return true;
|
||||
if (start < end) return hour >= start && hour <= end;
|
||||
return hour >= start || hour <= end;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -667,9 +748,22 @@ function resetSkinFilter() {
|
||||
|
||||
<!-- 列表标题 & 排序 -->
|
||||
<div class="list-head">
|
||||
<div>
|
||||
<p class="eyebrow">Account Market</p>
|
||||
<h2>可租账号推荐</h2>
|
||||
<div class="zone-head">
|
||||
<p class="eyebrow">Account Zone</p>
|
||||
<h2>账号专区</h2>
|
||||
<div class="zone-tabs">
|
||||
<button
|
||||
v-for="zone in zoneOptions"
|
||||
:key="zone.key"
|
||||
type="button"
|
||||
:class="{ active: activeZone === zone.key }"
|
||||
@click="setActiveZone(zone.key)"
|
||||
>
|
||||
<strong>{{ zone.label }}</strong>
|
||||
<span>{{ zone.hint }}</span>
|
||||
<em>{{ zone.count }}</em>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-actions">
|
||||
<el-radio-group v-model="sortBy" size="small">
|
||||
@@ -1557,6 +1651,83 @@ function resetSkinFilter() {
|
||||
color: #17233d;
|
||||
}
|
||||
|
||||
.zone-head {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.zone-tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
max-width: 1120px;
|
||||
}
|
||||
|
||||
.zone-tabs button {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 2px 12px;
|
||||
min-width: 132px;
|
||||
min-height: 58px;
|
||||
padding: 10px 14px;
|
||||
border: 1px solid #eef1f5;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
color: #17233d;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: all 0.18s ease;
|
||||
}
|
||||
|
||||
.zone-tabs button:hover {
|
||||
border-color: rgba(255, 106, 0, 0.36);
|
||||
box-shadow: 0 8px 20px rgba(23, 35, 61, 0.06);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.zone-tabs button.active {
|
||||
border-color: #ff6a00;
|
||||
background: #fff7ed;
|
||||
box-shadow: 0 8px 20px rgba(255, 106, 0, 0.12);
|
||||
}
|
||||
|
||||
.zone-tabs strong {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: inherit;
|
||||
font-size: 15px;
|
||||
font-weight: 900;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.zone-tabs span {
|
||||
grid-column: 1 / -1;
|
||||
color: #8b9cb5;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.zone-tabs em {
|
||||
align-self: start;
|
||||
min-width: 24px;
|
||||
border-radius: 999px;
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.zone-tabs button.active em {
|
||||
background: #ff6a00;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
|
||||
Reference in New Issue
Block a user