feat(api): 完善家谱系统API客户端契约
- 实现家谱管理相关方法,包括创建、详情、概览、我的家谱和选项查询 - 添加家谱加入申请功能,支持申请、审核、取消和待审核列表操作 - 集成通知详情获取方法和通知ID安全验证机制 - 完善功德记录、谱文、相册、视频、祭祀活动的完整CRUD操作契约 - 实现家谱成员管理功能,包含成员列表、更新、移除和转让所有者操作 - 优化路径ID验证逻辑,拒绝不安全的数值ID并提供明确错误提示 - 更新测试用例以验证所有新增API方法的路径和请求体白名单机制
This commit is contained in:
+308
-35
@@ -22,8 +22,9 @@
|
||||
var currentPageNum = 1;
|
||||
var currentPageSize = 20;
|
||||
var currentPageTotal = null;
|
||||
var managementAccess = true;
|
||||
var managementAccess = false;
|
||||
var writePending = false;
|
||||
var currentUserId = '';
|
||||
|
||||
function getApi() {
|
||||
return root.GenealogyApi && root.GenealogyApi.defaultClient;
|
||||
@@ -101,8 +102,7 @@
|
||||
return Number.isInteger(number) && Number.isSafeInteger(number) ? number : undefined;
|
||||
}
|
||||
|
||||
function getPersonId(item) {
|
||||
var value = item && item.personId;
|
||||
function normalizeId(value) {
|
||||
var text;
|
||||
|
||||
if (value === undefined || value === null || value === '') return '';
|
||||
@@ -111,22 +111,52 @@
|
||||
return /^\d+$/.test(text) ? text : '';
|
||||
}
|
||||
|
||||
function getPersonId(item) {
|
||||
return normalizeId(item && item.personId);
|
||||
}
|
||||
|
||||
function formatLineageDate(value) {
|
||||
var text = trimOrUndefined(value);
|
||||
|
||||
if (!text) return undefined;
|
||||
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(text)) return text.replace('T', ' ') + ':00';
|
||||
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(text)) return text.replace('T', ' ');
|
||||
return text;
|
||||
}
|
||||
|
||||
function buildLineagePersonBody(values) {
|
||||
var source = values || {};
|
||||
var body = { name: trimOrUndefined(source.name) };
|
||||
var bindingMode = trimOrUndefined(source.bindingMode);
|
||||
var body = {
|
||||
bindingMode: bindingMode,
|
||||
name: trimOrUndefined(source.name)
|
||||
};
|
||||
var optionalFields = [
|
||||
'personNo', 'aliasName', 'sex', 'generationName', 'birthDate', 'birthLunar', 'birthPlace',
|
||||
'deathDate', 'deathLunar', 'deathPlace', 'burialPlace', 'personStatus', 'biography',
|
||||
'personNo', 'aliasName', 'sex', 'generationName', 'birthLunar', 'birthPlace',
|
||||
'deathLunar', 'deathPlace', 'burialPlace', 'personStatus', 'biography',
|
||||
'remark', 'relationName'
|
||||
];
|
||||
var idFields = ['avatarOssId', 'fatherId', 'motherId'];
|
||||
var generation = trimOrUndefined(source.generation);
|
||||
var sortOrder = trimOrUndefined(source.sortOrder);
|
||||
var birthDate = formatLineageDate(source.birthDate);
|
||||
var deathDate = formatLineageDate(source.deathDate);
|
||||
|
||||
optionalFields.forEach(function (field) {
|
||||
var value = trimOrUndefined(source[field]);
|
||||
|
||||
if (value !== undefined) body[field] = value;
|
||||
});
|
||||
idFields.forEach(function (field) {
|
||||
var value = normalizeId(source[field]);
|
||||
|
||||
if (value) body[field] = value;
|
||||
});
|
||||
if (bindingMode === 'SPECIFIED') {
|
||||
body.appUserId = normalizeId(source.appUserId) || trimOrUndefined(source.appUserId);
|
||||
}
|
||||
if (birthDate !== undefined) body.birthDate = birthDate;
|
||||
if (deathDate !== undefined) body.deathDate = deathDate;
|
||||
if (generation !== undefined) body.generation = Number(generation);
|
||||
if (sortOrder !== undefined) body.sortOrder = Number(sortOrder);
|
||||
return body;
|
||||
@@ -134,6 +164,17 @@
|
||||
|
||||
function validateLineagePersonBody(body) {
|
||||
if (!body || !body.name) return '请填写成员姓名';
|
||||
if (!body.bindingMode) return '请选择账号绑定方式';
|
||||
if (['NONE', 'SELF', 'SPECIFIED'].indexOf(body.bindingMode) === -1) return '账号绑定方式无效';
|
||||
if (body.bindingMode === 'SPECIFIED' && !normalizeId(body.appUserId)) return '指定账号绑定缺少用户选项';
|
||||
if (body.bindingMode !== 'SPECIFIED' && body.appUserId !== undefined) return '当前绑定方式不能提交指定用户';
|
||||
if (body.sex !== undefined && ['0', '1', '2'].indexOf(body.sex) === -1) return '性别选项无效';
|
||||
if (body.personStatus !== undefined && ['0', '1', '2'].indexOf(body.personStatus) === -1) return '人物状态选项无效';
|
||||
if (body.birthLunar !== undefined && ['0', '1'].indexOf(body.birthLunar) === -1) return '出生历法选项无效';
|
||||
if (body.deathLunar !== undefined && ['0', '1'].indexOf(body.deathLunar) === -1) return '逝世历法选项无效';
|
||||
if (['avatarOssId', 'fatherId', 'motherId'].some(function (field) {
|
||||
return body[field] !== undefined && !normalizeId(body[field]);
|
||||
})) return '人物关联字段无效';
|
||||
if (body.generation !== undefined && (!Number.isInteger(body.generation) || !Number.isSafeInteger(body.generation))) {
|
||||
return '世代序号必须是整数';
|
||||
}
|
||||
@@ -147,6 +188,7 @@
|
||||
var personId = getPersonId(item);
|
||||
var name = trimOrUndefined(item && item.name);
|
||||
var person;
|
||||
var invalidId = false;
|
||||
|
||||
if (!personId || !name) return null;
|
||||
person = { personId: personId, name: name };
|
||||
@@ -160,15 +202,70 @@
|
||||
});
|
||||
['appUserId', 'genealogyId', 'fatherId', 'motherId', 'avatarOssId'].forEach(function (field) {
|
||||
if (item && item[field] !== undefined && item[field] !== null) {
|
||||
if (typeof item[field] === 'number' && !Number.isSafeInteger(item[field])) return;
|
||||
person[field] = String(item[field]);
|
||||
var value = normalizeId(item[field]);
|
||||
|
||||
if (!value) {
|
||||
invalidId = true;
|
||||
return;
|
||||
}
|
||||
person[field] = value;
|
||||
}
|
||||
});
|
||||
if (invalidId) return null;
|
||||
if (toIntegerOrUndefined(item && item.generation) !== undefined) person.generation = toIntegerOrUndefined(item.generation);
|
||||
if (toIntegerOrUndefined(item && item.sortOrder) !== undefined) person.sortOrder = toIntegerOrUndefined(item.sortOrder);
|
||||
return person;
|
||||
}
|
||||
|
||||
function normalizeLineageAccess(genealogy) {
|
||||
return {
|
||||
canEditContent: Boolean(genealogy && genealogy.canEditContent === true)
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeGenerationOption(item) {
|
||||
var generation = toIntegerOrUndefined(item && item.generationNo);
|
||||
var generationName = trimOrUndefined(item && item.generationText);
|
||||
|
||||
if (!generation || !generationName) return null;
|
||||
return {
|
||||
generation: generation,
|
||||
generationName: generationName
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeGenealogyMemberOption(item) {
|
||||
var memberId = normalizeId(item && item.memberId);
|
||||
var genealogyId = normalizeId(item && item.genealogyId);
|
||||
var appUserId = normalizeId(item && item.appUserId);
|
||||
var status = trimOrUndefined(item && item.status);
|
||||
|
||||
if (!memberId || !genealogyId || !appUserId || status !== '0') return null;
|
||||
return {
|
||||
memberId: memberId,
|
||||
genealogyId: genealogyId,
|
||||
appUserId: appUserId,
|
||||
appUserNickName: String(item.appUserNickName === undefined || item.appUserNickName === null ? '' : item.appUserNickName),
|
||||
memberName: String(item.memberName === undefined || item.memberName === null ? '' : item.memberName),
|
||||
roleType: String(item.roleType === undefined || item.roleType === null ? '' : item.roleType),
|
||||
status: status
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeGenealogyMemberOptions(data) {
|
||||
if (!Array.isArray(data)) return [];
|
||||
return data.map(normalizeGenealogyMemberOption).filter(Boolean);
|
||||
}
|
||||
|
||||
function normalizeLineageBinding(person, userId) {
|
||||
var appUserId = normalizeId(person && person.appUserId);
|
||||
var normalizedUserId = normalizeId(userId);
|
||||
|
||||
if (!appUserId) return { bindingMode: 'NONE', appUserId: '' };
|
||||
if (normalizedUserId && appUserId === normalizedUserId) return { bindingMode: 'SELF', appUserId: '' };
|
||||
return { bindingMode: 'SPECIFIED', appUserId: appUserId };
|
||||
}
|
||||
|
||||
function normalizeList(data) {
|
||||
if (Array.isArray(data)) return data;
|
||||
if (data && Array.isArray(data.rows)) return data.rows;
|
||||
@@ -259,12 +356,68 @@
|
||||
function renderOptions(data) {
|
||||
var select = query('[data-lineage-person-options]');
|
||||
var people = normalizeList(data).map(normalizeLineagePerson).filter(Boolean);
|
||||
|
||||
if (!select) return;
|
||||
select.innerHTML = '<option value="">请选择当前成员</option>' + people.map(function (person) {
|
||||
var options = people.map(function (person) {
|
||||
return '<option value="' + escapeHtml(person.personId) + '">' + escapeHtml(person.name + (person.generationName ? ' · ' + person.generationName : '')) + '</option>';
|
||||
}).join('');
|
||||
|
||||
if (!select) return;
|
||||
select.innerHTML = '<option value="">请选择当前成员</option>' + options;
|
||||
select.value = selectedPersonId;
|
||||
queryAll('[data-lineage-parent-option]').forEach(function (parentSelect) {
|
||||
var emptyLabel = parentSelect.getAttribute('data-empty-label') || '请选择人物';
|
||||
|
||||
parentSelect.innerHTML = '<option value="">' + escapeHtml(emptyLabel) + '</option>' + options;
|
||||
});
|
||||
}
|
||||
|
||||
function renderGenerationOptions(data) {
|
||||
var select = query('[data-lineage-generation]');
|
||||
var filter = query('[data-lineage-generation-filter]');
|
||||
var selectedGeneration = select ? select.value : '';
|
||||
var selectedFilter = filter ? filter.value : '';
|
||||
var options = normalizeList(data).map(normalizeGenerationOption).filter(Boolean);
|
||||
var optionHtml = options.map(function (option) {
|
||||
return '<option value="' + escapeHtml(option.generation) + '" data-generation-name="' + escapeHtml(option.generationName) + '">' +
|
||||
escapeHtml('第 ' + option.generation + ' 世 · ' + option.generationName) + '</option>';
|
||||
}).join('');
|
||||
|
||||
if (select) {
|
||||
select.innerHTML = '<option value="">请选择世代</option>' + optionHtml;
|
||||
select.value = selectedGeneration;
|
||||
}
|
||||
if (filter) {
|
||||
filter.innerHTML = '<option value="">全部世代</option>' + optionHtml;
|
||||
filter.value = selectedFilter;
|
||||
}
|
||||
}
|
||||
|
||||
function updateBindingFields() {
|
||||
var bindingMode = query('[name="bindingMode"]');
|
||||
var memberSelect = query('[data-lineage-member-options]');
|
||||
var specified = Boolean(bindingMode && bindingMode.value === 'SPECIFIED');
|
||||
|
||||
if (!memberSelect) return;
|
||||
memberSelect.hidden = !specified;
|
||||
memberSelect.required = specified;
|
||||
if (!specified) memberSelect.value = '';
|
||||
}
|
||||
|
||||
function renderGenealogyMemberOptions(data) {
|
||||
var select = query('[data-lineage-member-options]');
|
||||
var selectedValue = select ? select.value : '';
|
||||
var options = normalizeGenealogyMemberOptions(data).filter(function (option) {
|
||||
return option.appUserId !== currentUserId;
|
||||
});
|
||||
|
||||
if (!select) return options;
|
||||
select.innerHTML = '<option value="">请选择已绑定账号的家谱成员</option>' + options.map(function (option) {
|
||||
var label = option.memberName || option.appUserNickName || '家谱成员';
|
||||
|
||||
return '<option value="' + escapeHtml(option.appUserId) + '">' + escapeHtml(label) + '</option>';
|
||||
}).join('');
|
||||
select.value = selectedValue;
|
||||
updateBindingFields();
|
||||
return options;
|
||||
}
|
||||
|
||||
function renderListSummary(data) {
|
||||
@@ -281,7 +434,7 @@
|
||||
var previous = query('[data-lineage-page-action="previous"]');
|
||||
var next = query('[data-lineage-page-action="next"]');
|
||||
var status = query('[data-lineage-page-status]');
|
||||
var disabled = !managementAccess || writePending;
|
||||
var disabled = writePending;
|
||||
|
||||
if (!container) return;
|
||||
if (currentPageTotal === null) {
|
||||
@@ -294,6 +447,10 @@
|
||||
if (status) status.textContent = '第 ' + currentPageNum + ' 页,共 ' + currentPageTotal + ' 人';
|
||||
}
|
||||
|
||||
function canUseLineagePagination(pending) {
|
||||
return !Boolean(pending);
|
||||
}
|
||||
|
||||
function renderPagination(data) {
|
||||
var total = data && Number(data.total);
|
||||
|
||||
@@ -305,6 +462,7 @@
|
||||
var container = query('[data-lineage-detail]');
|
||||
var person = normalizeLineagePerson(data);
|
||||
var values;
|
||||
var actions = '';
|
||||
|
||||
if (!container) return;
|
||||
if (!person) {
|
||||
@@ -314,17 +472,30 @@
|
||||
selectedPersonId = person.personId;
|
||||
peopleById[person.personId] = person;
|
||||
values = [
|
||||
person.sex ? '性别:' + person.sex : '',
|
||||
person.sex !== undefined ? '性别:' + ({ '0': '男', '1': '女', '2': '未知' }[person.sex] || person.sex) : '',
|
||||
person.generation !== undefined ? '世代:' + person.generation : '',
|
||||
person.generationName ? '字辈:' + person.generationName : '',
|
||||
person.personNo ? '人物编号:' + person.personNo : '',
|
||||
person.aliasName ? '别名:' + person.aliasName : '',
|
||||
person.fatherName ? '父亲:' + person.fatherName : '',
|
||||
person.motherName ? '母亲:' + person.motherName : '',
|
||||
person.spouseNames ? '配偶:' + person.spouseNames : '',
|
||||
person.appUserNickName ? '绑定账号:' + person.appUserNickName : '',
|
||||
person.birthDate ? '出生:' + person.birthDate : '',
|
||||
person.birthPlace ? '出生地:' + person.birthPlace : '',
|
||||
person.deathDate ? '逝世:' + person.deathDate : '',
|
||||
person.biography ? '简介:' + person.biography : ''
|
||||
person.deathPlace ? '逝世地:' + person.deathPlace : '',
|
||||
person.burialPlace ? '安葬地:' + person.burialPlace : '',
|
||||
person.personStatus !== undefined ? '人物状态:' + ({ '0': '健在', '1': '已故', '2': '未知' }[person.personStatus] || person.personStatus) : '',
|
||||
person.biography ? '简介:' + person.biography : '',
|
||||
person.remark ? '备注:' + person.remark : ''
|
||||
].filter(Boolean);
|
||||
if (managementAccess) {
|
||||
actions = '<div class="row-actions"><button class="pill" type="button" data-lineage-edit="' + escapeHtml(person.personId) + '">编辑</button>' +
|
||||
'<button class="pill is-danger" type="button" data-lineage-disable="' + escapeHtml(person.personId) + '">停用</button></div>';
|
||||
}
|
||||
container.innerHTML = '<div class="module-row"><div><h3>' + escapeHtml(person.name) + '</h3><p>' + escapeHtml(values.join(' · ') || '暂无更多资料') + '</p></div>' +
|
||||
'<div class="row-actions"><button class="pill" type="button" data-lineage-edit="' + escapeHtml(person.personId) + '">编辑</button>' +
|
||||
'<button class="pill is-danger" type="button" data-lineage-disable="' + escapeHtml(person.personId) + '">停用</button></div></div>';
|
||||
actions + '</div>';
|
||||
renderLineageList(Object.keys(peopleById).map(function (id) { return peopleById[id]; }));
|
||||
if (query('[data-lineage-person-options]')) query('[data-lineage-person-options]').value = person.personId;
|
||||
refreshControls();
|
||||
@@ -377,6 +548,7 @@
|
||||
});
|
||||
if (query('[data-lineage-list-summary]')) query('[data-lineage-list-summary]').textContent = '';
|
||||
currentPageTotal = null;
|
||||
setLineageEnabled(false);
|
||||
updatePaginationControls();
|
||||
}
|
||||
|
||||
@@ -391,10 +563,16 @@
|
||||
}
|
||||
|
||||
function refreshControls() {
|
||||
var disabled = !managementAccess || writePending;
|
||||
var writeDisabled = !managementAccess || writePending;
|
||||
|
||||
queryAll('[data-lineage-relation], [data-lineage-search], [data-lineage-form] button, [data-lineage-person-options], [data-lineage-edit], [data-lineage-disable]').forEach(function (control) {
|
||||
control.disabled = disabled;
|
||||
queryAll('[data-lineage-management]').forEach(function (element) {
|
||||
element.hidden = !managementAccess;
|
||||
});
|
||||
queryAll('[data-lineage-relation], [data-lineage-form] button, [data-lineage-form] input, [data-lineage-form] select, [data-lineage-form] textarea, [data-lineage-edit], [data-lineage-disable]').forEach(function (control) {
|
||||
control.disabled = writeDisabled;
|
||||
});
|
||||
queryAll('[data-lineage-search], [data-lineage-person-options]').forEach(function (control) {
|
||||
control.disabled = writePending;
|
||||
});
|
||||
updatePaginationControls();
|
||||
}
|
||||
@@ -427,10 +605,38 @@
|
||||
return input ? input.value : '';
|
||||
}
|
||||
|
||||
function buildLineagePageQuery(values, pageNum, pageSize) {
|
||||
var source = values || {};
|
||||
var queryValues = {
|
||||
pageNum: Number(pageNum),
|
||||
pageSize: Number(pageSize)
|
||||
};
|
||||
var keyword = trimOrUndefined(source.keyword);
|
||||
var generation = toIntegerOrUndefined(source.generation);
|
||||
var personStatus = trimOrUndefined(source.personStatus);
|
||||
|
||||
if (keyword !== undefined) queryValues.keyword = keyword;
|
||||
if (generation !== undefined && generation > 0) queryValues.generation = generation;
|
||||
if (['0', '1', '2'].indexOf(personStatus) !== -1) queryValues.personStatus = personStatus;
|
||||
return queryValues;
|
||||
}
|
||||
|
||||
function getCurrentFilters(keyword) {
|
||||
var generation = query('[data-lineage-generation-filter]');
|
||||
var status = query('[data-lineage-status-filter]');
|
||||
|
||||
return {
|
||||
keyword: keyword,
|
||||
generation: generation ? generation.value : '',
|
||||
personStatus: status ? status.value : ''
|
||||
};
|
||||
}
|
||||
|
||||
async function loadLineage(keyword, pageNum) {
|
||||
var api = getApi();
|
||||
var genealogyId;
|
||||
var results;
|
||||
var access;
|
||||
var searchKeyword = trimOrUndefined(keyword);
|
||||
var requestedPage = Number(pageNum);
|
||||
|
||||
@@ -441,27 +647,41 @@
|
||||
syncGenealogyLinks(genealogyId);
|
||||
try {
|
||||
results = await Promise.all([
|
||||
api.genealogyDetail(genealogyId),
|
||||
api.currentProfile(),
|
||||
api.lineageTree(genealogyId),
|
||||
api.lineagePersons(genealogyId),
|
||||
api.lineagePersonsPage(genealogyId, {
|
||||
pageNum: currentPageNum,
|
||||
pageSize: currentPageSize,
|
||||
keyword: searchKeyword
|
||||
}),
|
||||
api.lineagePersonOptions(genealogyId)
|
||||
api.lineagePersonsPage(genealogyId, buildLineagePageQuery(
|
||||
getCurrentFilters(searchKeyword),
|
||||
currentPageNum,
|
||||
currentPageSize
|
||||
)),
|
||||
api.lineagePersonOptions(genealogyId),
|
||||
api.generationPoems(genealogyId)
|
||||
]);
|
||||
renderTree(results[0]);
|
||||
renderListSummary(results[1]);
|
||||
renderLineageList(results[2]);
|
||||
renderPagination(results[2]);
|
||||
renderOptions(results[3]);
|
||||
setLineageEnabled(true);
|
||||
access = normalizeLineageAccess(results[0]);
|
||||
currentUserId = normalizeId(results[1] && results[1].userId);
|
||||
setLineageEnabled(access.canEditContent);
|
||||
renderTree(results[2]);
|
||||
renderListSummary(results[3]);
|
||||
renderLineageList(results[4]);
|
||||
renderPagination(results[4]);
|
||||
renderOptions(results[5]);
|
||||
renderGenerationOptions(results[6]);
|
||||
if (access.canEditContent) {
|
||||
renderGenealogyMemberOptions(await api.genealogyMemberOptions(genealogyId));
|
||||
}
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
if (isForbidden(error)) {
|
||||
renderForbiddenState();
|
||||
return;
|
||||
}
|
||||
['[data-lineage-tree]', '[data-lineage-list]'].forEach(function (selector) {
|
||||
var container = query(selector);
|
||||
|
||||
if (container) container.innerHTML = '<div class="api-empty">世系人物加载失败,请稍后重试</div>';
|
||||
});
|
||||
showMessage(error.message || '世系人物加载失败');
|
||||
}
|
||||
}
|
||||
@@ -496,34 +716,63 @@
|
||||
}
|
||||
relationMode = mode;
|
||||
editingPersonId = '';
|
||||
setRelationFieldVisibility(mode === 'spouses');
|
||||
if (submitButton) submitButton.textContent = '新增' + relationLabel(mode);
|
||||
setFormStatus('当前将为“' + person.name + '”新增' + relationLabel(mode));
|
||||
}
|
||||
|
||||
function toLocalDateTime(value) {
|
||||
var text = trimOrUndefined(value);
|
||||
|
||||
return text ? text.slice(0, 16).replace(' ', 'T') : '';
|
||||
}
|
||||
|
||||
function setRelationFieldVisibility(visible) {
|
||||
var field = query('[data-lineage-spouse-field]');
|
||||
|
||||
if (field) field.hidden = !visible;
|
||||
}
|
||||
|
||||
function fillForm(person) {
|
||||
var form = query('[data-lineage-form]');
|
||||
var values;
|
||||
var submitButton;
|
||||
var binding;
|
||||
|
||||
if (!form || !person) return;
|
||||
binding = normalizeLineageBinding(person, currentUserId);
|
||||
values = {
|
||||
bindingMode: binding.bindingMode,
|
||||
appUserId: binding.appUserId,
|
||||
avatarOssId: person.avatarOssId,
|
||||
name: person.name,
|
||||
sex: person.sex,
|
||||
generation: person.generation,
|
||||
generationName: person.generationName,
|
||||
fatherId: person.fatherId,
|
||||
motherId: person.motherId,
|
||||
personNo: person.personNo,
|
||||
aliasName: person.aliasName,
|
||||
birthDate: person.birthDate ? person.birthDate.slice(0, 10) : '',
|
||||
deathDate: person.deathDate ? person.deathDate.slice(0, 10) : '',
|
||||
birthDate: toLocalDateTime(person.birthDate),
|
||||
birthLunar: person.birthLunar,
|
||||
birthPlace: person.birthPlace,
|
||||
deathDate: toLocalDateTime(person.deathDate),
|
||||
deathLunar: person.deathLunar,
|
||||
deathPlace: person.deathPlace,
|
||||
burialPlace: person.burialPlace,
|
||||
personStatus: person.personStatus,
|
||||
sortOrder: person.sortOrder,
|
||||
relationName: person.relationName,
|
||||
biography: person.biography
|
||||
biography: person.biography,
|
||||
remark: person.remark
|
||||
};
|
||||
queryAll('[name]', form).forEach(function (field) {
|
||||
field.value = values[field.name] === undefined || values[field.name] === null ? '' : values[field.name];
|
||||
});
|
||||
updateBindingFields();
|
||||
relationMode = '';
|
||||
editingPersonId = person.personId;
|
||||
setRelationFieldVisibility(false);
|
||||
submitButton = query('[data-lineage-form] button[type="submit"]');
|
||||
if (submitButton) submitButton.textContent = '保存修改';
|
||||
setFormStatus('正在编辑“' + person.name + '”');
|
||||
@@ -534,8 +783,10 @@
|
||||
|
||||
relationMode = '';
|
||||
editingPersonId = '';
|
||||
setRelationFieldVisibility(false);
|
||||
if (submitButton) submitButton.textContent = '保存成员';
|
||||
setFormStatus('');
|
||||
if (root.setTimeout) root.setTimeout(updateBindingFields, 0);
|
||||
}
|
||||
|
||||
async function submitPerson(form) {
|
||||
@@ -627,8 +878,23 @@
|
||||
});
|
||||
documentRef.addEventListener('change', function (event) {
|
||||
var select = event.target.closest('[data-lineage-person-options]');
|
||||
var generationSelect = event.target.closest('[data-lineage-generation]');
|
||||
var bindingSelect = event.target.closest('[name="bindingMode"]');
|
||||
var selectedOption;
|
||||
var generationName;
|
||||
var appUserId;
|
||||
|
||||
if (select && select.value) loadPersonDetail(select.value);
|
||||
if (generationSelect) {
|
||||
selectedOption = generationSelect.options[generationSelect.selectedIndex];
|
||||
generationName = query('[name="generationName"]', generationSelect.form);
|
||||
if (generationName) generationName.value = selectedOption ? selectedOption.getAttribute('data-generation-name') || '' : '';
|
||||
}
|
||||
if (bindingSelect) {
|
||||
appUserId = query('[name="appUserId"]', bindingSelect.form);
|
||||
if (bindingSelect.value !== 'SPECIFIED' && appUserId) appUserId.value = '';
|
||||
updateBindingFields();
|
||||
}
|
||||
});
|
||||
documentRef.addEventListener('click', function (event) {
|
||||
var target = event.target;
|
||||
@@ -645,7 +911,7 @@
|
||||
}
|
||||
if (pageButton) {
|
||||
event.preventDefault();
|
||||
if (!managementAccess || writePending) return;
|
||||
if (!canUseLineagePagination(writePending)) return;
|
||||
if (pageButton.getAttribute('data-lineage-page-action') === 'previous' && currentPageNum > 1) {
|
||||
loadLineage(getCurrentKeyword(), currentPageNum - 1);
|
||||
}
|
||||
@@ -688,6 +954,13 @@
|
||||
buildLineagePersonBody: buildLineagePersonBody,
|
||||
validateLineagePersonBody: validateLineagePersonBody,
|
||||
normalizeLineagePerson: normalizeLineagePerson,
|
||||
normalizeLineageAccess: normalizeLineageAccess,
|
||||
canUseLineagePagination: canUseLineagePagination,
|
||||
normalizeGenerationOption: normalizeGenerationOption,
|
||||
normalizeGenealogyMemberOption: normalizeGenealogyMemberOption,
|
||||
normalizeGenealogyMemberOptions: normalizeGenealogyMemberOptions,
|
||||
normalizeLineageBinding: normalizeLineageBinding,
|
||||
buildLineagePageQuery: buildLineagePageQuery,
|
||||
normalizeList: normalizeList,
|
||||
relationLabel: relationLabel,
|
||||
shouldRedirectToLogin: shouldRedirectToLogin,
|
||||
|
||||
Reference in New Issue
Block a user