feat: use DatePicker for expiry time and add ExpiryReminderDismissed migration (#320)

## Summary
- Replace datetime-local input with DatePicker component for expiry time
selection
- Add ExpiryReminderDismissed field to SQLite migration column check
list
This commit is contained in:
sagit
2026-03-14 12:38:04 +08:00
committed by GitHub
2 changed files with 27 additions and 14 deletions
+1 -1
View File
@@ -261,7 +261,7 @@ func prepareSQLiteLegacyColumns(db *gorm.DB) error {
m := db.Migrator()
if m.HasTable(&model.Node{}) {
for _, field := range []string{"ServerIPV4", "ServerIPV6", "ExtraIPs", "TCPListenAddr", "UDPListenAddr", "Inx", "IsRemote", "RemoteURL", "RemoteToken", "RemoteConfig", "Remark", "ExpiryTime", "RenewalCycle"} {
for _, field := range []string{"ServerIPV4", "ServerIPV6", "ExtraIPs", "TCPListenAddr", "UDPListenAddr", "Inx", "IsRemote", "RemoteURL", "RemoteToken", "RemoteConfig", "Remark", "ExpiryTime", "RenewalCycle", "ExpiryReminderDismissed"} {
if m.HasColumn(&model.Node{}, field) {
continue
}
+26 -13
View File
@@ -1,5 +1,6 @@
import { useState, useEffect, useMemo, useCallback } from "react";
import toast from "react-hot-toast";
import { parseDate } from "@internationalized/date";
import {
DndContext,
KeyboardSensor,
@@ -39,6 +40,7 @@ import { Progress } from "@/shadcn-bridge/heroui/progress";
import { Accordion, AccordionItem } from "@/shadcn-bridge/heroui/accordion";
import { Select, SelectItem } from "@/shadcn-bridge/heroui/select";
import { Checkbox } from "@/shadcn-bridge/heroui/checkbox";
import { DatePicker } from "@/shadcn-bridge/heroui/date-picker";
import {
createNode,
getNodeList,
@@ -2374,26 +2376,37 @@ export default function NodePage() {
</Select>
</div>
<Input
<DatePicker
showMonthAndYearPickers
description="填写最近一次续费时间或周期起始时间,系统会按月/季/年自动推算下次续费"
errorMessage={errors.expiryTime}
isInvalid={!!errors.expiryTime}
label="续费基准时间"
type="datetime-local"
value={
form.expiryTime > 0
? new Date(form.expiryTime).toISOString().slice(0, 16)
: ""
}
variant="bordered"
onChange={(e) =>
setForm((prev) => ({
...prev,
expiryTime: e.target.value
? new Date(e.target.value).getTime()
: 0,
}))
? (parseDate(
new Date(form.expiryTime).toISOString().split("T")[0],
) as any)
: null
}
onChange={(date) => {
if (date) {
const jsDate = new Date(
date.year,
date.month - 1,
date.day,
);
setForm((prev) => ({
...prev,
expiryTime: jsDate.getTime(),
}));
} else {
setForm((prev) => ({
...prev,
expiryTime: 0,
}));
}
}}
/>
<Alert