feat: 添加日期验证功能,确保发行日期不早于当前日期,申购截止日期不早于发行日期

This commit is contained in:
2025-12-19 19:35:43 +07:00
parent 9614563d3c
commit 2e2290022f
4 changed files with 63 additions and 28 deletions

View File

@@ -2,16 +2,23 @@
import type { FieldBindingObject } from "vee-validate"; import type { FieldBindingObject } from "vee-validate";
interface Props extends FieldBindingObject { interface Props extends FieldBindingObject {
datetime: string;
label?: string; label?: string;
formatterValue?: (value: string) => string; formatterValue?: (value: string) => string;
format?: (value: string) => string; format?: (value: string) => string;
min?: string;
max?: string;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();
const emit = defineEmits<{
(e: "update:value", value: string): void;
}>();
function handleChange(value: string) { function handleChange(value: string) {
const formattedValue = props.formatterValue ? props.formatterValue(value) : new Date(value).toISOString(); const formattedValue = props.formatterValue ? props.formatterValue(value) : new Date(value).toISOString();
props.onChange(formattedValue); props.onChange(formattedValue);
emit("update:value", formattedValue);
} }
function formatDisplay(value: string) { function formatDisplay(value: string) {
@@ -24,18 +31,20 @@ function formatDisplay(value: string) {
<ion-label class="text-sm font-bold color-(--ion-text-color-secondary) mb-3.5"> <ion-label class="text-sm font-bold color-(--ion-text-color-secondary) mb-3.5">
{{ props.label }} {{ props.label }}
</ion-label> </ion-label>
<ion-datetime-button datetime="datetime" color="primary"> <ion-datetime-button :datetime="datetime" color="primary">
<div slot="date-target"> <div slot="date-target">
{{ formatDisplay(props.value) }} {{ formatDisplay(props.value) }}
</div> </div>
</ion-datetime-button> </ion-datetime-button>
<ion-modal :keep-contents-mounted="true"> <ion-modal :keep-contents-mounted="true">
<ion-datetime <ion-datetime
id="datetime" :id="datetime"
class="ui-datetime" class="ui-datetime"
done-text="Done" done-text="Done"
presentation="date" presentation="date"
:show-default-buttons="true" :show-default-buttons="true"
:min="props.min"
:max="props.max"
@ion-change="handleChange($event.detail.value as string)" @ion-change="handleChange($event.detail.value as string)"
/> />
</ion-modal> </ion-modal>

View File

@@ -176,9 +176,11 @@
"categoryRequired": "Type is required", "categoryRequired": "Type is required",
"editionNameRequired": "Edition name is required", "editionNameRequired": "Edition name is required",
"launchDateRequired": "Launch date is required", "launchDateRequired": "Launch date is required",
"launchDateNotPast": "Launch date cannot be earlier than current date",
"perUserLimitRequired": "Per user limit is required", "perUserLimitRequired": "Per user limit is required",
"totalSupplyRequired": "Total supply is required", "totalSupplyRequired": "Total supply is required",
"subscriptionDeadlineRequired": "Subscription deadline is required", "subscriptionDeadlineRequired": "Subscription deadline is required",
"deadlineAfterLaunch": "Subscription deadline cannot be earlier than launch date",
"unitPriceRequired": "Unit price is required", "unitPriceRequired": "Unit price is required",
"dividendRateRequired": "Dividend rate is required" "dividendRateRequired": "Dividend rate is required"
}, },

View File

@@ -176,9 +176,11 @@
"categoryRequired": "产品类型是必填项", "categoryRequired": "产品类型是必填项",
"editionNameRequired": "发行期名称是必填项", "editionNameRequired": "发行期名称是必填项",
"launchDateRequired": "发行日期是必填项", "launchDateRequired": "发行日期是必填项",
"launchDateNotPast": "发行日期不能小于当前日期",
"perUserLimitRequired": "个人申购上限是必填项", "perUserLimitRequired": "个人申购上限是必填项",
"totalSupplyRequired": "发行总量是必填项", "totalSupplyRequired": "发行总量是必填项",
"subscriptionDeadlineRequired": "申购截止日期是必填项", "subscriptionDeadlineRequired": "申购截止日期是必填项",
"deadlineAfterLaunch": "申购截止日期不能小于发行日期",
"unitPriceRequired": "单价是必填项", "unitPriceRequired": "单价是必填项",
"dividendRateRequired": "分红率是必填项" "dividendRateRequired": "分红率是必填项"
}, },

View File

@@ -34,10 +34,23 @@ const schema = toTypedSchema(yup.object({
editions: yup.array().of( editions: yup.array().of(
yup.object({ yup.object({
editionName: yup.string().required(t("asset.issue.apply.validation.editionNameRequired")), editionName: yup.string().required(t("asset.issue.apply.validation.editionNameRequired")),
launchDate: yup.string().required(t("asset.issue.apply.validation.launchDateRequired")), launchDate: yup.string()
.required(t("asset.issue.apply.validation.launchDateRequired"))
.test("not-past", t("asset.issue.apply.validation.launchDateNotPast"), (value) => {
if (!value)
return true;
return new Date(value) >= new Date(now.value.toDateString());
}),
perUserLimit: yup.string().required(t("asset.issue.apply.validation.perUserLimitRequired")), perUserLimit: yup.string().required(t("asset.issue.apply.validation.perUserLimitRequired")),
totalSupply: yup.string().required(t("asset.issue.apply.validation.totalSupplyRequired")), totalSupply: yup.string().required(t("asset.issue.apply.validation.totalSupplyRequired")),
subscriptionDeadline: yup.string().required(t("asset.issue.apply.validation.subscriptionDeadlineRequired")), subscriptionDeadline: yup.string()
.required(t("asset.issue.apply.validation.subscriptionDeadlineRequired"))
.test("after-launch", t("asset.issue.apply.validation.deadlineAfterLaunch"), function (value) {
const { launchDate } = this.parent;
if (!value || !launchDate)
return true;
return new Date(value) >= new Date(launchDate);
}),
unitPrice: yup.string().required(t("asset.issue.apply.validation.unitPriceRequired")), unitPrice: yup.string().required(t("asset.issue.apply.validation.unitPriceRequired")),
dividendRate: yup.string().required(t("asset.issue.apply.validation.dividendRateRequired")), dividendRate: yup.string().required(t("asset.issue.apply.validation.dividendRateRequired")),
}), }),
@@ -47,11 +60,6 @@ const schema = toTypedSchema(yup.object({
function handleSubmit(values: GenericObject) { function handleSubmit(values: GenericObject) {
emit("submit", values.editions); emit("submit", values.editions);
} }
function handleChange(event: Event) {
debugger;
const input = event.target as HTMLInputElement;
return new Date(input.value);
}
</script> </script>
<template> <template>
@@ -70,18 +78,6 @@ function handleChange(event: Event) {
</Field> </Field>
<ErrorMessage :name="`editions[${idx}].editionName`" /> <ErrorMessage :name="`editions[${idx}].editionName`" />
</div> </div>
<div>
<Field :name="`editions[${idx}].launchDate`">
<template #default="{ field }">
<ui-datetime
v-bind="field"
:label="t('asset.issue.apply.launchDate')"
:formatter-value="(val) => new Date(val).toISOString()"
/>
</template>
</Field>
<ErrorMessage :name="`editions[${idx}].launchDate`" />
</div>
<div> <div>
<Field :name="`editions[${idx}].perUserLimit`" type="text"> <Field :name="`editions[${idx}].perUserLimit`" type="text">
@@ -115,15 +111,41 @@ function handleChange(event: Event) {
<div> <div>
<Field :name="`editions[${idx}].subscriptionDeadline`"> <Field :name="`editions[${idx}].subscriptionDeadline`">
<template #default="{ setValue }">
<Field :name="`editions[${idx}].launchDate`">
<template #default="{ field }"> <template #default="{ field }">
<ui-datetime <ui-datetime
datetime="launchDate"
v-bind="field"
:label="t('asset.issue.apply.launchDate')"
:min="now.toISOString()"
@update:value="(val) => {
setValue(val);
}"
/>
</template>
</Field>
<ErrorMessage :name="`editions[${idx}].launchDate`" />
</template>
</Field>
</div>
<div>
<Field :name="`editions[${idx}].launchDate`">
<template #default="{ value: launchDate }">
<Field :name="`editions[${idx}].subscriptionDeadline`">
<template #default="{ field }">
<ui-datetime
datetime="subscriptionDeadline"
v-bind="field" v-bind="field"
:label="t('asset.issue.apply.subscriptionDeadline')" :label="t('asset.issue.apply.subscriptionDeadline')"
:formatter-value="(val) => new Date(val).toISOString()" :min="launchDate ? new Date(launchDate).toISOString() : now.toISOString()"
/> />
</template> </template>
</Field> </Field>
<ErrorMessage :name="`editions[${idx}].subscriptionDeadline`" /> <ErrorMessage :name="`editions[${idx}].subscriptionDeadline`" />
</template>
</Field>
</div> </div>
<div> <div>