add customer lunar birthdate
This commit is contained in:
@@ -5,6 +5,18 @@
|
||||
:customer="customer"
|
||||
/>
|
||||
<t-cell-group v-if="customer" theme="card">
|
||||
<t-cell title="出生日期">
|
||||
<button
|
||||
v-if="isLunarBirthdate"
|
||||
class="birthdate-trigger"
|
||||
type="button"
|
||||
@click.stop="toggleBirthdateText"
|
||||
>
|
||||
<span v-text="birthdateText" />
|
||||
</button>
|
||||
<span v-else v-text="birthdateText" />
|
||||
</t-cell>
|
||||
<t-cell title="年龄" :note="ageText" />
|
||||
<t-cell title="住址" :note="customer.address || '无'" />
|
||||
<t-cell title="病症" :note="customer.disease || '无'" />
|
||||
<t-cell title="备注" :note="customer.remark || '无'" />
|
||||
@@ -162,6 +174,7 @@ import { useSettingStore } from "@/store/settingStore";
|
||||
import type { BodyAreaValue, Customer } from "@/types/Customer";
|
||||
import { getCustomerPhotoURL, normalizeBodyAreaValue } from "@/utils/customer";
|
||||
import { gaoPermissionCodes } from "@/utils/gaoPermission";
|
||||
import { LunarCalendar } from "@/utils/LunarCalendar";
|
||||
|
||||
defineOptions({
|
||||
name: "CustomerDetail"
|
||||
@@ -180,6 +193,7 @@ const scanPopupVisible = ref(false);
|
||||
const pendingInvitee = ref<Customer>();
|
||||
const scanStatus = ref("点击扫码开始识别。");
|
||||
const removing = ref(false);
|
||||
const showSolarBirthdate = ref(false);
|
||||
let latestDecodedText = "";
|
||||
|
||||
const inviter = computed(() => customer.value?.introducerCustomer);
|
||||
@@ -189,6 +203,10 @@ const creatorName = computed(() => {
|
||||
return creatorUser?.nick || creatorUser?.name || customer.value?.creatorUserId || "无";
|
||||
});
|
||||
const createdAtText = computed(() => formatTime(customer.value?.createdAt));
|
||||
const isLunarBirthdate = computed(() => customer.value?.birthdateCalendar === "LUNAR" && !!customer.value?.birthdate);
|
||||
const solarBirthdateText = computed(() => formatSolarBirthdate(customer.value));
|
||||
const birthdateText = computed(() => showSolarBirthdate.value && isLunarBirthdate.value ? solarBirthdateText.value : formatBirthdate(customer.value));
|
||||
const ageText = computed(() => customer.value?.age === undefined || customer.value?.age === null ? "无" : `${customer.value.age} 岁`);
|
||||
const selectedAreas = computed<BodyAreaValue>({
|
||||
get() {
|
||||
return normalizeBodyAreaValue(customer.value?.conditioningPart);
|
||||
@@ -203,10 +221,12 @@ async function loadCustomer(): Promise<void> {
|
||||
if (!id) {
|
||||
customer.value = undefined;
|
||||
invitees.value = [];
|
||||
showSolarBirthdate.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
showSolarBirthdate.value = false;
|
||||
customer.value = await CustomerAPI.detail(id);
|
||||
await loadInvitees();
|
||||
} catch (err) {
|
||||
@@ -297,6 +317,27 @@ function formatTime(value?: number): string {
|
||||
return Time.formatDateTime(date);
|
||||
}
|
||||
|
||||
function formatBirthdate(value?: Customer): string {
|
||||
if (!value?.birthdate) {
|
||||
return "无";
|
||||
}
|
||||
if (value.birthdateCalendar !== "LUNAR") {
|
||||
return `公历 ${value.birthdate}`;
|
||||
}
|
||||
const lunarDate = LunarCalendar.solarToLunar(value.birthdate);
|
||||
return lunarDate ? LunarCalendar.formatLunarDate(lunarDate) : "农历日期";
|
||||
}
|
||||
|
||||
function formatSolarBirthdate(value?: Customer): string {
|
||||
return value?.birthdate ? `公历 ${value.birthdate}` : "无";
|
||||
}
|
||||
|
||||
function toggleBirthdateText(): void {
|
||||
if (isLunarBirthdate.value) {
|
||||
showSolarBirthdate.value = !showSolarBirthdate.value;
|
||||
}
|
||||
}
|
||||
|
||||
function isCustomerAncestor(invitee: Customer): boolean {
|
||||
if (!customer.value?.id) {
|
||||
return false;
|
||||
@@ -519,6 +560,17 @@ watch(() => route.params.id, async () => {
|
||||
}
|
||||
}
|
||||
|
||||
.birthdate-trigger {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
color: var(--td-text-color-primary);
|
||||
font: inherit;
|
||||
background: transparent;
|
||||
text-align: right;
|
||||
text-decoration: underline dotted;
|
||||
text-underline-offset: .2rem;
|
||||
}
|
||||
|
||||
.scan-popup {
|
||||
gap: 1rem;
|
||||
padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom, 0)) 1rem;
|
||||
|
||||
@@ -34,11 +34,18 @@
|
||||
borderless
|
||||
/>
|
||||
</t-form-item>
|
||||
<t-form-item label="出生日期">
|
||||
<birthdate-picker
|
||||
v-model="formModel.birthdate"
|
||||
v-model:calendar="formModel.birthdateCalendar"
|
||||
/>
|
||||
</t-form-item>
|
||||
<t-form-item label="年龄">
|
||||
<t-input
|
||||
v-model.trim="formModel.age"
|
||||
type="number"
|
||||
placeholder="年龄"
|
||||
:readonly="!!formModel.birthdate"
|
||||
:placeholder="formModel.birthdate ? '根据出生日期自动计算' : '年龄'"
|
||||
borderless
|
||||
/>
|
||||
</t-form-item>
|
||||
@@ -157,7 +164,7 @@ import CodeScanner from "@/components/CodeScanner.vue";
|
||||
import CustomerSelector from "@/components/CustomerSelector.vue";
|
||||
import PhotoField from "@/components/PhotoField.vue";
|
||||
import { useSettingStore } from "@/store/settingStore";
|
||||
import type { BodyAreaValue, Customer, CustomerGender } from "@/types/Customer";
|
||||
import type { BodyAreaValue, Customer, CustomerBirthdateCalendar, CustomerGender } from "@/types/Customer";
|
||||
import { createBodyAreaValue, getCustomerPhotoURL, normalizeBodyAreaValue } from "@/utils/customer";
|
||||
import { gaoPermissionCodes } from "@/utils/gaoPermission";
|
||||
import { compressUploadImage } from "@/utils/imageCompression";
|
||||
@@ -194,6 +201,8 @@ const formModel = reactive({
|
||||
photoURL: "",
|
||||
telephone: "",
|
||||
age: "",
|
||||
birthdate: "",
|
||||
birthdateCalendar: "SOLAR" as CustomerBirthdateCalendar,
|
||||
address: "",
|
||||
referrer: "",
|
||||
disease: "",
|
||||
@@ -209,6 +218,8 @@ function resetFormModel(): void {
|
||||
photoURL: "",
|
||||
telephone: "",
|
||||
age: "",
|
||||
birthdate: "",
|
||||
birthdateCalendar: "SOLAR",
|
||||
address: "",
|
||||
referrer: "",
|
||||
disease: "",
|
||||
@@ -258,6 +269,8 @@ async function fillForm(): Promise<void> {
|
||||
photoURL: getCustomerPhotoURL(customer),
|
||||
telephone: customer.telephone || "",
|
||||
age: customer.age === undefined || customer.age === null ? "" : String(customer.age),
|
||||
birthdate: customer.birthdate || "",
|
||||
birthdateCalendar: customer.birthdateCalendar || "SOLAR",
|
||||
address: customer.address || "",
|
||||
referrer: customer.introducerCustomer?.name || "",
|
||||
disease: customer.disease || "",
|
||||
@@ -406,6 +419,8 @@ async function saveCustomer(): Promise<void> {
|
||||
name: formModel.name,
|
||||
gender: formModel.gender || undefined,
|
||||
age: Number(formModel.age) || undefined,
|
||||
birthdate: formModel.birthdate || null,
|
||||
birthdateCalendar: formModel.birthdate ? formModel.birthdateCalendar : undefined,
|
||||
telephone: formModel.telephone,
|
||||
address: formModel.address,
|
||||
remark: formModel.note,
|
||||
@@ -463,6 +478,28 @@ watch(() => formModel.referrer, (value) => {
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => formModel.birthdate, (value) => {
|
||||
if (value) {
|
||||
formModel.age = String(calculateAge(value));
|
||||
}
|
||||
});
|
||||
|
||||
function calculateAge(value: string): number {
|
||||
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
||||
if (!match) {
|
||||
return 0;
|
||||
}
|
||||
const birthYear = Number(match[1]);
|
||||
const birthMonth = Number(match[2]);
|
||||
const birthDay = Number(match[3]);
|
||||
const today = new Date();
|
||||
let age = today.getFullYear() - birthYear;
|
||||
if (today.getMonth() + 1 < birthMonth || (today.getMonth() + 1 === birthMonth && today.getDate() < birthDay)) {
|
||||
age--;
|
||||
}
|
||||
return Math.max(age, 0);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await fillForm();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user