Feature/fix external subscription client expiry (#6333)

* fix(sub): honor client expiry for external links

* fix(ui): show client expiry on external links

* fix(sub): address external expiry review
This commit is contained in:
duqigit
2026-09-04 04:32:05 +08:00
committed by GitHub
parent 13e87a18c8
commit 2ddcf53020
16 changed files with 332 additions and 61 deletions
+33 -22
View File
@@ -34,6 +34,7 @@ import { HttpUtil, IntlUtil, RandomUtil, Wireguard } from '@/utils';
import { formatInboundLabel } from '@/lib/inbounds/label';
import { generateMtprotoSecret } from '@/lib/xray/inbound-defaults';
import { normalizeClientIps, type ClientIpInfo } from '@/lib/clients/ip-log';
import { resolveExternalLinkExpiry } from '@/lib/clients/external-link';
import { useDatepicker } from '@/hooks/useDatepicker';
import { useClientHwids } from '@/hooks/useClientHwids';
import { DateTimePicker, SelectAllClearButtons } from '@/components/form';
@@ -1370,17 +1371,22 @@ export default function ClientFormModal({
<Controller
control={methods.control}
name={`externalLinks.${index}.expiryTime`}
render={({ field: expiryField }) => (
<DateTimePicker
value={
Number(expiryField.value) > 0
? dayjs(Number(expiryField.value))
: null
}
onChange={(v) => expiryField.onChange(v ? v.valueOf() : 0)}
placeholder={t('pages.inbounds.leaveBlankToNeverExpire')}
/>
)}
render={({ field: expiryField }) => {
const displayedExpiry = resolveExternalLinkExpiry(
expiryField.value,
expiryDate,
);
const hasSpecificExpiry = Number(expiryField.value) > 0;
return (
<DateTimePicker
value={displayedExpiry > 0 ? dayjs(displayedExpiry) : null}
onChange={(v) => expiryField.onChange(v ? v.valueOf() : 0)}
placeholder={t('pages.inbounds.leaveBlankToNeverExpire')}
allowClear={hasSpecificExpiry}
maxDate={expiryDate > 0 ? dayjs(expiryDate) : undefined}
/>
);
}}
/>
</div>
</div>
@@ -1442,17 +1448,22 @@ export default function ClientFormModal({
<Controller
control={methods.control}
name={`externalLinks.${index}.expiryTime`}
render={({ field: expiryField }) => (
<DateTimePicker
value={
Number(expiryField.value) > 0
? dayjs(Number(expiryField.value))
: null
}
onChange={(v) => expiryField.onChange(v ? v.valueOf() : 0)}
placeholder={t('pages.inbounds.leaveBlankToNeverExpire')}
/>
)}
render={({ field: expiryField }) => {
const displayedExpiry = resolveExternalLinkExpiry(
expiryField.value,
expiryDate,
);
const hasSpecificExpiry = Number(expiryField.value) > 0;
return (
<DateTimePicker
value={displayedExpiry > 0 ? dayjs(displayedExpiry) : null}
onChange={(v) => expiryField.onChange(v ? v.valueOf() : 0)}
placeholder={t('pages.inbounds.leaveBlankToNeverExpire')}
allowClear={hasSpecificExpiry}
maxDate={expiryDate > 0 ? dayjs(expiryDate) : undefined}
/>
);
}}
/>
</div>
<Typography.Text