完成50%
This commit is contained in:
@@ -4,13 +4,13 @@
|
||||
class="edit-member-page"
|
||||
:class="{
|
||||
'edit-state--form': editState === 'form',
|
||||
'edit-state--success': editState === 'success',
|
||||
'edit-state--preview': editState === 'preview',
|
||||
'edit-state--error': editState === 'error',
|
||||
'edit-state--no-permission': editState === 'no-permission',
|
||||
}"
|
||||
>
|
||||
<ModulePageBackground module="tree" />
|
||||
<view class="edit-member-page__header"><PageHeader title="编辑成员" /></view>
|
||||
<view class="edit-member-page__header"><PageHeader title="编辑成员" custom-back @back="requestBack" /></view>
|
||||
<view class="edit-member-panel">
|
||||
<view v-if="editState === 'form'" class="edit-member-form">
|
||||
<text class="form-eyebrow">成员档案维护</text>
|
||||
@@ -45,7 +45,7 @@
|
||||
<text class="form-note">隐私字段只向本人和具备维护权限的家谱管理员展示。</text>
|
||||
<view class="form-action" @click="saveMember">
|
||||
<image src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png" mode="scaleToFill" />
|
||||
<text>{{ isSubmitting ? "正在保存…" : "保存资料" }}</text>
|
||||
<text>{{ isSubmitting ? "正在校验…" : "生成本地预览" }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -68,9 +68,9 @@
|
||||
cancel-text="继续编辑"
|
||||
confirm-text="放弃修改"
|
||||
show-cancel
|
||||
@close="discardDialogVisible = false"
|
||||
@cancel="discardDialogVisible = false"
|
||||
@confirm="discardAndBack"
|
||||
:close-on-mask="false"
|
||||
@cancel="cancelDiscard"
|
||||
@confirm="confirmDiscard"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
@@ -81,7 +81,13 @@ import { onBackPress, onLoad, onUnload } from "@dcloudio/uni-app";
|
||||
import AppDialog from "@/components/AppDialog.vue";
|
||||
import ModulePageBackground from "@/components/ModulePageBackground.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
import { genealogyContext } from "@/utils/genealogy-context.js";
|
||||
import { findTreeMemberPresentationFixture } from "@/data/mock.js";
|
||||
import { createDiscardConfirmation } from "@/utils/discard-confirmation.js";
|
||||
import {
|
||||
goBack,
|
||||
handleBackPress,
|
||||
runBackGuard,
|
||||
} from "@/utils/navigation.js";
|
||||
|
||||
const editState = ref("form");
|
||||
const genealogyId = ref("");
|
||||
@@ -90,54 +96,93 @@ const isSubmitting = ref(false);
|
||||
const discardDialogVisible = ref(false);
|
||||
let submitTimer = null;
|
||||
|
||||
const memberFixtures = {
|
||||
101: { id: 101, name: "汤文远", generation: 12, generationName: "文字辈", branch: "主支", birthDate: "1940-03-01", deathDate: "2012-08-16", summary: "一生敦亲睦族,参与整理家族旧谱。" },
|
||||
102: { id: 102, name: "汤正国", generation: 13, generationName: "正字辈", branch: "长房", birthDate: "1965-05-12", deathDate: "", summary: "负责长房资料核对。" },
|
||||
103: { id: 103, name: "汤正华", generation: 13, generationName: "正字辈", branch: "二房", birthDate: "1968-09-03", deathDate: "", summary: "资料仍在补充。" },
|
||||
};
|
||||
const fallbackMember = { id: "", name: "当前成员", generation: "待确认", generationName: "", branch: "待确认", birthDate: "", deathDate: "", summary: "" };
|
||||
const originalMember = ref({ ...fallbackMember });
|
||||
const originalMember = ref(null);
|
||||
const baseline = ref("");
|
||||
const editForm = reactive({ name: "", generationName: "", birthDate: "", deathDate: "", summary: "" });
|
||||
const fieldErrors = reactive({ name: "", dates: "" });
|
||||
|
||||
const formSnapshot = computed(() => JSON.stringify(editForm));
|
||||
const hasValidContext = computed(() =>
|
||||
Boolean(genealogyId.value && personId.value && originalMember.value),
|
||||
);
|
||||
const isDirty = computed(
|
||||
() => editState.value === "form" && baseline.value && formSnapshot.value !== baseline.value,
|
||||
() =>
|
||||
(editState.value === "form" || editState.value === "preview") &&
|
||||
Boolean(baseline.value) &&
|
||||
formSnapshot.value !== baseline.value,
|
||||
);
|
||||
const resultCopy = computed(() => ({
|
||||
success: { eyebrow: "成员资料已更新", title: `${editForm.name}的档案已保存`, copy: "返回成员档案后可以查看本次修改。", action: "返回成员档案" },
|
||||
error: { eyebrow: "资料未保存", title: "暂时无法保存成员档案", copy: "当前修改仍保留,可返回表单后重试。", action: "返回修改" },
|
||||
preview: { eyebrow: "本地流程预览", title: `${editForm.name}的资料已通过本地校验`, copy: "尚未提交服务器,返回成员档案后不会显示本次修改。", action: "返回成员档案(不保存)" },
|
||||
error: hasValidContext.value
|
||||
? { eyebrow: "资料未保存", title: "暂时无法保存成员档案", copy: "当前修改仍保留,可返回表单后重试。", action: "返回修改" }
|
||||
: { eyebrow: "成员入口无效", title: "没有找到要编辑的成员", copy: "请从成员档案重新进入,页面不会创建临时成员身份。", action: "返回上一页" },
|
||||
"no-permission": { eyebrow: "权限不足", title: "当前账号不能编辑这位成员", copy: "本人或具备成员维护权限的家谱管理员才能修改档案。", action: "返回成员档案" },
|
||||
}[editState.value] || {}));
|
||||
const discardConfirmation = createDiscardConfirmation((visible) => {
|
||||
discardDialogVisible.value = visible;
|
||||
});
|
||||
const requestDiscardConfirmation = discardConfirmation.request;
|
||||
const confirmDiscard = discardConfirmation.confirm;
|
||||
const cancelDiscard = discardConfirmation.cancel;
|
||||
|
||||
const loadMember = (id) => {
|
||||
const member = memberFixtures[id] || { ...fallbackMember, id, name: "待核实成员" };
|
||||
const member = findTreeMemberPresentationFixture(genealogyId.value, id);
|
||||
if (!member) return false;
|
||||
originalMember.value = { ...member };
|
||||
Object.assign(editForm, {
|
||||
name: member.name,
|
||||
generationName: member.generationName,
|
||||
birthDate: member.birthDate,
|
||||
deathDate: member.deathDate,
|
||||
summary: member.summary,
|
||||
});
|
||||
if (["privacy", "forbidden"].includes(member.status)) {
|
||||
Object.assign(editForm, {
|
||||
name: member.name,
|
||||
generationName: "",
|
||||
birthDate: "",
|
||||
deathDate: "",
|
||||
summary: "",
|
||||
});
|
||||
} else {
|
||||
Object.assign(editForm, {
|
||||
name: member.name,
|
||||
generationName: member.generationName || "",
|
||||
birthDate: member.birthDate || "",
|
||||
deathDate: member.deathDate || "",
|
||||
summary: member.summary || "",
|
||||
});
|
||||
}
|
||||
baseline.value = formSnapshot.value;
|
||||
return true;
|
||||
};
|
||||
|
||||
onLoad((query) => {
|
||||
genealogyId.value = query.genealogyId || genealogyContext.getCurrentGenealogyId() || "";
|
||||
personId.value = query.personId || "";
|
||||
if (genealogyId.value) genealogyContext.setCurrentGenealogyId(genealogyId.value);
|
||||
loadMember(personId.value);
|
||||
editState.value = query.state === "success" ? "success" : query.state === "error" ? "error" : query.state === "no-permission" ? "no-permission" : !personId.value ? "error" : "form";
|
||||
genealogyId.value = String(query.genealogyId || "");
|
||||
personId.value = String(query.personId || "");
|
||||
const loaded = Boolean(genealogyId.value && personId.value) && loadMember(personId.value);
|
||||
editState.value = !loaded
|
||||
? "error"
|
||||
: ["privacy", "forbidden"].includes(originalMember.value.status)
|
||||
? "no-permission"
|
||||
: query.state === "preview"
|
||||
? "preview"
|
||||
: query.state === "error"
|
||||
? "error"
|
||||
: "form";
|
||||
});
|
||||
onUnload(() => { if (submitTimer) clearTimeout(submitTimer); });
|
||||
onBackPress(() => {
|
||||
if (discardDialogVisible.value) { discardDialogVisible.value = false; return true; }
|
||||
if (isDirty.value) { discardDialogVisible.value = true; return true; }
|
||||
return false;
|
||||
onUnload(() => {
|
||||
const timer = submitTimer;
|
||||
submitTimer = null;
|
||||
if (timer) clearTimeout(timer);
|
||||
discardConfirmation.dispose();
|
||||
});
|
||||
|
||||
const requestBack = () =>
|
||||
runBackGuard({
|
||||
transientOpen: discardDialogVisible.value,
|
||||
dirty: isDirty.value,
|
||||
submitting: isSubmitting.value,
|
||||
"close-transient": cancelDiscard,
|
||||
"block-submitting": () => true,
|
||||
"confirm-discard": requestDiscardConfirmation,
|
||||
});
|
||||
|
||||
onBackPress((event) => handleBackPress(event, requestBack));
|
||||
|
||||
const clearError = (field) => { fieldErrors[field] = ""; };
|
||||
const selectDate = (field, event) => {
|
||||
editForm[field] = event.detail.value || "";
|
||||
@@ -150,21 +195,29 @@ const validateEditForm = () => {
|
||||
};
|
||||
const saveMember = () => {
|
||||
if (isSubmitting.value || !validateEditForm()) return;
|
||||
const submitSnapshot = Object.freeze({ ...editForm });
|
||||
isSubmitting.value = true;
|
||||
submitTimer = setTimeout(() => {
|
||||
editState.value = editForm.name.trim() === "失败" ? "error" : "success";
|
||||
if (editState.value === "success") baseline.value = formSnapshot.value;
|
||||
const timer = setTimeout(() => {
|
||||
if (submitTimer !== timer) return;
|
||||
editState.value = submitSnapshot.name.trim() === "失败" ? "error" : "preview";
|
||||
isSubmitting.value = false;
|
||||
submitTimer = null;
|
||||
}, 280);
|
||||
submitTimer = timer;
|
||||
};
|
||||
const returnToMember = async () => {
|
||||
const confirmed = isDirty.value
|
||||
? await requestDiscardConfirmation()
|
||||
: true;
|
||||
if (!confirmed) return false;
|
||||
return goBack();
|
||||
};
|
||||
const handleResultAction = () => {
|
||||
if (editState.value === "error") { editState.value = "form"; return; }
|
||||
uni.navigateBack();
|
||||
};
|
||||
const discardAndBack = () => {
|
||||
discardDialogVisible.value = false;
|
||||
uni.navigateBack();
|
||||
if (editState.value === "error" && hasValidContext.value) {
|
||||
editState.value = "form";
|
||||
return;
|
||||
}
|
||||
return returnToMember();
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user