修改完成待测试
This commit is contained in:
+142
-42
@@ -49,7 +49,7 @@
|
||||
<picker
|
||||
:range="sexOptions.map((item) => item.label)"
|
||||
:value="optionIndex(sexOptions, editForm.sex)"
|
||||
@change="selectOption('sex', sexOptions, $event)"
|
||||
@change="selectSex"
|
||||
>
|
||||
<view class="form-field form-field--picker">
|
||||
<text>性别</text
|
||||
@@ -148,8 +148,28 @@
|
||||
type="number"
|
||||
placeholder="正整数"
|
||||
placeholder-class="form-placeholder"
|
||||
@blur="loadRankOptions"
|
||||
/>
|
||||
</view>
|
||||
<picker
|
||||
v-if="rankOptions.length"
|
||||
:range="rankPickerLabels"
|
||||
:value="rankOptionIndex"
|
||||
:disabled="rankOptionsState !== 'ready'"
|
||||
@change="selectRank"
|
||||
>
|
||||
<view class="form-field form-field--picker">
|
||||
<text>排行称谓</text>
|
||||
<text>{{ selectedRankName || "请选择" }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
<view v-else class="form-field form-field--disabled">
|
||||
<text>排行称谓</text>
|
||||
<text>{{ rankOptionStateLabel }}</text>
|
||||
</view>
|
||||
<text v-if="rankOptionsState === 'error'" class="field-error"
|
||||
>排行配置暂未就绪,请稍后重试。</text
|
||||
>
|
||||
<picker
|
||||
:range="personOptionLabels"
|
||||
:value="personOptionIndex(editForm.fatherId)"
|
||||
@@ -170,16 +190,15 @@
|
||||
><text>{{ personOptionLabel(editForm.motherId) }}</text></view
|
||||
>
|
||||
</picker>
|
||||
<picker
|
||||
mode="date"
|
||||
:value="editForm.birthDate"
|
||||
@change="selectDate('birthDate', $event)"
|
||||
<view
|
||||
class="form-field form-field--picker"
|
||||
role="button"
|
||||
aria-label="选择出生日期"
|
||||
@click="openDatePicker('birthDate', '选择出生日期')"
|
||||
>
|
||||
<view class="form-field form-field--picker"
|
||||
><text>出生日期</text
|
||||
><text>{{ editForm.birthDate || "未填写" }}</text></view
|
||||
>
|
||||
</picker>
|
||||
<text>出生日期</text>
|
||||
<text>{{ editForm.birthDate || "未填写" }}</text>
|
||||
</view>
|
||||
<picker
|
||||
:range="lunarOptions.map((item) => item.label)"
|
||||
:value="optionIndex(lunarOptions, editForm.birthLunar)"
|
||||
@@ -257,17 +276,16 @@
|
||||
placeholder-class="form-placeholder"
|
||||
/>
|
||||
</view>
|
||||
<picker
|
||||
<view
|
||||
v-if="isDeceased"
|
||||
mode="date"
|
||||
:value="editForm.deathDate"
|
||||
@change="selectDate('deathDate', $event)"
|
||||
class="form-field form-field--picker"
|
||||
role="button"
|
||||
aria-label="选择离世日期"
|
||||
@click="openDatePicker('deathDate', '选择离世日期')"
|
||||
>
|
||||
<view class="form-field form-field--picker"
|
||||
><text>离世日期</text
|
||||
><text>{{ editForm.deathDate || "在世或未填写" }}</text></view
|
||||
>
|
||||
</picker>
|
||||
<text>离世日期</text>
|
||||
<text>{{ editForm.deathDate || "在世或未填写" }}</text>
|
||||
</view>
|
||||
<picker
|
||||
v-if="isDeceased"
|
||||
:range="lunarOptions.map((item) => item.label)"
|
||||
@@ -329,17 +347,16 @@
|
||||
class="form-note"
|
||||
>遗传病史属于敏感健康信息,仅在已授权时读取和保存。</text
|
||||
>
|
||||
<picker
|
||||
<view
|
||||
v-if="isDeceased"
|
||||
mode="date"
|
||||
:value="editForm.burialDate"
|
||||
@change="selectDate('burialDate', $event)"
|
||||
class="form-field form-field--picker"
|
||||
role="button"
|
||||
aria-label="选择安葬日期"
|
||||
@click="openDatePicker('burialDate', '选择安葬日期')"
|
||||
>
|
||||
<view class="form-field form-field--picker"
|
||||
><text>安葬日期</text
|
||||
><text>{{ editForm.burialDate || "未填写" }}</text></view
|
||||
>
|
||||
</picker>
|
||||
<text>安葬日期</text>
|
||||
<text>{{ editForm.burialDate || "未填写" }}</text>
|
||||
</view>
|
||||
<view v-if="isDeceased" class="form-field">
|
||||
<text>安葬地</text>
|
||||
<input
|
||||
@@ -361,15 +378,6 @@
|
||||
}}</text>
|
||||
</view>
|
||||
</picker>
|
||||
<view class="form-field">
|
||||
<text>排序值</text>
|
||||
<input
|
||||
v-model="editForm.sortOrder"
|
||||
type="number"
|
||||
placeholder="可选整数,值越小越靠前"
|
||||
placeholder-class="form-placeholder"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-field form-field--summary">
|
||||
<text>人物简介</text>
|
||||
<textarea
|
||||
@@ -419,6 +427,14 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<MemberDatePickerSheet
|
||||
:visible="datePickerVisible"
|
||||
:title="datePickerTitle"
|
||||
:value="datePickerValue"
|
||||
@cancel="closeDatePicker"
|
||||
@confirm="confirmDatePicker"
|
||||
/>
|
||||
|
||||
<AppDialog
|
||||
:visible="discardDialogVisible"
|
||||
eyebrow="资料尚未保存"
|
||||
@@ -439,6 +455,7 @@ import { computed, reactive, ref } from "vue";
|
||||
import { onBackPress, onLoad, onUnload } from "@dcloudio/uni-app";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
import AppDialog from "@/components/AppDialog.vue";
|
||||
import MemberDatePickerSheet from "@/components/tree/MemberDatePickerSheet.vue";
|
||||
import ModulePageBackground from "@/components/ModulePageBackground.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
import {
|
||||
@@ -476,11 +493,15 @@ const isAvatarUploading = ref(false);
|
||||
const avatarFileName = ref("");
|
||||
const avatarUploadError = ref("");
|
||||
const discardDialogVisible = ref(false);
|
||||
const datePickerVisible = ref(false);
|
||||
const datePickerField = ref("");
|
||||
const datePickerTitle = ref("选择日期");
|
||||
const errorMessage = ref("");
|
||||
const failedAction = ref("load");
|
||||
const memberDetailRequestController = createRequestController();
|
||||
const personOptionsRequestController = createRequestController();
|
||||
const memberOptionsRequestController = createRequestController();
|
||||
const rankOptionsRequestController = createRequestController();
|
||||
const avatarUploadRequestController = createRequestController();
|
||||
const memberUpdateRequestController = createRequestController();
|
||||
const sensitiveProfileRequestController = createRequestController();
|
||||
@@ -491,6 +512,8 @@ const dictionaryRequestControllers = {
|
||||
};
|
||||
let pageActive = true;
|
||||
let loadSequence = 0;
|
||||
let rankLoadSequence = 0;
|
||||
let rankOptionsContext = "";
|
||||
|
||||
const originalMember = ref(null);
|
||||
const baseline = ref("");
|
||||
@@ -504,6 +527,7 @@ const editForm = reactive({
|
||||
sex: "",
|
||||
generation: "",
|
||||
generationName: "",
|
||||
rankId: "",
|
||||
fatherId: "",
|
||||
motherId: "",
|
||||
avatarOssId: "",
|
||||
@@ -541,6 +565,8 @@ const lunarOptions = memberFormOptions.lunar;
|
||||
const personStatusOptions = memberFormOptions.personStatus;
|
||||
const bindingModeOptions = memberFormOptions.bindingMode;
|
||||
const personOptions = ref([{ label: "不选择", value: "" }]);
|
||||
const rankOptionsState = ref("idle");
|
||||
const rankOptions = ref([]);
|
||||
const personOptionLabels = computed(() =>
|
||||
personOptions.value.map((item) => item.label),
|
||||
);
|
||||
@@ -565,6 +591,26 @@ const memberOptionLabels = computed(() =>
|
||||
memberBindingOptions.value.map((item) => item.label),
|
||||
);
|
||||
const isDeceased = computed(() => editForm.personStatus === "1");
|
||||
const datePickerValue = computed(() => editForm[datePickerField.value] || "");
|
||||
const rankOptionIndex = computed(() => {
|
||||
const index = rankOptions.value.findIndex((item) => item.rankId === editForm.rankId);
|
||||
return index < 0 ? 0 : index + 1;
|
||||
});
|
||||
const rankPickerLabels = computed(() => [
|
||||
"请选择排行称谓",
|
||||
...rankOptions.value.map((item) => item.rankName),
|
||||
]);
|
||||
const selectedRankName = computed(
|
||||
() =>
|
||||
rankOptions.value.find((item) => item.rankId === editForm.rankId)?.rankName ||
|
||||
(editForm.rankId === originalMember.value?.rankId ? originalMember.value?.rankName : "") ||
|
||||
"",
|
||||
);
|
||||
const rankOptionStateLabel = computed(() => {
|
||||
if (rankOptionsState.value === "loading") return "正在读取";
|
||||
if (rankOptionsState.value === "error") return "暂时无法读取";
|
||||
return selectedRankName.value || "暂无可选排行";
|
||||
});
|
||||
|
||||
const formSnapshot = computed(() => JSON.stringify(editForm));
|
||||
const hasValidContext = computed(() =>
|
||||
@@ -654,6 +700,7 @@ const loadMember = async () => {
|
||||
sex: member.sex || "",
|
||||
generation: member.generation || "",
|
||||
generationName: member.generationName || "",
|
||||
rankId: member.rankId || "",
|
||||
fatherId:
|
||||
member.relatives.find((item) => item.relation === "父亲")?.id || "",
|
||||
motherId:
|
||||
@@ -696,6 +743,8 @@ const loadMember = async () => {
|
||||
errorMessage.value = "";
|
||||
failedAction.value = "load";
|
||||
editState.value = "form";
|
||||
rankOptionsContext = `${Number(editForm.generation)}:${String(editForm.sex || "")}`;
|
||||
void loadRankOptions();
|
||||
} catch (error) {
|
||||
if (!pageActive || activeLoad !== loadSequence || isRequestCancelled(error)) return;
|
||||
originalMember.value = null;
|
||||
@@ -720,7 +769,7 @@ const loadPersonOptions = async () => {
|
||||
return null;
|
||||
}
|
||||
const name = item.name;
|
||||
return { value: personOptionId, label: `${name}(${personOptionId})` };
|
||||
return { value: personOptionId, label: name };
|
||||
})
|
||||
.filter(Boolean);
|
||||
personOptions.value = [{ label: "不选择", value: "" }, ...options];
|
||||
@@ -779,6 +828,32 @@ const loadMemberOptions = async () => {
|
||||
memberOptionsState.value = "error";
|
||||
}
|
||||
};
|
||||
const loadRankOptions = async () => {
|
||||
const generation = Number(editForm.generation);
|
||||
const sex = String(editForm.sex || "");
|
||||
const context = `${generation}:${sex}`;
|
||||
const activeLoad = ++rankLoadSequence;
|
||||
if (!Number.isSafeInteger(generation) || generation < 1 || !["0", "1", "2"].includes(sex)) {
|
||||
rankOptions.value = [];
|
||||
rankOptionsState.value = "idle";
|
||||
return;
|
||||
}
|
||||
if (context !== rankOptionsContext) editForm.rankId = "";
|
||||
rankOptionsContext = context;
|
||||
rankOptionsState.value = "loading";
|
||||
try {
|
||||
const options = await lineageApi.getRankOptions(genealogyId.value, generation, sex, {
|
||||
requestController: rankOptionsRequestController,
|
||||
});
|
||||
if (!pageActive || activeLoad !== rankLoadSequence) return;
|
||||
rankOptions.value = options;
|
||||
rankOptionsState.value = "ready";
|
||||
} catch (error) {
|
||||
if (!pageActive || activeLoad !== rankLoadSequence || isRequestCancelled(error)) return;
|
||||
rankOptions.value = [];
|
||||
rankOptionsState.value = "error";
|
||||
}
|
||||
};
|
||||
|
||||
onLoad((query) => {
|
||||
genealogyId.value = String(query?.genealogyId || "");
|
||||
@@ -802,6 +877,7 @@ onUnload(() => {
|
||||
memberDetailRequestController.abort();
|
||||
personOptionsRequestController.abort();
|
||||
memberOptionsRequestController.abort();
|
||||
rankOptionsRequestController.abort();
|
||||
avatarUploadRequestController.abort();
|
||||
memberUpdateRequestController.abort();
|
||||
sensitiveProfileRequestController.abort();
|
||||
@@ -811,10 +887,13 @@ onUnload(() => {
|
||||
|
||||
const requestBack = () =>
|
||||
runBackGuard({
|
||||
transientOpen: discardDialogVisible.value,
|
||||
transientOpen: datePickerVisible.value || discardDialogVisible.value,
|
||||
dirty: isDirty.value,
|
||||
submitting: isSubmitting.value || isAvatarUploading.value,
|
||||
"close-transient": cancelDiscard,
|
||||
"close-transient": () => {
|
||||
if (datePickerVisible.value) return closeDatePicker();
|
||||
return cancelDiscard();
|
||||
},
|
||||
"block-submitting": () => true,
|
||||
"confirm-discard": requestDiscardConfirmation,
|
||||
});
|
||||
@@ -829,6 +908,16 @@ const optionLabel = findMemberOptionLabel;
|
||||
const selectOption = (field, options, event) => {
|
||||
updateMemberFormOption(editForm, field, options, event);
|
||||
};
|
||||
const selectSex = (event) => {
|
||||
const previousSex = editForm.sex;
|
||||
selectOption("sex", sexOptions, event);
|
||||
if (editForm.sex !== previousSex) editForm.rankId = "";
|
||||
void loadRankOptions();
|
||||
};
|
||||
const selectRank = (event) => {
|
||||
const selectedIndex = Number(event.detail.value) - 1;
|
||||
editForm.rankId = rankOptions.value[selectedIndex]?.rankId || "";
|
||||
};
|
||||
const selectBindingMode = (event) => {
|
||||
updateMemberBindingMode(editForm, event);
|
||||
fieldErrors.bindingMode = "";
|
||||
@@ -880,9 +969,19 @@ const uploadAvatar = async () => {
|
||||
if (pageActive) isAvatarUploading.value = false;
|
||||
}
|
||||
};
|
||||
const selectDate = (field, event) => {
|
||||
editForm[field] = event.detail.value || "";
|
||||
const openDatePicker = (field, title) => {
|
||||
datePickerField.value = field;
|
||||
datePickerTitle.value = title;
|
||||
datePickerVisible.value = true;
|
||||
};
|
||||
const closeDatePicker = () => {
|
||||
datePickerVisible.value = false;
|
||||
};
|
||||
const confirmDatePicker = (value) => {
|
||||
if (!datePickerField.value) return closeDatePicker();
|
||||
editForm[datePickerField.value] = value;
|
||||
fieldErrors.dates = "";
|
||||
closeDatePicker();
|
||||
};
|
||||
const validateEditForm = () => {
|
||||
fieldErrors.name = editForm.name.trim() ? "" : "请填写成员姓名";
|
||||
@@ -936,6 +1035,7 @@ const saveMember = async () => {
|
||||
? Number(editForm.generation)
|
||||
: undefined,
|
||||
generationName: editForm.generationName,
|
||||
rankId: editForm.rankId,
|
||||
fatherId: editForm.fatherId,
|
||||
motherId: editForm.motherId,
|
||||
avatarOssId: editForm.avatarOssId,
|
||||
|
||||
Reference in New Issue
Block a user