feat(admin): streamline appointments and fleet intake
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import { computed, ref } from 'vue'
|
||||
import AppointmentInboundCodes from './AppointmentInboundCodes.vue'
|
||||
import { addDays, calendarDates, calendarRange, dateKey, moveCalendar, type CalendarMode } from './calendar'
|
||||
|
||||
export interface CalendarEvent {
|
||||
@@ -11,6 +12,7 @@ export interface CalendarEvent {
|
||||
title: string
|
||||
subtitle?: string
|
||||
fields: Array<{ label: string; value?: string | null }>
|
||||
inboundCodes?: Array<string | null | undefined>
|
||||
canEdit?: boolean
|
||||
canDelete?: boolean
|
||||
}
|
||||
@@ -18,9 +20,10 @@ export interface CalendarEvent {
|
||||
const props = withDefaults(defineProps<{
|
||||
events: CalendarEvent[]
|
||||
loading?: boolean
|
||||
incomplete?: boolean
|
||||
canCreate?: boolean
|
||||
initialDate?: string
|
||||
}>(), { loading: false, canCreate: false, initialDate: '' })
|
||||
}>(), { loading: false, incomplete: false, canCreate: false, initialDate: '' })
|
||||
const emit = defineEmits<{
|
||||
range: [range: { from: string; to: string }]
|
||||
create: [date: string]
|
||||
@@ -84,10 +87,10 @@ defineExpose({ selectedDate, mode })
|
||||
<div v-loading="loading" class="calendar-grid" :class="{ 'week-grid': mode === 'week' }">
|
||||
<button v-for="date in dates" :key="date" type="button" class="calendar-day"
|
||||
:class="{ selected: selectedDate === date, outside: mode === 'month' && date.slice(0, 7) !== selectedDate.slice(0, 7) }"
|
||||
:title="`${date},共 ${(grouped.get(date) || []).length} 条安排`" :aria-label="`${date},${(grouped.get(date) || []).length} 项安排`" :aria-pressed="selectedDate === date" @click="select(date)">
|
||||
:title="`${date},${incomplete ? '已加载' : '共'} ${(grouped.get(date) || []).length} 条安排${incomplete ? '(部分来源未加载)' : ''}`" :aria-label="`${date},${(grouped.get(date) || []).length} 项安排${incomplete ? '(部分来源未加载)' : ''}`" :aria-pressed="selectedDate === date" @click="select(date)">
|
||||
<span class="day-number">{{ mode === 'week' ? `${Number(date.slice(5, 7))}月` : '' }}{{ Number(date.slice(8)) }}</span>
|
||||
<span class="day-events">
|
||||
<span v-for="event in (grouped.get(date) || []).slice(0, 3)" :key="event.key" class="event-chip" :class="event.type" :title="`${event.time} ${event.title} · 当天共 ${(grouped.get(date) || []).length} 条安排`">
|
||||
<span v-for="event in (grouped.get(date) || []).slice(0, 3)" :key="event.key" class="event-chip" :class="event.type" :title="`${event.time} ${event.title} · 当天${incomplete ? '已加载' : '共'} ${(grouped.get(date) || []).length} 条安排${incomplete ? '(部分来源未加载)' : ''}`">
|
||||
{{ event.title }}<small v-if="mode === 'week'">{{ event.time }}</small>
|
||||
</span>
|
||||
<span v-if="(grouped.get(date) || []).length > 3" class="event-more">还有 {{ (grouped.get(date) || []).length - 3 }} 条</span>
|
||||
@@ -96,13 +99,14 @@ defineExpose({ selectedDate, mode })
|
||||
</div>
|
||||
</div>
|
||||
<aside class="calendar-detail" aria-label="当天安排">
|
||||
<header><strong>{{ selectedDate }}</strong><p>当天共有 <b>{{ selectedEvents.length }}</b> 项安排</p></header>
|
||||
<header><strong>{{ selectedDate }}</strong><p>{{ incomplete ? '当天已加载' : '当天共有' }} <b>{{ selectedEvents.length }}</b> 项安排<span v-if="incomplete">(部分来源未加载)</span></p></header>
|
||||
<div class="detail-events" aria-live="polite">
|
||||
<p v-if="!selectedEvents.length && !loading" class="empty-day">当天暂无到港或送仓预约</p>
|
||||
<p v-if="!selectedEvents.length && !loading" class="empty-day">{{ incomplete ? '部分来源未加载,请重试后确认当天安排' : '当天暂无到港或送仓预约' }}</p>
|
||||
<article v-for="event in selectedEvents" :key="event.key" class="detail-event">
|
||||
<div class="event-heading"><span class="event-type" :class="event.type">{{ event.type === 'arrival' ? '船舶到港' : '预约送仓' }}</span><span>{{ event.time || '—' }}</span></div>
|
||||
<h3>{{ event.title }}</h3><p v-if="event.subtitle" class="event-subtitle">{{ event.subtitle }}</p>
|
||||
<dl><div v-for="field in event.fields" :key="field.label"><dt>{{ field.label }}</dt><dd>{{ field.value || '—' }}</dd></div></dl>
|
||||
<AppointmentInboundCodes v-if="event.inboundCodes" :codes="event.inboundCodes" />
|
||||
<footer v-if="event.canEdit || event.canDelete" class="density-actions">
|
||||
<el-button v-if="event.canEdit" class="density-action" :disabled="loading" @click="emit('edit', event)">编辑</el-button>
|
||||
<el-button v-if="event.canDelete" class="density-action" data-tone="danger" :disabled="loading" @click="emit('delete', event)">删除</el-button>
|
||||
|
||||
Reference in New Issue
Block a user