function skuDlg(cur){ cur=cur||{}; const types=['subs','inapp','one_time']; return modal({ title: cur.id ? '编辑 SKU' : '添加 SKU', okText: '保存', fields:[ {label:'名称', value:cur.title||''}, {label:'包名', value:cur.package||'', placeholder:'com.example.app'}, {label:'SKU', value:cur.sku||''}, {label:'类型 subs / inapp / one_time', value:cur.product_type||'subs', placeholder:types.join(' / ')}, {label:'默认 offer token(可选)', value:cur.offer_token||''}, {label:'备注', value:cur.note||''} ] }); } async function addSkuDlg(){ const v=await skuDlg(null); if(!v) return; const body={title:String(v[0]||'').trim(), package:String(v[1]||'').trim(), sku:String(v[2]||'').trim(), product_type:String(v[3]||'subs').trim()||'subs', offer_token:String(v[4]||'').trim(), note:String(v[5]||'').trim()}; if(!body.package || !body.sku) return fail('无法添加','包名和 SKU 必填'); const j=await api('/api/skus',{method:'POST',body:JSON.stringify(body)}); if(j.error) return fail('无法添加', j.error); notice('已添加', body.sku); await loadAll(); render(false); } async function editSku(id){ const cur=(cache.skus||[]).find(s=>Number(s.id)===Number(id)); if(!cur) return fail('无法编辑','找不到 SKU'); const v=await skuDlg(cur); if(!v) return; const body={title:String(v[0]||'').trim(), package:String(v[1]||'').trim(), sku:String(v[2]||'').trim(), product_type:String(v[3]||'subs').trim()||'subs', offer_token:String(v[4]||'').trim(), note:String(v[5]||'').trim()}; if(!body.package || !body.sku) return fail('无法保存','包名和 SKU 必填'); const j=await api('/api/skus/'+id,{method:'PUT',body:JSON.stringify(body)}); if(j.error) return fail('无法保存', j.error); notice('已保存', body.sku); await loadAll(); render(false); } async function delSku(id){ const cur=(cache.skus||[]).find(s=>Number(s.id)===Number(id)); const ok=await modal({title:'删除 SKU', message:'删除 '+(cur?(cur.title||cur.sku):('#'+id))+'?报价也会一起去掉。', okText:'删除', cancelText:'取消'}); if(!ok) return; const j=await api('/api/skus/'+id,{method:'DELETE'}); if(j.error) return fail('无法删除', j.error); notice('已删除', cur?(cur.sku||''):('#'+id)); await loadAll(); render(false); }