feat(work-results): support historical project outcomes

This commit is contained in:
2026-07-22 00:29:19 +08:00
parent 49189474c1
commit d7664e45a7
26 changed files with 479 additions and 49 deletions
@@ -0,0 +1,79 @@
<template>
<view class="work-date-selector" aria-label="选择工作成果日期">
<button class="date-step" :disabled="disabled" @click="shiftDate(-1)">前一天</button>
<picker
class="date-picker"
mode="date"
:value="modelValue"
:end="today"
:disabled="disabled"
@change="selectDate"
>
<view class="date-current">
<text class="date-label">{{ displayDate }}</text>
<text class="date-hint">{{ modelValue === today ? '选择历史日期' : '点此选择日期' }}</text>
</view>
</picker>
<button class="date-step" :disabled="disabled || modelValue >= today" @click="shiftDate(1)">后一天</button>
</view>
</template>
<script setup lang="ts">
import { computed } from 'vue';
const props = withDefaults(defineProps<{
modelValue: string;
maxDate?: string;
disabled?: boolean;
}>(), {
disabled: false
});
const emit = defineEmits<{
change: [value: string];
}>();
const currentDate = () => new Date().toLocaleDateString('sv-SE', { timeZone: 'Asia/Shanghai' });
const today = computed(() => props.maxDate || currentDate());
const displayDate = computed(() => {
if (props.modelValue === today.value) return `今天 · ${props.modelValue}`;
const [year, month, day] = props.modelValue.split('-').map(Number);
if (!year || !month || !day) return props.modelValue;
return new Intl.DateTimeFormat('zh-CN', {
month: 'long',
day: 'numeric',
weekday: 'short',
timeZone: 'Asia/Shanghai'
}).format(new Date(Date.UTC(year, month - 1, day, 4)));
});
const shiftDate = (days: number) => {
if (props.disabled) return;
const [year, month, day] = props.modelValue.split('-').map(Number);
if (!year || !month || !day) return;
const nextDate = new Date(Date.UTC(year, month - 1, day + days)).toISOString().slice(0, 10);
if (nextDate > today.value || nextDate === props.modelValue) return;
emit('change', nextDate);
};
const selectDate = (event: { detail: { value: string } }) => {
const value = event.detail.value;
if (!value || value > today.value || value === props.modelValue) return;
emit('change', value);
};
</script>
<style scoped>
.work-date-selector{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:stretch;gap:8px;margin-bottom:14px;padding:8px;border:1px solid #e5e7eb;border-radius:18px;background:#fff;box-shadow:0 6px 20px rgba(31,38,50,.04)}
.date-step{display:flex;align-items:center;justify-content:center;min-width:72px;min-height:48px;margin:0;padding:0 10px;border:0;border-radius:13px;background:#f5f6f8;color:#303744;font-size:14px;line-height:1}
.date-step::after{border:0}
.date-step[disabled]{background:#fafafa;color:#b9bec7;opacity:1}
.date-picker{min-width:0}
.date-current{display:flex;align-items:center;justify-content:center;min-height:48px;flex-direction:column;border-radius:13px;background:#fff0f1;text-align:center}
.date-label{color:#171b23;font-size:15px;font-weight:800}
.date-hint{margin-top:3px;color:#d9081c;font-size:11px}
html[data-aihr-font-size='extra-large'] .work-date-selector{grid-template-columns:1fr 1.5fr 1fr}
html[data-aihr-font-size='extra-large'] .date-step{min-width:0;padding:0 6px;font-size:13px}
html[data-aihr-font-size='extra-large'] .date-label{font-size:14px}
</style>