refactor: remove countdown icons
ci / gitleaks (push) Successful in 7s
ci / docker (push) Successful in 5m38s

This commit is contained in:
2026-09-08 13:06:31 +08:00
parent 61f8c27e6c
commit 540ad5f46a
2 changed files with 17 additions and 9 deletions
+8 -9
View File
@@ -10,7 +10,7 @@ type Countdown = {
calendar_mode: 'solar'|'lunar'; lunar_year: number|null; lunar_month: number|null; lunar_day: number|null
ignore_year: boolean; lunar_text: string|null
}
type Form = { title:string; event_date:string; kind:Countdown['kind']; repeat_rule:Countdown['repeat_rule']; icon:string; calendar_mode:Countdown['calendar_mode']; lunar_year:number; lunar_month:number; lunar_day:number; leap_month:boolean; ignore_year:boolean }
type Form = { title:string; event_date:string; kind:Countdown['kind']; repeat_rule:Countdown['repeat_rule']; calendar_mode:Countdown['calendar_mode']; lunar_year:number; lunar_month:number; lunar_day:number; leap_month:boolean; ignore_year:boolean }
type CountdownGroup = { key: string; title: string; items: Countdown[] }
const emit = defineEmits<{ notice: [message: string] }>()
const items = ref<Countdown[]>([]), archived = ref<Countdown[]>([])
@@ -18,7 +18,7 @@ const showArchived = ref(false), open = ref(false), busy = ref(false)
const editingId = ref<string|null>(null), error = ref('')
const detailItem = ref<Countdown|null>(null), showAdvanced = ref(false)
const currentYear = new Date().getFullYear()
const freshForm = (): Form => ({ title:'', event_date:dateKey(new Date()), kind:'countdown', repeat_rule:'none', icon:'📅', calendar_mode:'solar', lunar_year:currentYear, lunar_month:1, lunar_day:1, leap_month:false, ignore_year:false })
const freshForm = (): Form => ({ title:'', event_date:dateKey(new Date()), kind:'countdown', repeat_rule:'none', calendar_mode:'solar', lunar_year:currentYear, lunar_month:1, lunar_day:1, leap_month:false, ignore_year:false })
const form = ref<Form>(freshForm())
const composerOrigin = ref({ x: window.innerWidth - 43, y: window.innerHeight - 104 })
const composerStyle = computed(() => ({ '--fab-origin-x': `${composerOrigin.value.x}px`, '--fab-origin-y': `${composerOrigin.value.y}px` }))
@@ -122,7 +122,7 @@ function edit(item:Countdown) {
detailItem.value=null
editingId.value=item.id
showAdvanced.value=false
form.value={ title:item.title, event_date:item.event_date, kind:item.kind, repeat_rule:item.repeat_rule, icon:item.icon, calendar_mode:item.calendar_mode, lunar_year:item.lunar_year || Number(item.event_date.slice(0,4)), lunar_month:Math.abs(item.lunar_month || 1), lunar_day:item.lunar_day || 1, leap_month:(item.lunar_month || 0)<0, ignore_year:item.ignore_year }
form.value={ title:item.title, event_date:item.event_date, kind:item.kind, repeat_rule:item.repeat_rule, calendar_mode:item.calendar_mode, lunar_year:item.lunar_year || Number(item.event_date.slice(0,4)), lunar_month:Math.abs(item.lunar_month || 1), lunar_day:item.lunar_day || 1, leap_month:(item.lunar_month || 0)<0, ignore_year:item.ignore_year }
open.value=true
focusDialog()
}
@@ -133,7 +133,7 @@ function applyKindDefaults() {
async function save() {
if (!form.value.title.trim()) return
await safe(async()=>{
const payload:any={ title:form.value.title.trim(), event_date:form.value.calendar_mode==='lunar' ? `${form.value.lunar_year}-01-01` : form.value.event_date, kind:form.value.kind, repeat_rule:form.value.ignore_year ? 'yearly' : form.value.repeat_rule, icon:form.value.icon, calendar_mode:form.value.calendar_mode, ignore_year:form.value.ignore_year }
const payload:any={ title:form.value.title.trim(), event_date:form.value.calendar_mode==='lunar' ? `${form.value.lunar_year}-01-01` : form.value.event_date, kind:form.value.kind, repeat_rule:form.value.ignore_year ? 'yearly' : form.value.repeat_rule, calendar_mode:form.value.calendar_mode, ignore_year:form.value.ignore_year }
if (form.value.calendar_mode==='lunar') { payload.lunar_month=form.value.leap_month ? -form.value.lunar_month : form.value.lunar_month; payload.lunar_day=form.value.lunar_day }
const path=editingId.value ? `/countdowns/${editingId.value}` : '/countdowns'
await request(path,{ method:editingId.value?'PATCH':'POST', body:JSON.stringify(payload) })
@@ -166,7 +166,6 @@ onBeforeUnmount(() => { previousFocus = null })
<section v-for="group in countdownGroups" :key="group.key" class="countdown-group">
<h3>{{group.title}}</h3>
<button v-for="item in group.items" :key="item.id" type="button" class="countdown-row" :class="{ pinned:item.pinned, today:item.days===0, past:item.days<0 }" @click="openDetail(item)">
<span class="countdown-icon">{{item.icon}}</span>
<span class="countdown-main"><b>{{item.title}}</b><small>{{primaryDate(item)}}<template v-if="secondaryDate(item)"> · {{secondaryDate(item)}}</template></small><span class="countdown-badges"><em v-for="badge in visibleBadges(item)" :key="badge">{{badge}}</em></span></span>
<span class="countdown-state"><strong>{{item.days===0?'今天':Math.abs(item.days)}}</strong><small>{{countdownDayText(item.days)}}</small></span>
<Pin v-if="item.pinned" class="pinned-icon"/>
@@ -174,18 +173,18 @@ onBeforeUnmount(() => { previousFocus = null })
</section>
</div>
<aside v-if="focusItem" class="countdown-focus">
<small>最近的重要日子</small><span>{{focusItem.icon}}</span><h3>{{focusItem.title}}</h3>
<small>最近的重要日子</small><h3>{{focusItem.title}}</h3>
<div class="countdown-number"><strong>{{focusItem.days===0?'今天':Math.abs(focusItem.days)}}</strong><span v-if="focusItem.days!==0"></span></div>
<b class="countdown-copy">{{countdownDayText(focusItem.days)}}</b><p>{{primaryDate(focusItem)}}</p>
</aside>
</div>
<div v-else-if="!busy" class="countdown-empty"><CalendarHeart/><b>还没有重要日子</b><span>生日、纪念日,或一场期待已久的旅行</span><button type="button" class="primary-small" @click="openFromEmpty">添加第一个重要日子</button></div>
<button v-if="archived.length" class="archived-toggle" @click="showArchived=!showArchived"><ArchiveRestore/>已归档{{archived.length}}</button>
<div v-if="showArchived" class="archived-countdowns"><article v-for="item in archived" :key="item.id"><span>{{item.icon}}</span><b>{{item.title}}</b><small>{{formatDateShort(item.display_date)}}<template v-if="item.lunar_text"> · {{item.lunar_text}}</template><template v-if="item.calendar_mode==='lunar'"> · 农历</template></small><button @click="restore(item)"><ArchiveRestore/>恢复</button><button class="danger-text" @click="purge(item)"><Trash2/>永久删除</button></article></div>
<div v-if="showArchived" class="archived-countdowns"><article v-for="item in archived" :key="item.id"><b>{{item.title}}</b><small>{{formatDateShort(item.display_date)}}<template v-if="item.lunar_text"> · {{item.lunar_text}}</template><template v-if="item.calendar_mode==='lunar'"> · 农历</template></small><button @click="restore(item)"><ArchiveRestore/>恢复</button><button class="danger-text" @click="purge(item)"><Trash2/>永久删除</button></article></div>
</div>
<Transition name="countdown-detail">
<div v-if="detailItem" class="countdown-detail-mask" @click.self="closeDetail"><article class="countdown-detail-sheet" role="dialog" aria-modal="true" aria-labelledby="countdown-detail-title" @keydown.esc="closeDetail">
<header><span class="countdown-icon">{{detailItem.icon}}</span><div><small>重要日子详情</small><h3 id="countdown-detail-title">{{detailItem.title}}</h3></div><button ref="detailCloseButton" type="button" aria-label="关闭详情" @click="closeDetail"><X/></button></header>
<header><div><small>重要日子详情</small><h3 id="countdown-detail-title">{{detailItem.title}}</h3></div><button ref="detailCloseButton" type="button" aria-label="关闭详情" @click="closeDetail"><X/></button></header>
<div class="countdown-detail-days"><strong>{{detailItem.days===0?'今天':Math.abs(detailItem.days)}}</strong><span v-if="detailItem.days!==0"></span><b>{{countdownDayText(detailItem.days)}}</b></div>
<dl><div><dt>日期</dt><dd>{{primaryDate(detailItem)}}</dd></div><div v-if="secondaryDate(detailItem)"><dt>换算</dt><dd>{{secondaryDate(detailItem)}}</dd></div><div><dt>类型</dt><dd>{{countdownKindLabel(detailItem.kind)}} · {{detailItem.calendar_mode==='lunar'?'农历':'公历'}} · {{repeatBadge(detailItem) || '不重复'}}</dd></div></dl>
<footer><button v-if="!detailItem.pinned" type="button" @click="pin(detailItem)"><Pin/>置顶</button><button type="button" @click="edit(detailItem)"><Pencil/>编辑</button><button type="button" class="danger-text" @click="archiveItem(detailItem)"><Archive/>归档</button></footer>
@@ -194,7 +193,7 @@ onBeforeUnmount(() => { previousFocus = null })
<Transition name="countdown-compose">
<div v-if="open" class="countdown-modal-mask" @click.self="closeDialog"><form class="countdown-modal" :style="composerStyle" role="dialog" aria-modal="true" aria-labelledby="countdown-dialog-title" @submit.prevent="save" @keydown.esc="closeDialog" @keydown="trapDialogFocus">
<header><div><small>{{editingId?'调整重要日子':'快速记下重要日子'}}</small><h3 id="countdown-dialog-title">{{editingId?'编辑倒数日':'新建倒数日'}}</h3></div><button type="button" aria-label="关闭" @click="closeDialog"><X/></button></header>
<label>图标与名称<div class="countdown-title-fields"><input v-model="form.icon" maxlength="8" aria-label="图标"><input ref="titleInput" v-model="form.title" maxlength="200" required placeholder="例如:去北海道旅行" autofocus></div></label>
<label>名称<input ref="titleInput" v-model="form.title" maxlength="200" required placeholder="例如:去北海道旅行" autofocus></label>
<label v-if="form.calendar_mode==='solar'">日期<input v-model="form.event_date" type="date" required></label>
<label>类型<select v-model="form.kind" @change="applyKindDefaults"><option value="countdown">倒数日</option><option value="anniversary">纪念日</option><option value="birthday">生日</option></select></label>
<details class="countdown-advanced" :open="showAdvanced" @toggle="showAdvanced=($event.target as HTMLDetailsElement).open"><summary><span>更多设置</span><ChevronDown/></summary>