// Embedded in native JNPF form events. Native forms own persistence and history. (function createErrataRevisionRuntime() { const table = 'kanwu_chuli_mingxi'; const auditInterface = '1f7b38dee4cec69f0ad88afc2fcb84e3'; const requestInterface = '012e85618f1f4a35a1c21bea394c8ad3'; const sourceFields = ['kanwu_zixiang_id', 'kanwu_shenqing_id', 'wenjian_id', 'banben_id', 'wenjian_bianhao', 'wenjian_mingcheng', 'banbenhao', 'kanwu_weizhi', 'kanwu_neirong', 'xiugai_jianyi', 'kanwu_yuanyin', 'fujian', 'shifou_yichuli']; const text = value => String(value ?? '').trim(); function fail(message) { throw new Error(message); } function parseRows(value) { let rows = value; if (typeof value === 'string') { try { rows = JSON.parse(value); } catch { fail('勘误数据格式错误,请重新加载'); } } if (!Array.isArray(rows)) fail('勘误数据未正确返回,请重新加载'); const seen = new Set(); return rows.map(row => { if (!row || !text(row.kanwu_zixiang_id) || !text(row.kanwu_shenqing_id) || !text(row.wenjian_id)) { fail('勘误来源不完整,请联系管理员'); } if (seen.has(row.kanwu_zixiang_id)) fail('勘误来源重复,请联系管理员'); seen.add(row.kanwu_zixiang_id); if (!Array.isArray(row.fujian)) fail('勘误附件格式错误,请联系管理员'); return Object.fromEntries(sourceFields.map(key => [key, row[key] ?? ''])); }); } function canonical(value) { if (Array.isArray(value)) return value.map(canonical); if (value && typeof value === 'object') return Object.fromEntries(Object.keys(value).sort().map(key => [key, canonical(value[key])])); return value; } const sameSource = (a, b) => sourceFields.every(key => JSON.stringify(canonical(a[key] ?? '')) === JSON.stringify(canonical(b[key] ?? ''))); function mergeRows(current, incoming) { const old = new Map((Array.isArray(current) ? current : []).map(row => [row.kanwu_zixiang_id, row])); return incoming.map(source => { const previous = old.get(source.kanwu_zixiang_id); // Changed source text requires a fresh decision; source ids are never child primary keys. if (previous && sameSource(previous, source)) return { ...previous, ...source }; return { ...source, ...(previous?.id ? { id: previous.id } : {}), ...(previous?.f_id ? { f_id: previous.f_id } : {}), chuli_jielun: '', chuli_yuanyin: '', chuli_ren_id: '', chuli_shijian: null }; }); } async function fetchSource(args, interfaceId, idField, id) { const response = await args.onlineUtils.request('/api/system/DataInterface/' + interfaceId + '/Actions/InfoByIds', 'post', { ids: [id], interfaceId, paramList: [{ field: 'search_val', defaultValue: '' }], propsValue: idField, relationField: 'wenjian_bianhao', }); if (!Array.isArray(response?.data)) fail('勘误查询失败,请重新加载后提交'); const matches = response.data.filter(row => text(row[idField]) === id); if (matches.length !== 1) fail('修订来源已失效,无法核对勘误'); return matches[0]; } function reminder(rows) { return rows.length ? '是' : '否'; } function auditSourceChange(args) { if (!args.data?.xiuding_shenqing_zixiang_id) { args.setFormData(table, []); return; } try { args.setFormData(table, mergeRows([], parseRows(args.data.kanwu_mingxi))); } catch (error) { args.setFormData(table, []); args.onlineUtils.toast(error.message, 'warning'); } } function requestSourceChange(args) { try { const value = args.data?.wenjian_id ? reminder(parseRows(args.data.kanwu_mingxi)) : ''; args.setFormData('xiuding_shenqing_zixiang.kanwu_tixing', value, args.rowIndex); } catch (error) { args.setFormData('xiuding_shenqing_zixiang.kanwu_tixing', '勘误读取失败,请重新选择文件', args.rowIndex); args.onlineUtils.toast(error.message, 'warning'); } } async function beforeAuditSubmit(args) { const id = text(args.formData.xiuding_shenqing_zixiang_id); if (!id) fail('请选择修订申请明细'); const source = await fetchSource(args, auditInterface, 'xiuding_shenqing_zixiang_id', id); if (text(args.formData.xiuding_shenqing_zixiang_id) !== id) fail('修订来源已切换,请重新提交'); if (text(source.wenjian_id) !== text(args.formData.wenjian_id) || text(source.yuan_wenjian_banben_id) !== text(args.formData.yuan_wenjian_banben_id)) fail('修订文件或来源版本不一致,请重新选择'); const incoming = parseRows(source.kanwu_mingxi); const current = Array.isArray(args.formData[table]) ? args.formData[table] : []; const next = mergeRows(current, incoming); const changed = current.length !== incoming.length || current.some((row, i) => !incoming[i] || !sameSource(row, incoming[i])); args.setFormData(table, next); // Restore deleted rows and surface newly approved or changed notes before allowing submission. if (changed) fail('已刷新勘误列表,请逐条核对并填写处理方式、原因后重新提交'); for (let i = 0; i < next.length; i++) { const row = next[i]; if (!['yixiugai_queren', 'bucaina'].includes(row.chuli_jielun) || !text(row.chuli_yuanyin)) { fail('第 ' + (i + 1) + ' 条勘误请选择“已修改确认”或“不采纳”,并说明原因'); } if (!text(row.chuli_ren_id) || !row.chuli_shijian) fail('第 ' + (i + 1) + ' 条勘误缺少处理留痕,请重新填写处理方式或原因'); } } async function beforeRequestSubmit(args) { const rows = args.formData.xiuding_shenqing_zixiang || []; const selection = JSON.stringify(rows.map(row => [row.wenjian_id, row.yuan_wenjian_banben_id])); const values = await Promise.all(rows.map(async row => { const source = await fetchSource(args, requestInterface, 'wenjian_id', text(row.wenjian_id)); if (text(source.yuan_wenjian_banben_id) !== text(row.yuan_wenjian_banben_id)) fail('文件当前版本已变化,请重新选择'); return reminder(parseRows(source.kanwu_mingxi)); })); if (JSON.stringify((args.formData.xiuding_shenqing_zixiang || []).map(row => [row.wenjian_id, row.yuan_wenjian_banben_id])) !== selection) { fail('修订文件清单已变化,请重新提交'); } let changed = false; values.forEach((value, i) => { if (text(rows[i].kanwu_tixing) !== value) changed = true; args.setFormData('xiuding_shenqing_zixiang.kanwu_tixing', value, i); }); if (changed) fail('已更新“是否需要勘误”,请核对后重新提交'); } function decisionChange(args) { const row = args.formData[table]?.[args.rowIndex]; if (!row) return; const userId = args.onlineUtils.getUserInfo()?.userId; args.setFormData(table + '.chuli_ren_id', userId || '', args.rowIndex); args.setFormData(table + '.chuli_shijian', userId ? Date.now() : null, args.rowIndex); } // Opening a saved record must display its historical snapshot without rewriting it. async function auditOnLoad(args) { if (args.formData.id || !text(args.formData.xiuding_shenqing_zixiang_id)) return; const id = text(args.formData.xiuding_shenqing_zixiang_id); try { const source = await fetchSource(args, auditInterface, 'xiuding_shenqing_zixiang_id', id); if (text(args.formData.xiuding_shenqing_zixiang_id) === id) { args.setFormData(table, mergeRows(args.formData[table], parseRows(source.kanwu_mingxi))); } } catch (error) { args.onlineUtils.toast(error.message || '勘误加载失败,请重新选择文件', 'warning'); } } return { parseRows, mergeRows, reminder, auditSourceChange, requestSourceChange, beforeAuditSubmit, beforeRequestSubmit, decisionChange, auditOnLoad }; })