This commit is contained in:
rain
2026-07-24 18:03:02 +08:00
parent c7f278fe79
commit ec8486b035
86 changed files with 7943 additions and 1841 deletions
+96 -11
View File
@@ -26,7 +26,7 @@
</view>
<view class="form-field">
<text>姓名</text>
<text><text class="required-mark">*</text>姓名</text>
<input
v-model="addForm.name"
maxlength="20"
@@ -44,25 +44,70 @@
@change="selectRelation"
>
<view class="form-field form-field--picker">
<text>与本人关系</text>
<text><text class="required-mark">*</text>与本人关系</text>
<text>{{ addForm.relation || "请选择亲属关系" }}</text>
</view>
</picker>
<text v-if="fieldErrors.relation" class="field-error">{{ fieldErrors.relation }}</text>
<view class="form-field">
<text>别名</text>
<input v-model="addForm.aliasName" maxlength="40" placeholder="按家谱记载填写" placeholder-class="form-placeholder" />
</view>
<view class="form-field">
<text>字辈</text>
<input v-model="addForm.generationName" maxlength="12" placeholder="按家谱记载填写" placeholder-class="form-placeholder" />
</view>
<picker mode="date" :value="addForm.birthDate" @change="selectBirthDate">
<view class="form-field form-field--picker">
<text>出生日期</text><text>{{ addForm.birthDate || "选填" }}</text>
<text>出生日期</text><text>{{ addForm.birthDate || "请选择" }}</text>
</view>
</picker>
<view class="form-field">
<text>出生农历</text>
<input v-model="addForm.birthLunar" maxlength="40" placeholder="按家谱记载填写" placeholder-class="form-placeholder" />
</view>
<view class="form-field">
<text>出生地</text>
<input v-model="addForm.birthPlace" maxlength="60" placeholder="按家谱记载填写" placeholder-class="form-placeholder" />
</view>
<picker mode="date" :value="addForm.deathDate" @change="selectDeathDate">
<view class="form-field form-field--picker">
<text>逝世日期</text><text>{{ addForm.deathDate || "请选择" }}</text>
</view>
</picker>
<view class="form-field">
<text>逝世农历</text>
<input v-model="addForm.deathLunar" maxlength="40" placeholder="按家谱记载填写" placeholder-class="form-placeholder" />
</view>
<view class="form-field">
<text>逝世地</text>
<input v-model="addForm.deathPlace" maxlength="60" placeholder="按家谱记载填写" placeholder-class="form-placeholder" />
</view>
<view class="form-field">
<text>安葬地</text>
<input v-model="addForm.burialPlace" maxlength="60" placeholder="按家谱记载填写" placeholder-class="form-placeholder" />
</view>
<view class="form-field form-field--summary">
<text>简要说明</text>
<text>人物简介</text>
<textarea
v-model="addForm.summary"
v-model="addForm.biography"
auto-height
maxlength="500"
placeholder="按家谱记载填写"
placeholder-class="form-placeholder"
/>
</view>
<view class="form-field form-field--summary">
<text>备注</text>
<textarea
v-model="addForm.remark"
auto-height
maxlength="200"
placeholder="选填:字辈、祖居地或身份说明"
placeholder="补充说明"
placeholder-class="form-placeholder"
/>
</view>
@@ -136,7 +181,21 @@ const relationIntents = Object.freeze({
DAUGHTER: { label: "女儿" },
});
const genericRelationTypes = Object.freeze(["FATHER", "MOTHER", "SPOUSE", "SIBLING", "SON", "DAUGHTER"]);
const addForm = reactive({ name: "", relation: "", birthDate: "", summary: "" });
const addForm = reactive({
name: "",
relation: "",
aliasName: "",
generationName: "",
birthDate: "",
birthLunar: "",
birthPlace: "",
deathDate: "",
deathLunar: "",
deathPlace: "",
burialPlace: "",
biography: "",
remark: "",
});
const fieldErrors = reactive({ name: "", relation: "" });
const isFirstMember = computed(() => mode.value === "first");
@@ -161,13 +220,13 @@ const formCopy = computed(() =>
: "先确认新成员与当前成员的关系,再填写可核实的身份信息。",
);
const formNote = computed(() =>
"本次只提交姓名、出生日期和人物简介;性别编码、头像和同辈排行不在当前写入范围。",
"红色 * 为必填项,其余内容可按家谱记载补充。",
);
const resultCopy = computed(() => {
if (hasValidContext.value) {
return {
eyebrow: "保存失败",
title: `${relationLabel.value}尚未保存`,
title: `${isFirstMember.value ? "首位成员" : relationLabel.value}尚未保存`,
copy: errorMessage.value || "服务未确认本次写入,请检查填写后重试。",
action: "返回修改",
};
@@ -255,6 +314,7 @@ const selectRelation = (event) => {
clearError("relation");
};
const selectBirthDate = (event) => { addForm.birthDate = event.detail.value || ""; };
const selectDeathDate = (event) => { addForm.deathDate = event.detail.value || ""; };
const validateAddForm = () => {
fieldErrors.name = addForm.name.trim() ? "" : "请填写成员姓名";
fieldErrors.relation = isFirstMember.value || addForm.relation ? "" : "请选择与当前成员的关系";
@@ -266,8 +326,18 @@ const submitAdd = async () => {
try {
const payload = {
name: addForm.name,
aliasName: addForm.aliasName,
generationName: addForm.generationName,
birthDate: addForm.birthDate,
biography: addForm.summary,
birthLunar: addForm.birthLunar,
birthPlace: addForm.birthPlace,
deathDate: addForm.deathDate,
deathLunar: addForm.deathLunar,
deathPlace: addForm.deathPlace,
burialPlace: addForm.burialPlace,
biography: addForm.biography,
remark: addForm.remark,
...(isFirstMember.value ? { generation: 1 } : {}),
...(isFirstMember.value ? {} : { relationName: relationLabel.value }),
};
if (isFirstMember.value) {
@@ -278,7 +348,21 @@ const submitAdd = async () => {
: genericRelationTypes[relationOptions.value.indexOf(addForm.relation)];
await appApi.createRelatedPerson(genealogyId.value, personId.value, type, payload, { requestController: addRequestController });
}
Object.assign(addForm, { name: "", relation: "", birthDate: "", summary: "" });
Object.assign(addForm, {
name: "",
relation: "",
aliasName: "",
generationName: "",
birthDate: "",
birthLunar: "",
birthPlace: "",
deathDate: "",
deathLunar: "",
deathPlace: "",
burialPlace: "",
biography: "",
remark: "",
});
await returnTo("T01", { genealogyId: genealogyId.value });
} catch (error) {
if (isRequestCancelled(error)) return;
@@ -310,6 +394,7 @@ const returnToTree = async () => {
.member-context, .form-field { @include adaptive.adaptive-tree-field; display: grid; grid-template-columns: auto minmax(0, 1fr); min-height: 78rpx; align-items: center; gap: 20rpx; margin-top: 14rpx; padding: 12rpx 22rpx; }
.member-context text:first-child, .form-field > text:first-child { color: $ink; font-size: 24rpx; font-weight: 700; }
.member-context text:last-child, .form-field > text:last-child, .form-field input, .form-field textarea { min-width: 0; color: $ink; font-size: 24rpx; line-height: 1.45; text-align: right; }
.required-mark { display: inline-block; margin-right: 4rpx; color: $brand-red; font-size: 22rpx; line-height: 1; transform: translateY(-2rpx); }
.form-field textarea { width: auto; min-height: 54rpx; text-align: left; }
.form-field--summary { align-items: start; }
.form-placeholder { color: #a79884; }
+1 -1
View File
@@ -12,7 +12,7 @@
<ModulePageBackground module="tree" />
<view class="directory-page__header"><PageHeader title="成员目录" /></view>
<view v-if="hasValidContext" class="directory-context">
<text class="directory-context__name">汤氏家谱</text>
<text class="directory-context__name">当前家谱</text>
<text class="directory-context__meta"
>已加载 {{ members.length }} / {{ total }} 位成员</text
>
+4 -5
View File
@@ -71,10 +71,10 @@ const states = {
},
available: {
eyebrow: "人物状态",
title: "当前状态已由服务端返回",
copy: "页面只展示人物详情中的原始状态值,不把未声明的字典值解释成隐私、纪念或访问限制。",
title: "暂无法展示状态说明",
copy: "服务端返回了状态字段,但未提供可读名称或说明;本页不会向家人展示内部状态值。",
guideTitle: "当前合同范围",
guides: ["人物状态值来自 personStatus 字段", "状态展示文案需要后端提供字典 owner", "当前页不执行停用或任何状态写入"],
guides: ["状态由服务端维护", "状态展示需要后端提供可读字典", "当前页不执行停用或任何状态写入"],
action: "返回成员档案",
},
error: {
@@ -91,8 +91,7 @@ const pageTitle = computed(() => "成员状态");
const hasValidContext = computed(() => Boolean(genealogyId.value && personId.value));
const memberIdentityCopy = computed(() => {
if (!member.value) return "";
const status = member.value.personStatus || "未填写";
return `${member.value.name} · 第 ${member.value.generation} 世 · 状态值 ${status}`;
return `${member.value.name} · 第 ${member.value.generation}`;
});
const loadMember = async () => {