update
Some checks failed
deploy / deploy (push) Has been cancelled

This commit is contained in:
toom1996
2026-08-30 22:49:56 +08:00
parent dd66e5b693
commit 662b12c612
10 changed files with 210 additions and 90 deletions

View File

@ -22,6 +22,29 @@ const sortOptions: { value: string; label: string }[] = [
{ value: "year_desc", label: t('Newest year') },
{ value: "year_asc", label: t('Oldest year') },
]
// 地区筛选:值即后端 street_snap.city 列存储的规范英文名(与 backfill_city 词典保持一致)。
// 标签用 t(city) —— 英文环境回退显示英文(巴黎→Paris),中文环境显示中文(Paris→巴黎)。
const cityOptions: { value: string; label: string }[] = [
{ value: "Paris", label: t('Paris') },
{ value: "New York", label: t('New York') },
{ value: "Milan", label: t('Milan') },
{ value: "London", label: t('London') },
{ value: "Copenhagen", label: t('Copenhagen') },
{ value: "Florence", label: t('Florence') },
{ value: "Berlin", label: t('Berlin') },
{ value: "Tokyo", label: t('Tokyo') },
{ value: "Seoul", label: t('Seoul') },
{ value: "Shanghai", label: t('Shanghai') },
{ value: "Beijing", label: t('Beijing') },
{ value: "Rome", label: t('Rome') },
{ value: "Madrid", label: t('Madrid') },
{ value: "Amsterdam", label: t('Amsterdam') },
{ value: "Antwerp", label: t('Antwerp') },
{ value: "Los Angeles", label: t('Los Angeles') },
{ value: "Moscow", label: t('Moscow') },
{ value: "Mumbai", label: t('Mumbai') },
]
---
<div class="snapsroot w-full" x-data="streetSnapsPage()" data-locale={locale}>
@ -88,6 +111,23 @@ const sortOptions: { value: string; label: string }[] = [
</div>
</section>
<!-- City / 地区 -->
<section class="snapsg">
<header class="snapsg-h" @click="toggleGroup('city')">
<span>{t('City')}</span>
<span class="snapsg-chev" :class="{ 'is-collapsed': collapsedGroups.city }">
<svg viewBox="0 0 12 12" width="11" height="11"><path d="M2.5 4.5l3.5 3 3.5-3" stroke="currentColor" fill="none" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
</span>
</header>
<div class="snapsg-b" x-show="!collapsedGroups.city">
<ul class="snapschecks snapschecks--flat">
{cityOptions.map((o) => (
<li><label><input type="radio" name="snapCity" value={o.value} :checked={'selectedCity === "' + o.value + '"'} :class={`{'is-checked': selectedCity === '${o.value}'}`} @click.prevent={'selectedCity = selectedCity === "' + o.value + '" ? "" : "' + o.value + '"; loadPage(1)'} /> <span>{o.label}</span></label></li>
))}
</ul>
</div>
</section>
<button class="snapsclear" type="button" @click="clearAll()" x-show="pills.length > 0" x-cloak>Clear all ×</button>
</div>
</aside>
@ -172,7 +212,7 @@ const sortOptions: { value: string; label: string }[] = [
</div>
</div>
<script id="snaps-year-opts" type="application/json" set:html={JSON.stringify({ yearOptions, sortOptions })}></script>
<script id="snaps-year-opts" type="application/json" set:html={JSON.stringify({ yearOptions, sortOptions, cityOptions })}></script>
@ -193,11 +233,13 @@ const sortOptions: { value: string; label: string }[] = [
SPIN_SVG,
yearOptions: opts.yearOptions || [],
sortOptions: opts.sortOptions || [],
cityOptions: opts.cityOptions || [],
selectedYear: '' as string,
selectedSort: DEFAULT_SORT as string,
selectedCity: '' as string,
// 侧栏分组折叠状态:默认全部收起(不做持久化,每次进页都是关着的)
collapsedGroups: { year: true, sort: true } as Record<string, boolean>,
collapsedGroups: { year: true, sort: true, city: true } as Record<string, boolean>,
items: [] as (StreetSnapItem & { _imgLoaded?: boolean })[],
loading: false,
@ -207,6 +249,10 @@ const sortOptions: { value: string; label: string }[] = [
init() {
this.locale = this.$el.dataset.locale || 'en'
// 支持从 header 下拉深链 ?city=xxx 直接进入对应地区(与侧栏 City 筛选一致)
const city = new URLSearchParams(window.location.search).get('city')
const allowed = (this.cityOptions || []).map((c: any) => c.value)
if (city && allowed.includes(city)) this.selectedCity = city
this.loadPage(1)
},
@ -217,6 +263,7 @@ const sortOptions: { value: string; label: string }[] = [
clearAll() {
this.selectedYear = ''
this.selectedSort = DEFAULT_SORT
this.selectedCity = ''
this.loadPage(1)
},
@ -237,6 +284,13 @@ const sortOptions: { value: string; label: string }[] = [
clear: () => { this.selectedSort = DEFAULT_SORT; this.loadPage(1) },
})
}
if (this.selectedCity) {
const hit = this.cityOptions.find((o: any) => o.value === this.selectedCity)
out.push({
label: "CITY · " + (hit ? hit.label : this.selectedCity),
clear: () => { this.selectedCity = ''; this.loadPage(1) },
})
}
return out
},
@ -255,6 +309,7 @@ const sortOptions: { value: string; label: string }[] = [
const json = await getStreetSnaps({
page,
year: this.selectedYear || undefined,
city: this.selectedCity || undefined,
sort: this.selectedSort,
})
if (myToken !== this.reqToken) return