# -*- coding: utf-8 -*- """修复 demo-B2:无返回值写端点(data=null)在 tryApi(...) != null 判定下静默失败。 方案:新增 okApi(成功 true / 失败 false + err toast),把「无返回值写端点」的判定从 `await tryApi(step, fn) != null` 换成 `await okApi(step, fn)`。 card/save(返回 id)等有返回值端点保持 tryApi。 """ import io import sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') PATH = r'd:\code\crm-backend-matt\.scratch\opportunity-e2e\demo\index.html' txt = open(PATH, encoding='utf-8').read() ANCHOR = """async function tryApi(step, fn, silent) { try { return await fn(); } catch (e) { if (!silent) toast(`[${step}] ${e.message}`, 'err'); console.warn(step, e.raw || e); return null; } }""" OKAPI = ANCHOR + """ /* okApi:无返回值写端点(data=null)专用——「不抛错即成功」,修复 demo-B2 */ async function okApi(step, fn) { try { await fn(); return true; } catch (e) { toast(`[${step}] ${e.message}`, 'err'); console.warn(step, e.raw || e); return false; } }""" PAIRS = [ # doTransition(claim/resume) ("""if (await tryApi(act, () => api('POST', `/api/opportunity/${act}`, { form: { id: S.oppId } })) != null) {""", """if (await okApi(act, () => api('POST', `/api/opportunity/${act}`, { form: { id: S.oppId } }))) {"""), # dlgAssign ("""if (await tryApi('assign', () => api('POST', '/api/opportunity/assign', { form: { id: S.oppId, userId: v('userId') } })) != null) {""", """if (await okApi('assign', () => api('POST', '/api/opportunity/assign', { form: { id: S.oppId, userId: v('userId') } }))) {"""), # dlgPause ("""if (await tryApi('pause', () => api('POST', '/api/opportunity/pause', { form })) != null) {""", """if (await okApi('pause', () => api('POST', '/api/opportunity/pause', { form }))) {"""), # dlgRelease ("""if (await tryApi('release-pool', () => api('POST', '/api/opportunity/release-pool', { form })) != null) {""", """if (await okApi('release-pool', () => api('POST', '/api/opportunity/release-pool', { form }))) {"""), # dlgClose ("""if (await tryApi('close', () => api('POST', '/api/opportunity/close', { form })) != null) {""", """if (await okApi('close', () => api('POST', '/api/opportunity/close', { form }))) {"""), # dlgReopen ("""if (await tryApi('reopen', () => api('POST', '/api/opportunity/reopen', { form })) != null) {""", """if (await okApi('reopen', () => api('POST', '/api/opportunity/reopen', { form }))) {"""), # dlgHandover ("""if (await tryApi('handover', () => api('POST', '/api/opportunity/handover', { form })) != null) {""", """if (await okApi('handover', () => api('POST', '/api/opportunity/handover', { form }))) {"""), # dlgSwitchStage(跨行) ("""if (await tryApi('switch-stage', () => api('POST', '/api/opportunity/stage/switch', { form: { oppId: S.oppId, toStageId: v('toStageId'), remark: v('remark') } })) != null) {""", """if (await okApi('switch-stage', () => api('POST', '/api/opportunity/stage/switch', { form: { oppId: S.oppId, toStageId: v('toStageId'), remark: v('remark') } }))) {"""), # doFocus ("""if (await tryApi(act, () => api('POST', `/api/opportunity/${act}`, { form: { oppId: S.oppId } })) != null) {""", """if (await okApi(act, () => api('POST', `/api/opportunity/${act}`, { form: { oppId: S.oppId } }))) {"""), # doFollow ("""if (await tryApi('follow/add', () => api('POST', '/api/opportunity/follow/add', { form })) != null) {""", """if (await okApi('follow/add', () => api('POST', '/api/opportunity/follow/add', { form }))) {"""), # doSurvey ("""if (await tryApi('survey/add', () => api('POST', '/api/opportunity/site-survey/add', { form })) != null) {""", """if (await okApi('survey/add', () => api('POST', '/api/opportunity/site-survey/add', { form }))) {"""), # submitCard ("""if (await tryApi('card/submit', () => api('POST', '/api/opportunity/scheme-card/submit', { params: { id } })) != null) {""", """if (await okApi('card/submit', () => api('POST', '/api/opportunity/scheme-card/submit', { params: { id } }))) {"""), # doEdit ("""if (await tryApi('edit', () => api('POST', '/api/opportunity/edit', { form })) != null) {""", """if (await okApi('edit', () => api('POST', '/api/opportunity/edit', { form }))) {"""), # doSaveView(跨行) ("""if (await tryApi('view/save', () => api('POST', '/api/preference/view/save?scopeKey=opportunity', { json: { name, conditions, isDefault: false, seqNo: S.cviews.length + 1 } })) != null) {""", """if (await okApi('view/save', () => api('POST', '/api/preference/view/save?scopeKey=opportunity', { json: { name, conditions, isDefault: false, seqNo: S.cviews.length + 1 } }))) {"""), # doRuleSave(跨行) ("""if (await tryApi(publish ? 'publish' : 'save-draft', () => api('POST', `/api/rule/${fam}/${publish ? 'publish' : 'save-draft'}`, { form })) != null) {""", """if (await okApi(publish ? 'publish' : 'save-draft', () => api('POST', `/api/rule/${fam}/${publish ? 'publish' : 'save-draft'}`, { form }))) {"""), # ruleCopy ("""if (await tryApi('copy', () => api('POST', `/api/rule/${S.family}/copy`, { params: { id } })) != null) {""", """if (await okApi('copy', () => api('POST', `/api/rule/${S.family}/copy`, { params: { id } }))) {"""), # ruleDisable ("""if (await tryApi('disable', () => api('POST', `/api/rule/${S.family}/disable`, { params: { id } })) != null) {""", """if (await okApi('disable', () => api('POST', `/api/rule/${S.family}/disable`, { params: { id } }))) {"""), # ruleDelete ("""if (await tryApi('delete', () => api('POST', `/api/rule/${S.family}/delete`, { params: { id } })) != null) {""", """if (await okApi('delete', () => api('POST', `/api/rule/${S.family}/delete`, { params: { id } }))) {"""), ] if 'okApi' in txt: print('已含 okApi,跳过插入') else: assert ANCHOR in txt, 'tryApi anchor 未找到' txt = txt.replace(ANCHOR, OKAPI, 1) print('okApi 定义已插入') missed = [] for old, new in PAIRS: n = txt.count(old) if n != 1: missed.append((old[:60], n)) continue txt = txt.replace(old, new, 1) if missed: print('未命中(count != 1):') for m, n in missed: print(' ', n, m) sys.exit(1) open(PATH, 'w', encoding='utf-8').write(txt) print('替换完成:', len(PAIRS), '处') leftover = [ln for ln in txt.split('\n') if 'tryApi(' in ln and '!= null' in ln] print('残留 tryApi!=null 判定行数:', len(leftover)) for ln in leftover: print(' ', ln.strip()[:90])