trustbase-seller-backend 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/routes/onboard.html +239 -31
- package/test-onboard-applyment.js +29 -2
package/package.json
CHANGED
package/routes/onboard.html
CHANGED
|
@@ -63,6 +63,25 @@ h1{font-size:22px;margin-bottom:4px}
|
|
|
63
63
|
/* 结算规则只读展示框 (按主体推导, 商户不用选; settlement_id=结算规则 ID 716/719/727,
|
|
64
64
|
qualification_type=行业类目 MCC — 两次微信实测错误交叉锁定后的正确口径) */
|
|
65
65
|
#apply-form .arule{padding:10px 12px;border:1px dashed #D4CDBF;border-radius:8px;background:#F7F3EB;color:#6B655B;font-size:14px}
|
|
66
|
+
/* ===== 分步向导 stepper (2026-10-03 腾讯式分步填写): 6 步, 当前橙/完成绿/未达灰, 可回跳完成步 ===== */
|
|
67
|
+
#wz-bar{display:flex;gap:6px;overflow-x:auto;margin-bottom:12px;padding-bottom:4px}
|
|
68
|
+
#wz-bar .wz-item{display:flex;align-items:center;gap:6px;flex:none;font-size:12px;padding:6px 10px;border-radius:999px;border:1px solid #EAE3D6;background:#FFFDF9;cursor:pointer;color:#6B655B}
|
|
69
|
+
#wz-bar .wz-dot{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;background:#D4CDBF;color:#fff;font-size:11px;font-weight:600}
|
|
70
|
+
#wz-bar .wz-item.cur{border-color:#C4633C;background:#FBF1EA;color:#C4633C;font-weight:600}
|
|
71
|
+
#wz-bar .wz-item.cur .wz-dot{background:#C4633C}
|
|
72
|
+
#wz-bar .wz-item.done{border-color:#BBF7D0;background:#F0FDF4;color:#166534}
|
|
73
|
+
#wz-bar .wz-item.done .wz-dot{background:#16A34A}
|
|
74
|
+
#wz-bar .wz-item.todo{color:#BDB5A6;cursor:default}
|
|
75
|
+
#wz-step-head{margin-bottom:10px}
|
|
76
|
+
#wz-step-head .desc{margin-top:2px}
|
|
77
|
+
#wz-nav{display:flex;gap:10px;margin-top:16px}
|
|
78
|
+
#wz-nav .sbtn{flex:1;padding:12px;text-align:center;font-size:15px}
|
|
79
|
+
#wz-preview .wz-grp{border:1px solid #EAE3D6;border-radius:10px;padding:10px 12px;margin-bottom:10px;background:#FFFDF9}
|
|
80
|
+
#wz-preview .wz-grp-t{font-size:13px;font-weight:600;color:#C4633C;margin-bottom:6px}
|
|
81
|
+
#wz-preview .wz-row{display:flex;justify-content:space-between;font-size:13px;padding:3px 0;border-bottom:1px dashed #EFE9DC;gap:12px}
|
|
82
|
+
#wz-preview .wz-row:last-child{border-bottom:none}
|
|
83
|
+
#wz-preview .wz-row span{color:#8A857B;flex:none}
|
|
84
|
+
#wz-preview .wz-row b{text-align:right;word-break:break-all}
|
|
66
85
|
/* 特殊资质槽 (就地位: 行业选择正下方, 紧凑矮版 — 选了餐饮下面立刻要食品经营许可证) */
|
|
67
86
|
#apply-form #a_up_qual_wrap{margin-top:4px}
|
|
68
87
|
#apply-form #a_up_qual_wrap label.sbtn{padding:10px;gap:2px}
|
|
@@ -181,7 +200,9 @@ img.auprev{display:none;width:100%;max-height:140px;object-fit:cover;border-radi
|
|
|
181
200
|
<div class="hintbox" id="apply-msg"></div>
|
|
182
201
|
<div id="apply-status" style="display:none;margin-top:12px"></div>
|
|
183
202
|
<div id="apply-form" style="display:none;margin-top:12px">
|
|
184
|
-
<div class="desc" style="margin-bottom:12px">以下资料由你的电脑<b>本地加密</b>后交给服务商,向微信申请特约商户收款账户。身份证号/银行卡号在你电脑上就已加密,任何人 (含服务商) 都看不到明文。</div>
|
|
203
|
+
<div class="desc" style="margin-bottom:12px">以下资料由你的电脑<b>本地加密</b>后交给服务商,向微信申请特约商户收款账户。身份证号/银行卡号在你电脑上就已加密,任何人 (含服务商) 都看不到明文。</div>
|
|
204
|
+
<div id="wz-bar"></div>
|
|
205
|
+
<div id="wz-step-head"><b id="wz-title" style="font-size:15px"></b><div class="desc" id="wz-desc"></div></div>
|
|
185
206
|
|
|
186
207
|
<div class="acard">
|
|
187
208
|
<div class="acard-h">经营场景 <span class="aopt">三选一, 决定第 4/5 张卡片要什么资料</span></div>
|
|
@@ -268,14 +289,13 @@ img.auprev{display:none;width:100%;max-height:140px;object-fit:cover;border-radi
|
|
|
268
289
|
<div class="acard-h"><span class="anum">4</span><span id="acard4-title">门店信息</span></div>
|
|
269
290
|
<div id="scene_fields_app">
|
|
270
291
|
<div class="agrid">
|
|
271
|
-
<div class="afield"><label for="a_app_appid">应用 AppID</label><input id="a_app_appid" placeholder="
|
|
272
|
-
<div class="hint" id="a_appid_note" style="display:none;font-size:12px;color:#16A34A;margin-top:3px">✓
|
|
292
|
+
<div class="afield" id="a_appid_field"><label for="a_app_appid">应用 AppID</label><input id="a_app_appid" placeholder="wx 开头">
|
|
293
|
+
<div class="hint" id="a_appid_note" style="display:none;font-size:12px;color:#16A34A;margin-top:3px">✓ 由服务商提供</div></div>
|
|
273
294
|
<div class="afield"><label for="a_app_provider">应用归属</label>
|
|
274
295
|
<select id="a_app_provider"><option value="sp">服务商应用 (默认, 零自备)</option><option value="own">商户自有应用</option></select></div>
|
|
275
296
|
</div>
|
|
276
|
-
<div class="ahint" id="
|
|
277
|
-
|
|
278
|
-
</div>
|
|
297
|
+
<div class="ahint" id="a_app_provided" style="display:none;margin-top:8px;background:#F0FDF4;border-color:#BBF7D0;color:#166534"></div>
|
|
298
|
+
<div class="ahint" id="a_app_missing" style="display:none;margin-top:8px">⚠️ 服务商尚未配置应用,请联系服务商配置,或改用下方"商户自有应用"填写</div>
|
|
279
299
|
<div class="ahint" id="a_app_own_hint" style="display:none;margin-top:8px">使用自有应用: 请填自己的 AppID 并上传 4 张应用截图</div>
|
|
280
300
|
</div>
|
|
281
301
|
<div class="agrid" id="scene_fields_store">
|
|
@@ -317,9 +337,18 @@ img.auprev{display:none;width:100%;max-height:140px;object-fit:cover;border-radi
|
|
|
317
337
|
</div>
|
|
318
338
|
</div>
|
|
319
339
|
|
|
340
|
+
<div class="acard" id="wz-preview-card" style="display:none">
|
|
341
|
+
<div class="acard-h"><span class="anum">6</span>确认提交</div>
|
|
342
|
+
<div class="desc" style="margin-bottom:8px">请核对以下资料,确认无误后提交。身份证号/卡号等敏感信息已打码。</div>
|
|
343
|
+
<div id="wz-preview"></div>
|
|
344
|
+
</div>
|
|
320
345
|
<div id="apply-err" style="display:none"></div>
|
|
321
346
|
<button class="abtn" id="btn-apply-submit" onclick="submitApplyment()">加密并提交进件</button>
|
|
322
347
|
<div class="aprivacy">🔒 资料只保存在这台电脑; 敏感字段本机加密后交服务商; 服务商暂时不可达时加密暂存本机, 可重试。</div>
|
|
348
|
+
<div id="wz-nav">
|
|
349
|
+
<button type="button" class="sbtn" id="wz-prev" onclick="wzGo(-1)">← 上一步</button>
|
|
350
|
+
<button type="button" class="sbtn primary" id="wz-next" onclick="wzGo(1)">下一步 →</button>
|
|
351
|
+
</div>
|
|
323
352
|
</div>
|
|
324
353
|
</div>
|
|
325
354
|
</div>
|
|
@@ -668,22 +697,40 @@ function setScene(scene){
|
|
|
668
697
|
});
|
|
669
698
|
paintAppScene(); // APP 场景: 服务商素材复用行显隐 + 截图槽联动
|
|
670
699
|
}
|
|
671
|
-
// APP 场景 (
|
|
672
|
-
//
|
|
700
|
+
// APP 场景 (2026-10-03 UX 修正): 服务商配置完整 (AppID+4素材) → AppID 框和截图槽全隐藏,
|
|
701
|
+
// 只留绿标"应用和截图由服务商提供, 无需操作"; 未配齐 → 提示联系服务商 + 展开自有字段组;
|
|
702
|
+
// 选自有应用 → AppID 输入框 + 4 张截图槽。
|
|
703
|
+
function appSpComplete(){
|
|
704
|
+
var sp=window._spInfo||{}, a=sp.app_screenshots||{};
|
|
705
|
+
return !!(sp.app_appid&&a.home&&a.tail&&a.inner&&a.pay);
|
|
706
|
+
}
|
|
707
|
+
function maskAppid(a){ a=String(a||''); return a.length>8?a.slice(0,4)+'****'+a.slice(-4):a; }
|
|
673
708
|
function paintAppScene(){
|
|
674
709
|
if(currentScene()!=='SALES_SCENES_APP') return;
|
|
675
|
-
var
|
|
676
|
-
var hasSp=Object.keys(spAssets).length>0;
|
|
677
|
-
var reuseRow=document.getElementById('a_app_reuse_row');
|
|
678
|
-
if(reuseRow) reuseRow.style.display=hasSp?'':'none';
|
|
710
|
+
var complete=appSpComplete();
|
|
679
711
|
var provider=(document.getElementById('a_app_provider')||{}).value||'sp';
|
|
680
|
-
var
|
|
712
|
+
var zeroMode=provider==='sp'&&complete; // 零操作: 全隐藏
|
|
713
|
+
var missing=provider==='sp'&&!complete; // 服务商未配齐 → 提示+自有组
|
|
714
|
+
var fAppid=document.getElementById('a_appid_field');
|
|
715
|
+
if(fAppid) fAppid.style.display=zeroMode?'none':'';
|
|
716
|
+
var provided=document.getElementById('a_app_provided');
|
|
717
|
+
if(provided){
|
|
718
|
+
provided.style.display=zeroMode?'':'none';
|
|
719
|
+
if(zeroMode) provided.textContent='✓ 应用和截图由服务商提供 (AppID: '+maskAppid((window._spInfo||{}).app_appid)+'), 无需操作';
|
|
720
|
+
}
|
|
721
|
+
var missEl=document.getElementById('a_app_missing');
|
|
722
|
+
if(missEl) missEl.style.display=missing?'':'none';
|
|
723
|
+
var ownHint=document.getElementById('a_app_own_hint');
|
|
724
|
+
if(ownHint) ownHint.style.display=provider==='own'?'':'none';
|
|
681
725
|
['a_up_s1','a_up_s2','a_up_s3','a_up_s4'].forEach(function(id){
|
|
682
|
-
var el=document.getElementById(id);
|
|
683
|
-
if(el) el.style.display=reuse?'none':'';
|
|
726
|
+
var el=document.getElementById(id); if(el) el.style.display=zeroMode?'none':'';
|
|
684
727
|
});
|
|
685
|
-
|
|
686
|
-
|
|
728
|
+
// AppID: 服务商配了 → 预填 (隐藏提交也要用); 未配 → 不显示误导占位, 占位统一 "wx 开头"
|
|
729
|
+
var appidEl=document.getElementById('a_app_appid');
|
|
730
|
+
if(appidEl){
|
|
731
|
+
if((window._spInfo||{}).app_appid&&!appidEl.value) appidEl.value=(window._spInfo||{}).app_appid;
|
|
732
|
+
appidEl.placeholder='wx 开头';
|
|
733
|
+
}
|
|
687
734
|
}
|
|
688
735
|
setScene('SALES_SCENES_APP'); // 默认 APP (普通商户零自备)
|
|
689
736
|
function aval(id){var e=document.getElementById(id);return e?e.value.trim():''}
|
|
@@ -712,13 +759,14 @@ function applyFormBody(){
|
|
|
712
759
|
body.web_home_media_id=_aMedia.web_home_media_id||'';body.web_product_media_id=_aMedia.web_product_media_id||'';
|
|
713
760
|
}else if(scene==='SALES_SCENES_APP'){
|
|
714
761
|
var provider=aval('a_app_provider')||'sp';
|
|
715
|
-
body.appid=aval('a_app_appid');
|
|
716
762
|
body.appid_provider=provider; // sp=服务商应用(默认零自备) / own=商户自有应用
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
763
|
+
if(provider==='sp'&&appSpComplete()){
|
|
764
|
+
// 零操作: AppID 和截图全部用服务商配置 (商户页面全隐藏)
|
|
765
|
+
body.appid=(window._spInfo||{}).app_appid;
|
|
766
|
+
var sa=(window._spInfo||{}).app_screenshots||{};
|
|
767
|
+
body.app_screenshots=['home','tail','inner','pay'].map(function(k){return sa[k];}).filter(Boolean);
|
|
721
768
|
}else{
|
|
769
|
+
body.appid=aval('a_app_appid');
|
|
722
770
|
body.app_screenshots=[_aMedia.app_home_media_id,_aMedia.app_tail_media_id,_aMedia.app_inner_media_id,_aMedia.app_pay_media_id].filter(Boolean);
|
|
723
771
|
}
|
|
724
772
|
}else{
|
|
@@ -974,12 +1022,8 @@ async function loadSpInfo(){
|
|
|
974
1022
|
if(!j||!j.name) return;
|
|
975
1023
|
window._spInfo=j; // APP 场景零自备: app_appid/app_screenshots 预填复用
|
|
976
1024
|
var appidEl=document.getElementById('a_app_appid');
|
|
977
|
-
if(appidEl&&j.app_appid&&!appidEl.value)
|
|
978
|
-
|
|
979
|
-
var note=document.getElementById('a_appid_note');
|
|
980
|
-
if(note) note.style.display='block';
|
|
981
|
-
}
|
|
982
|
-
paintAppScene(); // 素材复用行按服务商配置刷新
|
|
1025
|
+
if(appidEl&&j.app_appid&&!appidEl.value) appidEl.value=j.app_appid;
|
|
1026
|
+
paintAppScene(); // 三态显隐按服务商配置完整度刷新
|
|
983
1027
|
card.style.display='block';
|
|
984
1028
|
card.classList.toggle('offline', !!j.offline);
|
|
985
1029
|
document.getElementById('sp-name').textContent=j.offline&&!j.stale?'服务商暂时不可达':j.name;
|
|
@@ -1039,6 +1083,172 @@ async function submit(){
|
|
|
1039
1083
|
loadStatus(); // 刷新进度面板
|
|
1040
1084
|
}catch(e){alert('网络错误: '+e.message);btn.disabled=false}
|
|
1041
1085
|
}
|
|
1086
|
+
// ============================== 分步卡片向导 (2026-10-03 腾讯式分步填写) ==============================
|
|
1087
|
+
// 6 步: 主体资料 → 法人与超管 → 结算账户 → 经营与行业(场景+行业+许可证) → 证件上传 → 确认提交(预览)。
|
|
1088
|
+
// 全部既有逻辑 (字段 id/applyFormBody/上传槽/草稿/联动/错误红卡) 原样复用, 这里只做分步显隐+导航。
|
|
1089
|
+
var WZ_STEPS=[
|
|
1090
|
+
{t:'主体资料',d:'营业执照上的主体信息,需与微信实名审核一致'},
|
|
1091
|
+
{t:'法人与超管',d:'法人身份将用于微信实名审核,超管接收开户通知'},
|
|
1092
|
+
{t:'结算账户',d:'微信收的款结算到这张卡(企业主体须对公账户)'},
|
|
1093
|
+
{t:'经营与行业',d:'选经营场景和所属行业,特殊行业就地传许可证'},
|
|
1094
|
+
{t:'证件上传',d:'拍清楚、四角完整、无反光 — 模糊是驳回首因'},
|
|
1095
|
+
{t:'确认提交',d:'核对资料,确认后提交微信审核'}
|
|
1096
|
+
];
|
|
1097
|
+
var _wzCur=1,_wzMax=1,_wzGroups=[];
|
|
1098
|
+
function wzInit(){
|
|
1099
|
+
var cards=document.querySelectorAll('#apply-form > .acard');
|
|
1100
|
+
// 既有卡片 DOM 顺序: [经营场景卡, ①主体, ②法人, ③结算, ④场景信息, ⑤证件上传]
|
|
1101
|
+
_wzGroups=[
|
|
1102
|
+
[cards[1]],[cards[2]],[cards[3]],[cards[0],cards[4]],[cards[5]],
|
|
1103
|
+
[document.getElementById('wz-preview-card'),document.getElementById('btn-apply-submit'),document.querySelector('#apply-form .aprivacy')]
|
|
1104
|
+
];
|
|
1105
|
+
var bar=document.getElementById('wz-bar');
|
|
1106
|
+
bar.innerHTML='';
|
|
1107
|
+
WZ_STEPS.forEach(function(st,i){
|
|
1108
|
+
var d=document.createElement('div');
|
|
1109
|
+
d.className='wz-item todo'; d.setAttribute('data-step',i+1);
|
|
1110
|
+
d.innerHTML='<span class="wz-dot">'+(i+1)+'</span><span class="wz-lbl">'+st.t+'</span>';
|
|
1111
|
+
d.addEventListener('click',function(){ if(i+1<=_wzMax) wzShow(i+1); }); // 只许回跳已完成步
|
|
1112
|
+
bar.appendChild(d);
|
|
1113
|
+
});
|
|
1114
|
+
wzShow(1);
|
|
1115
|
+
}
|
|
1116
|
+
function wzShow(n){
|
|
1117
|
+
_wzCur=n; if(n>_wzMax)_wzMax=n;
|
|
1118
|
+
_wzGroups.forEach(function(g,i){
|
|
1119
|
+
g.forEach(function(el){ if(el) el.style.display=(i+1===n)?'':'none'; });
|
|
1120
|
+
});
|
|
1121
|
+
document.querySelectorAll('#wz-bar .wz-item').forEach(function(it){
|
|
1122
|
+
var s=Number(it.getAttribute('data-step'));
|
|
1123
|
+
it.className='wz-item'+(s===n?' cur':(s<_wzMax?' done':' todo'));
|
|
1124
|
+
it.querySelector('.wz-dot').innerHTML=(s<_wzMax&&s!==n)?'✓':String(s);
|
|
1125
|
+
});
|
|
1126
|
+
var st=WZ_STEPS[n-1];
|
|
1127
|
+
document.getElementById('wz-title').textContent='第 '+n+'/6 步 · '+st.t;
|
|
1128
|
+
document.getElementById('wz-desc').textContent=st.d;
|
|
1129
|
+
document.getElementById('wz-prev').style.visibility=n===1?'hidden':'visible';
|
|
1130
|
+
document.getElementById('wz-next').style.display=n===6?'none':'';
|
|
1131
|
+
if(n===6) renderWzPreview();
|
|
1132
|
+
hideApplyErr();
|
|
1133
|
+
document.getElementById('apply-form').scrollIntoView({behavior:'smooth',block:'start'});
|
|
1134
|
+
}
|
|
1135
|
+
function wzGo(dir){
|
|
1136
|
+
if(dir>0){ var v=wzValidate(_wzCur); if(!v.ok){ showApplyErr(v.msg,v.field); return; } } // 下一步先校验当前步
|
|
1137
|
+
var n=_wzCur+dir;
|
|
1138
|
+
if(n<1||n>6) return;
|
|
1139
|
+
wzShow(n);
|
|
1140
|
+
saveApplyDraft();
|
|
1141
|
+
}
|
|
1142
|
+
// 当前步必填校验 (不过则红卡指到缺的字段, 不放行; 与后端 APPLY_* 校验同字段名, 错误定位复用)
|
|
1143
|
+
function wzValidate(n){
|
|
1144
|
+
function need(id,label,field){
|
|
1145
|
+
var e=document.getElementById(id);
|
|
1146
|
+
if(!e||!String(e.value||'').trim()) return {ok:false,field:field||id.replace(/^a_/,''),msg:'请填写: '+label};
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
if(n===1){
|
|
1150
|
+
return need('a_shortname','商户简称','merchant_shortname')||need('a_merchant_name','营业执照名称','merchant_name')
|
|
1151
|
+
||need('a_license_number','统一社会信用代码','license_number')||need('a_service_phone','客服电话','service_phone')||{ok:true};
|
|
1152
|
+
}
|
|
1153
|
+
if(n===2){
|
|
1154
|
+
var r=need('a_legal_name','法人/经营者姓名','legal_name')||need('a_legal_id_number','法人身份证号','legal_id_number');
|
|
1155
|
+
if(r) return r;
|
|
1156
|
+
if(document.getElementById('a_subject_type').value==='SUBJECT_TYPE_ENTERPRISE'){
|
|
1157
|
+
r=need('a_legal_id_address','身份证居住地址','legal_id_address'); if(r) return r;
|
|
1158
|
+
}
|
|
1159
|
+
return need('a_period_begin','身份证有效期开始','legal_id_period_begin')||need('a_period_end','身份证有效期结束','legal_id_period_end')
|
|
1160
|
+
||need('a_contact_name','超管姓名','contact_name')||need('a_contact_mobile','超管手机号','contact_mobile')
|
|
1161
|
+
||need('a_contact_email','联系邮箱','contact_email')||{ok:true};
|
|
1162
|
+
}
|
|
1163
|
+
if(n===3){
|
|
1164
|
+
return need('a_account_bank','开户银行','account_bank')||need('a_account_name','开户名称','account_name')
|
|
1165
|
+
||need('a_account_number','银行账号','account_number')||{ok:true};
|
|
1166
|
+
}
|
|
1167
|
+
if(n===4){
|
|
1168
|
+
var scene=currentScene(), r=null;
|
|
1169
|
+
if(scene==='SALES_SCENES_STORE'){
|
|
1170
|
+
r=need('a_store_name','门店名称','store_name')||need('a_store_address_code','门店省市编码','store_address_code')||need('a_store_address','门店详细地址','store_address');
|
|
1171
|
+
}else if(scene==='SALES_SCENES_WEB'){
|
|
1172
|
+
r=need('a_website_url','网站网址','website_url');
|
|
1173
|
+
}else if(scene==='SALES_SCENES_MP'){
|
|
1174
|
+
r=need('a_appid','公众号/小程序 AppID','appid');
|
|
1175
|
+
}else{
|
|
1176
|
+
// APP 场景: 服务商配置完整(零操作)时 AppID 框隐藏且用服务商值, 不校验输入框
|
|
1177
|
+
if(!((document.getElementById('a_app_provider')||{}).value!=='own'&&appSpComplete())){
|
|
1178
|
+
r=need('a_app_appid','应用 AppID','app_appid');
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
if(r) return r;
|
|
1182
|
+
var ind=aval('a_settlement_id');
|
|
1183
|
+
if(!ind) return {ok:false,field:'qualification_type',msg:'请选择: 所属行业'};
|
|
1184
|
+
if(typeof QUAL_REQUIRED!=='undefined'&&QUAL_REQUIRED[ind]&&!_aMedia.qual_media_id){
|
|
1185
|
+
return {ok:false,field:'qual_media_id',msg:'请上传: '+ind+' 所需资质 ('+QUAL_REQUIRED[ind]+')'};
|
|
1186
|
+
}
|
|
1187
|
+
if(scene==='SALES_SCENES_APP'){
|
|
1188
|
+
var provider=(document.getElementById('a_app_provider')||{}).value||'sp';
|
|
1189
|
+
if(!(provider==='sp'&&appSpComplete())
|
|
1190
|
+
&&!(_aMedia.app_home_media_id&&_aMedia.app_tail_media_id&&_aMedia.app_inner_media_id&&_aMedia.app_pay_media_id)){
|
|
1191
|
+
return {ok:false,field:'app_screenshots',msg:'请上传 4 张应用截图 (或等服务商配置后重试)'};
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
return {ok:true};
|
|
1195
|
+
}
|
|
1196
|
+
if(n===5){
|
|
1197
|
+
var scene=currentScene();
|
|
1198
|
+
if(!_aMedia.license_media_id) return {ok:false,field:'license_media_id',msg:'请上传: 营业执照照片'};
|
|
1199
|
+
if(!_aMedia.legal_id_front_media_id) return {ok:false,field:'legal_id_front_media_id',msg:'请上传: 身份证人像面'};
|
|
1200
|
+
if(!_aMedia.legal_id_back_media_id) return {ok:false,field:'legal_id_back_media_id',msg:'请上传: 身份证国徽面'};
|
|
1201
|
+
if(scene==='SALES_SCENES_STORE'){
|
|
1202
|
+
if(!_aMedia.store_entrance_media_id) return {ok:false,field:'store_entrance_media_id',msg:'请上传: 门店门头照片'};
|
|
1203
|
+
if(!_aMedia.store_indoor_media_id) return {ok:false,field:'store_indoor_media_id',msg:'请上传: 门店内部照片'};
|
|
1204
|
+
}else if(scene==='SALES_SCENES_WEB'){
|
|
1205
|
+
if(!_aMedia.web_home_media_id) return {ok:false,field:'web_home_media_id',msg:'请上传: 网站首页截图'};
|
|
1206
|
+
if(!_aMedia.web_product_media_id) return {ok:false,field:'web_product_media_id',msg:'请上传: 商品/服务页截图'};
|
|
1207
|
+
}else if(scene==='SALES_SCENES_MP'){
|
|
1208
|
+
if(!_aMedia.mp_media_id) return {ok:false,field:'mp_media_id',msg:'请上传: 公众号/小程序页面截图'};
|
|
1209
|
+
}
|
|
1210
|
+
return {ok:true};
|
|
1211
|
+
}
|
|
1212
|
+
return {ok:true}; // 第 6 步提交由后端兜底
|
|
1213
|
+
}
|
|
1214
|
+
// 第 6 步预览: 分组只读摘要 (敏感字段 ***后4位)
|
|
1215
|
+
function wzMask(s){ s=String(s||''); return s.length<=4?'***':'***'+s.slice(-4); }
|
|
1216
|
+
function renderWzPreview(){
|
|
1217
|
+
var f=applyFormBody();
|
|
1218
|
+
var scene=currentScene();
|
|
1219
|
+
var rows=[];
|
|
1220
|
+
function grp(t,items){
|
|
1221
|
+
rows.push('<div class="wz-grp"><div class="wz-grp-t">'+escHtml(t)+'</div>'
|
|
1222
|
+
+items.map(function(it){return '<div class="wz-row"><span>'+escHtml(it[0])+'</span><b>'+escHtml(it[1]==null||it[1]===''?'—':it[1])+'</b></div>';}).join('')+'</div>');
|
|
1223
|
+
}
|
|
1224
|
+
grp('主体资料',[
|
|
1225
|
+
['主体类型',(document.querySelector('#a_subject_type option:checked')||{}).textContent||f.subject_type],
|
|
1226
|
+
['商户简称',f.merchant_shortname],['营业执照名称',f.merchant_name],
|
|
1227
|
+
['信用代码',f.license_number],['客服电话',f.service_phone]]);
|
|
1228
|
+
grp('法人与超管',[
|
|
1229
|
+
['法人姓名',f.legal_name],['身份证号',wzMask(f.legal_id_number)],
|
|
1230
|
+
['有效期',f.legal_id_period_begin+' ~ '+f.legal_id_period_end],
|
|
1231
|
+
['超管',f.contact_name+' '+wzMask(f.contact_mobile)],['邮箱',f.contact_email]]);
|
|
1232
|
+
grp('结算账户',[
|
|
1233
|
+
['账户类型',f.account_type==='BANK_ACCOUNT_TYPE_CORPORATE'?'对公账户':'经营者个人卡'],
|
|
1234
|
+
['开户行',f.account_bank],['户名',wzMask(f.account_name)],['卡号',wzMask(f.account_number)]]);
|
|
1235
|
+
var sceneName={SALES_SCENES_APP:'APP 应用',SALES_SCENES_STORE:'线下门店',SALES_SCENES_WEB:'互联网网站',SALES_SCENES_MP:'公众号/小程序'}[scene]||scene;
|
|
1236
|
+
grp('经营与行业',[
|
|
1237
|
+
['经营场景',sceneName],
|
|
1238
|
+
['所属行业',(document.getElementById('a_industry_cat')||{}).value+' > '+f.qualification_type],
|
|
1239
|
+
['结算规则',(document.getElementById('a_settlement_rule')||{}).textContent||''],
|
|
1240
|
+
['特殊资质',_aMedia.qual_media_id?'已上传 ✓':'—']]);
|
|
1241
|
+
var docs=[['营业执照',_aMedia.license_media_id],['身份证人像面',_aMedia.legal_id_front_media_id],['身份证国徽面',_aMedia.legal_id_back_media_id]];
|
|
1242
|
+
var sceneDocs={store_entrance_media_id:'门店门头照',store_indoor_media_id:'门店内部照',web_home_media_id:'网站首页截图',web_product_media_id:'商品/服务页截图',mp_media_id:'公众号/小程序截图',app_home_media_id:'应用首页截图',app_tail_media_id:'应用尾页截图',app_inner_media_id:'应用内页截图',app_pay_media_id:'应用支付页截图'};
|
|
1243
|
+
for(var k in sceneDocs){ if(_aMedia[k]) docs.push([sceneDocs[k],_aMedia[k]]); }
|
|
1244
|
+
if(scene==='SALES_SCENES_APP'&&f.appid_provider==='sp'&&appSpComplete()){
|
|
1245
|
+
docs.push(['应用截图','服务商素材 ✓']);
|
|
1246
|
+
}
|
|
1247
|
+
grp('证件',docs.map(function(d){return [d[0], d[1]?(d[1]==='服务商素材 ✓'?d[1]:'已上传 ✓'):'未上传 ✗'];}));
|
|
1248
|
+
document.getElementById('wz-preview').innerHTML=rows.join('');
|
|
1249
|
+
}
|
|
1250
|
+
window.addEventListener('load',wzInit);
|
|
1251
|
+
|
|
1042
1252
|
// 安全卡二维码: 本机后端读 tb-keyring 出 dataURL (qrcode 包无浏览器 build, 且安全词不进 script 依赖链);
|
|
1043
1253
|
// 只在创建会话 (_mn 在内存) 拉取 — 刷新后不再展示 (与"安全词只展示一次"同口径)
|
|
1044
1254
|
async function loadBackupQr(){
|
|
@@ -1187,9 +1397,7 @@ async function restoreIdentity(){
|
|
|
1187
1397
|
}
|
|
1188
1398
|
}
|
|
1189
1399
|
if(stl){ stl.addEventListener('change',paintQualSlot); }
|
|
1190
|
-
// APP 场景联动:
|
|
1191
|
-
var appReuse=document.getElementById('a_app_reuse');
|
|
1192
|
-
if(appReuse) appReuse.addEventListener('change',function(){ paintAppScene(); saveApplyDraft(); });
|
|
1400
|
+
// APP 场景联动: 应用归属切换 → 字段组/截图槽显隐
|
|
1193
1401
|
var appProv=document.getElementById('a_app_provider');
|
|
1194
1402
|
if(appProv) appProv.addEventListener('change',function(){ paintAppScene(); saveApplyDraft(); });
|
|
1195
1403
|
if(catEl){ catEl.addEventListener('change',function(){ renderIndustrySubs(false); }); }
|
|
@@ -782,16 +782,43 @@ test("APP 场景零自备: 默认场景=APP + 服务商素材复用提交组装
|
|
|
782
782
|
} finally { srv.close(); }
|
|
783
783
|
});
|
|
784
784
|
|
|
785
|
-
test("APP 场景页面: 默认选中 APP +
|
|
785
|
+
test("APP 场景页面: 默认选中 APP + 三态显隐 (配齐全隐藏/未配提示/自有展开)", async () => {
|
|
786
786
|
const { srv, base } = await startSeller();
|
|
787
787
|
try {
|
|
788
788
|
const html = await (await fetch(base + "/onboard/")).text();
|
|
789
789
|
assert.ok(html.includes('value="SALES_SCENES_APP" checked'), "默认场景=APP");
|
|
790
790
|
assert.ok(html.includes("scene_fields_app"), "APP 字段组");
|
|
791
791
|
assert.ok(html.includes("a_app_appid") && html.includes("a_app_provider"), "AppID + 归属");
|
|
792
|
-
assert.ok(html.includes("
|
|
792
|
+
assert.ok(html.includes("a_app_provided") && html.includes("无需操作"), "零操作绿标");
|
|
793
|
+
assert.ok(html.includes("a_app_missing") && html.includes("尚未配置应用"), "未配提示");
|
|
794
|
+
assert.ok(html.includes("appSpComplete") && html.includes("maskAppid"), "完整度判定 + AppID 打码");
|
|
795
|
+
assert.ok(html.includes("a_appid_field"), "AppID 字段容器 (可整体隐藏)");
|
|
796
|
+
assert.ok(!html.includes("a_app_reuse"), "复用勾选已移除 (零自备=默认行为)");
|
|
793
797
|
assert.ok(html.includes("a_up_s3") && html.includes("a_up_s4"), "4 截图槽");
|
|
794
798
|
assert.ok(html.includes("paintAppScene"), "场景联动");
|
|
795
799
|
assert.ok(html.includes("app_screenshots"), "提交字段");
|
|
796
800
|
} finally { srv.close(); }
|
|
797
801
|
});
|
|
802
|
+
|
|
803
|
+
test("分步向导: stepper/导航/校验/预览 元素与逻辑齐备", async () => {
|
|
804
|
+
const { srv, base } = await startSeller();
|
|
805
|
+
try {
|
|
806
|
+
const html = await (await fetch(base + "/onboard/")).text();
|
|
807
|
+
// stepper + 6 步 + 导航
|
|
808
|
+
assert.ok(html.includes("wz-bar") && html.includes("WZ_STEPS"), "进度条");
|
|
809
|
+
assert.ok(html.includes("确认提交"), "第 6 步");
|
|
810
|
+
assert.ok(html.includes("wz-prev") && html.includes("wz-next"), "上一步/下一步");
|
|
811
|
+
assert.ok(html.includes("wzGo") && html.includes("wzShow"), "导航函数");
|
|
812
|
+
// 校验: 下一步拦 + 上一步不校验 + 回跳完成步
|
|
813
|
+
assert.ok(html.includes("wzValidate"), "当前步校验");
|
|
814
|
+
assert.ok(html.includes("if(dir>0){ var v=wzValidate(_wzCur); if(!v.ok)"), "上一步不校验");
|
|
815
|
+
assert.ok(html.includes("if(i+1<=_wzMax) wzShow(i+1)"), "只许回跳已完成步");
|
|
816
|
+
// 第 6 步预览: 分组 + 脱敏
|
|
817
|
+
assert.ok(html.includes("wz-preview") && html.includes("renderWzPreview"), "预览渲染");
|
|
818
|
+
assert.ok(html.includes("wzMask") && html.includes("***"), "敏感字段脱敏");
|
|
819
|
+
assert.ok(html.includes("主体资料") && html.includes("法人与超管") && html.includes("结算账户")
|
|
820
|
+
&& html.includes("经营与行业") && html.includes("证件上传"), "6 步标题");
|
|
821
|
+
// 旧结构未破坏: 既有卡片/字段 id 都在
|
|
822
|
+
assert.ok(html.includes("a_shortname") && html.includes("a_up_license") && html.includes("btn-apply-submit"), "既有字段/提交钮保留");
|
|
823
|
+
} finally { srv.close(); }
|
|
824
|
+
});
|