@@ -3,7 +3,7 @@
( function ( ) {
'use strict' ;
/* 页面版本号( YYMMDD+序号) : 显示在「关于兜爸心选」页底部; bump 时同步 head 注释与 ?v= */
var VER = '26110461 ' ;
var VER = '26110462 ' ;
const $ = ( s , c ) => ( c || document ) . querySelector ( s ) ;
const $$ = ( s , c ) => Array . from ( ( c || document ) . querySelectorAll ( s ) ) ;
@@ -1889,6 +1889,7 @@
$$ ( '[data-wk]' ) . forEach ( n => {
n . textContent = n . dataset . wk === 'cn' ? '孕 ' + state . week + ' 周' : state . week ;
} ) ;
setTimeout ( renderGiftShelf ) ; // 福利区按孕周出;异步调,避开它那几个 const 还没初始化的时段
/* ⚠️ #calNext 归**卡片接口**优先(与孕检日历应用同一套排期、还支持"改过预约日以预约日为准") ;
本地按预产期推算只在接口没数据时兜底。两者并行返回、先后不定,所以看 cardsOwned.cal。
( curve 卡的 [data-wk] 由 applyRemoteCards 摘掉,这里自然跳过,无需额外判断。) */
@@ -2654,96 +2655,63 @@
}
/* ================= 孕育资源库:列表页 + 内容页 ================= */
const RES = {
book : {
img : 'assets/img/gift-book.png' , cat : '产检' , tint : 'o' ,
title : '《糖耐检查全攻略》' , desc : '孕24-28周必看 · 附检查前饮食清单' ,
meta : [ '8 分钟读完' , '12.8 万妈妈已领取' , '孕24-28周' ] ,
body : [ [ '什么是糖耐量检查' , '糖耐量检查( OGTT) 用于筛查妊娠期糖尿病, 一般安排在孕 24– 28 周。检查当天需空腹抽血一次,喝下 75g 葡萄糖水后 1 小时、2 小时各抽血一次,共三次。' ] ,
[ '检查前 3 天怎么吃' , '不需要刻意节食。保持平时饮食即可,但每天碳水化合物摄入不少于 150g, 否则可能出现假阳性。避免油炸、含糖饮料与夜宵。' ] ,
[ '检查当天注意事项' , '前一晚 22:00 后禁食,可少量饮水。带上水杯、小零食(抽完最后一管血再吃)和陪同家属。喝糖水要在 5 分钟内喝完,之后静坐等待,不要来回走动。 ' ] ,
[ '结果怎么看' , '空腹 < 5.1、1 小时 < 10.0、2 小时 < 8.5( mmol/L) , 任意一项超标即诊断为妊娠期糖尿病。多数可通过饮食与运动控制, 不必过度紧张。' ] ]
} ,
food : {
img : 'assets/img/gift-food.png' , cat : '营养' , tint : 'g' ,
title : '孕期营养全书' , desc : '按孕周编排的一日三餐参考' ,
m eta : [ '12 分钟读完' , '20.4 万妈妈已领取' , '全孕期' ] ,
body : [ [ '孕中期的能量需求' , '孕中期每天比孕前多约 300 kcal, 相当于一杯牛奶加一个鸡蛋加半碗米饭, 不需要「吃两人份」。' ] ,
[ '四类必须补的营养素' , '钙 1000mg/天(奶制品、豆制品)、铁 24mg/天( 红肉、动物肝脏) 、DHA 200mg/天(深海鱼)、叶酸 400μg/天(绿叶菜、补充剂)。' ] ,
[ '一日三餐参考' , '早餐:牛奶 + 全麦面包 + 鸡蛋 + 一份水果;午餐:杂粮饭 + 瘦肉 + 深绿色蔬菜 + 豆制品;晚餐:清淡为主,鱼虾 + 蔬菜 + 少量主食;加餐:坚果一小把或酸奶一杯。' ] ,
[ '要少碰的东西' , '生食(刺身、溏心蛋)、未杀菌乳制品、高汞鱼(金枪鱼、鲨鱼)、酒精与浓咖啡。' ] ]
} ,
music : {
img : 'assets/img/gift-music.png ', cat : '胎教' , tint : 'p ' ,
title : '胎教音乐合集' , desc : '30 首适合孕中期的舒缓曲目' ,
meta : [ '30 首 · 共 96 分钟' , '9.6 万妈妈已领取' , '孕16周起' ] ,
body : [ [ '宝宝什么时候能听见' , '孕 16 周左右听觉器官初步形成, 24 周后已能对外界声音作出反应,这是胎教音乐最合适的开始时间。' ] ,
[ '正确的听法' , '不要把设备贴在肚皮上。房间内正常音量播放即可,控制在 60 分贝以下,每次 15– 20 分钟,每天 1– 2 次。' ] ,
[ '选什么曲子' , '节奏平稳、旋律简单、无强烈鼓点的音乐最合适,如古典小品、轻钢琴、自然音。妈妈自己听着放松,才是最好的胎教。' ] ,
[ '比音乐更重要的事' , '妈妈的声音是宝宝最熟悉的声音。每天和宝宝说几句话,效果胜过任何一张专辑。' ] ]
} ,
sport : {
img : 'assets/img/72910df66ee3.png' , cat : '运动' , tint : 'g' ,
title : '孕中期安全运动指南' , desc : '每天 30 分钟,缓解腰背酸痛 ' ,
meta : [ '6 分钟读完' , '7.2 万妈妈已领取' , '孕13-28周' ] ,
body : [ [ '为什么孕中期最适合运动' , '早孕反应消退、腹部尚未过分隆起,是整个孕期活动最舒适的窗口,规律运动能降低妊娠糖尿病与子痫前期风险。' ] ,
[ '推荐的四种运动' , '快走、游泳、孕妇瑜伽、固定式单车。每周 5 天、每次 30 分钟,强度以「能正常说话但唱不了歌」为准。' ] ,
[ '必须避开的动作' , '仰卧位动作(孕 16 周后)、跳跃与急转、需要平衡的运动、任何有腹部撞击风险的项目。' ] ,
[ '出现这些情况立即停止' , '阴道出血、规律宫缩、头晕胸闷、羊水样液体流出,应停止运动并及时就医。' ] ]
} ,
sleep : {
img : 'assets/img/f0d5e062f11a.png' , cat : '心理' , tint : 'b' ,
title : '睡不好怎么办' , desc : '孕期失眠的 7 个改善方法' ,
meta : [ '5 分钟读完' , '15.1 万妈妈已领取' , '全孕期' ] ,
body : [ [ '孕期失眠很常见' , '约 70% 的孕妇有不同程度的睡眠问题,多由激素变化、尿频、腿抽筋和焦虑引起,绝大多数不需要药物治疗。' ] ,
[ '睡姿怎么选' , '孕中晚期优先左侧卧,可在两腿之间与腰后各垫一个枕头,减轻下腔静脉压迫。' ] ,
[ '睡前一小时的仪式' , '关掉主灯、放下手机、温水泡脚 10 分钟、轻音乐或呼吸练习,让身体建立入睡信号。' ] ,
[ '白天该做的事' , '固定起床时间、午睡不超过 30 分钟、下午之后不摄入咖啡因、傍晚适量活动。' ] ]
} ,
diet : {
img : 'assets/img/dd5639fde61d.png' , cat : '营养' , tint : 'o' ,
title : '孕期体重管理' , desc : '孕前 BMI 决定你该长多少' ,
meta : [ '7 分钟读完' , '11.3 万妈妈已领取' , '全孕期' ] ,
body : [ [ '先算孕前 BMI' , 'BMI = 体重(kg) ÷ 身高(m)²。孕前偏瘦(<18.5)建议全孕期增重 12.5– 18kg, 正常( 18.5– 24.9) 11.5– 16kg, 超重( 25– 29.9) 7– 11.5kg。' ] ,
[ '孕中期的增重节奏' , '孕中晚期每周增重 0.3– 0.5kg 较理想。单周超过 1kg 多为水肿或饮食过量,需要复盘。' ] ,
[ '称重的正确方法' , '固定每周同一天、同一时间、同样着装,晨起排空后测量,只看趋势不纠结单次数字。 '] ,
[ '长得太快或太慢' , '连续两周超标先减少精制主食与含糖饮料;增长过慢则增加优质蛋白与健康脂肪,并排查甲功与贫血。' ] ]
} ,
report : {
img : 'assets/img/b855b45df1f3.png' , cat : '产检' , tint : 'b' ,
title : '产检时间表(全孕期)' , desc : '13 次产检,一次都不漏' ,
meta : [ '4 分钟读完' , '26.7 万妈妈已领取' , '全孕期' ] ,
body : [ [ '孕早期( ≤13周) ' , '6– 8 周建卡 + B超确认宫内孕; 11– 13⁺⁶ 周 NT 检查与早期唐筛。' ] ,
[ '孕中期( 14– 27周) ' , '15– 20 周唐筛或无创 DNA; 20– 24 周大排畸; 24– 28 周糖耐 + 血常规复查。' ] ,
[ '孕晚期( 28周后) ' , '28– 36 周每 2 周一次; 36 周后每周一次, 含胎心监护、B超估重与骨盆评估。' ] ,
[ '每次都要带的东西' , '母子健康手册、既往报告、医保卡、水杯与小零食。建议提前一天在手机里存好问题清单。' ] ]
} ,
med : {
img : 'assets/img/4657f50f42c8.png' , cat : '心理' , tint : 'p' ,
title : '孕期情绪自查手册' , desc : '分清正常波动与孕期抑郁' ,
meta : [ '6 分钟读完' , '5.9 万妈妈已领取' , '全孕期' ] ,
body : [ [ '情绪起伏是正常的' , '激素剧烈变化叠加身份转变,孕期爱哭、易怒、突然焦虑都很常见,本身不等于抑郁。' ] ,
[ '需要警惕的信号' , '持续两周以上的情绪低落、对什么都提不起兴趣、睡眠与食欲明显改变、反复自责或出现伤害自己的念头。' ] ,
[ '可以自己做的三件事' , '把感受说出来而不是憋着;每天留 20 分钟只属于自己;减少无休止的搜索式焦虑。' ] ,
[ '寻求帮助不丢人' , '产科、心理科都可以提供帮助,孕期心理干预安全且有效,越早越好。' ] ]
}
} ;
const RES _ORDER = [ 'book' , 'food' , 'music' , 'report' , 'sport' , 'diet' , 'sleep' , 'med' ] ;
/* 2026-11-05 用户: 福利资料改「3 兜豆兑换 → 立刻弹网盘地址」,详情页要说清「这份资料里有什么」。
PACK = 文件形式 + 内容清单( AI 助手起草,用户待核对;网盘里实际文件变了要同步改这里)。
价格以接口 claim-status.price 为准, RES_PRICE 只是没拉到时的默认值。 */
let RES _PRICE = 3 ;
const PACK = {
book : { fmt : [ 'PDF · 18 页' , '可打印' ] , items : [ '糖耐检查流程图: 3 次抽血的时间点一张图看懂' , '检查前 3 天饮食清单(每天碳水够 150g 的吃法)' , '检查当天携带物品清单' , '结果对照表:空腹 / 1 小时 / 2 小时三个数怎么看' , '万一超标:一周控糖食谱示例' , '妈妈们最常问的 12 个问题' ] } ,
food : { fmt : [ 'PDF · 86 页' , '按孕周分章' ] , items : [ '孕早 / 中 / 晚期分章节,每章先讲这阶段缺什么' , '40 周每周一日三餐参考' , '钙、铁、DHA、叶酸常见食物含量表' , '孕期要少碰的食物清单' , '加餐搭配 30 例' ] } ,
music : { fmt : [ 'MP3 · 30 首' , '共 96 分钟' , '附听法说明' ] , items : [ '古典小品 10 首' , '轻钢琴 10 首' , '自然音 10 首(雨声、溪流、鸟鸣)' , '每日播放安排表:什么时候听、听多久' , '音量和距离的注意事项' ] } ,
report : { fmt : [ 'PDF · 6 页' , '附可打印表格' ] , items : [ '全孕期 13 次产检:时间 + 检查项目一览' , '每次产检要带的东西' , '「问医生」问题清单模板' , '产检报告存放登记表' ] } ,
sport : { fmt : [ 'PDF · 22 页' , '动作图解' ] , items : [ '快走、游泳、孕妇瑜伽、固定单车的要点' , '12 个孕期瑜伽动作分步图解' , '运动强度怎么把握' , '必须避开的动作清单' , '出现哪些情况要立刻停下' ] } ,
diet : { fmt : [ 'PDF · 16 页' , '附体重记录表' ] , items : [ '孕前 BMI 对应的增重范围对照表' , '每周体重记录表(可打印)' , '正确称重的方法' , '长得太快 / 太慢怎么调整' ] } ,
sleep : { fmt : [ 'PDF · 14 页' , '附助眠音频 5 段' ] , items : [ '孕期失眠的 7 个改善方法' , '左侧卧 + 垫枕头的睡姿图解' , '睡前放松呼吸练习(音频)' , '一周睡眠记录表' ] } ,
med : { fmt : [ 'PDF · 12 页' , '附自评量表' ] , items : [ '情绪自评量表 + 计分说明' , '需要警惕的信号清单' , '情绪日记模板' , '可以求助的渠道' ] }
} ;
/* 已兑换的 key( 来自 claim-status.resGot) ; 兑换成功后本地追加 */
/* 2026-11-05 起「孕N周专属福利」资料由数胎动后台维护( taidong.douba.top/admin 左侧「孕周专属福利」,会话 375797cf) 。
公开列表 GET /taidong/api/public/week-perks → {items:[{id,week_from,week_to,title,subtitle,cover,images,detail,price,sort}]},
只含已上架、不含网盘地址;兑换走 box_app /resources/{id}/claim( 服务端去对方取链接 + 扣豆,价格以对方为准)。
原来写死的 8 份资料( book/food… + 正文 body + 内容清单 PACK) 全部删除; 列表为空 / 本周没有 → 整个福利区块隐藏(对方要求)。
RES[id] = {img,title,desc,detail,images,price,wf,wt,tint}, RES_ORDER 按 sort。 */
const RES = { } ;
const RES _ORDER = [ ] ;
const TINTS = [ 'o' , 'g' , 'p' , 'b '] ;
const escR = t => String ( t == null ? '' : t ) . replace ( /[&<>"']/g , c => ( { '&' : '&' , '<' : '<' , '>' : '>' , '"' : '"' , "'" : ''' } [ c ] ) ) ;
const wkTxt = r => ( ! r . wf || ! r . wt || ( r . wf <= 1 && r . wt >= 42 ) ) ? '全孕期' : r . wf === r . wt ? '孕' + r . wf + '周' : '孕' + r . wf + '-' + r . wt + '周' ;
const priceTxt = r => r . price > 0 ? r . price + ' 兜豆' : '免费' ;
let perksLoaded = false ;
function loadPerks ( ) {
return f etch ( '/taidong/api/public/week-perks' ) . then ( r => r . ok ? r . json ( ) : null ) . then ( j => {
const items = ( ( j && j . items ) || [ ] ) . slice ( ) . sort ( ( a , b ) => ( a . sort || 0 ) - ( b . sort || 0 ) ) ;
Object . keys ( RES ) . forEach ( k => { delete RES [ k ] ; } ) ;
RES _ORDER . length = 0 ;
items . forEach ( ( it , n ) => {
const id = String ( it . id ) ;
RES [ id ] = {
img : it . cover || '' , title : it . title || ' ', desc : it . subtitle || '' , detail : it . detail || '' ,
images : Array . isArray ( it . images ) ? it . images : [ ] , price : + it . price || 0 ,
wf : + it . week _from || 0 , wt : + it . week _to || 0 , tint : TINTS [ n % 4 ]
} ;
RES _ORDER . push ( id ) ;
} ) ;
perksLoaded = true ;
} ) . catch ( ( ) => { perksLoaded = true ; } ) . then ( renderGiftShelf ) ;
}
/* 首页福利区:只出适用当前孕周的(含两端),按 sort; 一份都没有就整块藏 */
let giftShelfSig = ' ';
function renderGiftShelf ( ) {
const shelf = $ ( '.shelf.gift2' ) ;
if ( ! shelf || ! perksLoaded ) return ;
const wk = state . week || 0 ;
const keys = RES _ORDER . filter ( k => { const r = RES [ k ] ; return ! r . wf || ! r . wt || ( wk >= r . wf && wk <= r . wt ) ; } ) ;
const sig = wk + '|' + keys . join ( ',' ) + '|' + resGot . join ( ',' ) ;
if ( sig === giftShelfSig ) return ;
giftShelfSig = sig ;
const n = $ ( '#giftTotal' ) ; if ( n ) n . textContent = RES _ORDER . length ;
const m = $ ( '#rlTotal' ) ; if ( m ) m . textContent = RES _ORDER . length ;
shelf . style . display = keys . length ? '' : 'none' ;
if ( ! keys . length ) return ;
$ ( '.shelf-rail' , shelf ) . innerHTML = keys . map ( k => {
const r = RES [ k ] , got = resGot . indexOf ( k ) >= 0 ;
return '<button class="shelf-book ' + ( { o : 'sb-book' , g : 'sb-food' , p : 'sb-music' , b : 'sb-blue' } ) [ r . tint ] + ' ripple" data-open="detailRes" data-res="' + escR ( k ) + '">' +
'<span class="sb-tag">孕<span>' + wk + '</span>周专属</span>' +
'<img class="sb-cover" src="' + escR ( r . img ) + '" alt="" aria-hidden="true">' +
'<span class="sb-title">' + escR ( r . title ) + '</span>' +
'<span class="sb-desc">' + escR ( r . desc ) + '</span>' +
'<span class="sb-row"><span class="sb-faces" aria-hidden="true"></span><i class="sb-got">宝妈都在领</i>' +
'<span class="pill-free">' + ( got ? '已兑换' : r . price > 0 ? r . price + ' 豆兑' : '免费领' ) + '</span></span></button>' ;
} ) . join ( ' ') ;
$$ ( '.shelf-book' , shelf ) . forEach ( b => b . addEventListener ( 'click' , ( ) => openPanel ( 'detailRes' , b ) ) ) ;
if ( window . mbGiftFaces ) window . mbGiftFaces ( ) ;
}
/* 已兑换的 id( 来自 claim-status.resGot) ; 兑换成功后本地追加 */
const resGot = [ ] ;
function loadResGot ( ) {
const oid = hashParam ( 'openid' ) ;
@@ -2752,18 +2720,13 @@
. then ( r => r . ok ? r . json ( ) : null ) . then ( j => {
const x = j && j . result ;
if ( ! x ) return ;
if ( typeof x . price === 'number' && x . price > 0 ) RES _PRICE = x . price ;
resGot . length = 0 ;
( x . resGot || [ ] ) . forEach ( k => resGot . push ( k ) ) ;
syncResPrice ( ) ;
( x . resGot || [ ] ) . forEach ( k => resGot . push ( String ( k ) ) ) ;
( x . resFav || [ ] ) . forEach ( k => { if ( state . resFav . indexOf ( String ( k ) ) < 0 ) state . resFav . push ( String ( k ) ) ; } ) ;
renderGiftShelf ( ) ;
setRdGet ( ) ;
} ) . catch ( ( ) => { } ) ;
}
/* 首页书架 / 列表 / 详情页上所有「几兜豆」文案 */
function syncResPrice ( ) {
$$ ( '.shelf.gift2 .sb-row .pill-free' ) . forEach ( el => { el . textContent = RES _PRICE + ' 豆兑' ; } ) ;
$$ ( '.res-price-n' ) . forEach ( el => { el . textContent = RES _PRICE ; } ) ;
setRdGet ( ) ;
}
/* ⚠️ 2026-09-19( 9.19 需求 1.2):这里原来有 PAN_DEFAULT / PAN 两张**百度网盘
链接表**、panOf()、以及企业微信兑换码 WX_CODE / wxCodeOK()。
@@ -2774,20 +2737,14 @@
const isFav = k => state . resFav . indexOf ( k ) >= 0 ;
function resCardHTML ( k ) {
const r = RES [ k ] ;
/* ⚠️ 这里原来还有「领过的那一份」分支:整张卡加 .is-got、缩略图右上角打 ✓、
底行的「免费」标换成「已领 ✓」。9.19 需求取消「已领」概念后一并删除,
现在每张卡都是同一个样子(免费)。 */
return '<button class="res-item ripple"' +
' data-open="detailRes" data-res="' + k + '">' +
'<span class="ri-thumb ' + r . tint + '"><img src="' + r . img + '" alt=""></span>' +
'<span class="ri-body"><span class="ri-title">' + r . title + '</span>' +
'<span class="ri-desc">' + r . desc + '</span>' +
/* 底部这行:分类 + 适用孕周 + 右侧状态标。
⚠️ 状态标现在恒为「免费」(原来领过的会换成「已领 ✓」,已随「已领」概念删除)。 */
' data-open="detailRes" data-res="' + escR ( k ) + '">' +
'<span class="ri-thumb ' + r . tint + '"><img src="' + escR ( r. img ) + '" alt=""></span>' +
'<span class="ri-body"><span class="ri-title">' + escR ( r. title ) + '</span>' +
'<span class="ri-desc">' + escR ( r. desc ) + '</span>' +
'<span class="ri-row">' +
'<em class="ri-cat ">' + r . cat + '</em>' +
'<em class="ri-ga">' + r . meta [ 2 ] + '</em>' +
'<em class="pill-free">' + ( resGot . indexOf ( k ) >= 0 ? '已兑换' : RES _PRICE + ' 兜豆' ) + '</em>' +
'<em class="ri-ga ">' + wkTxt ( r ) + '</em>' +
'<em class="pill-free">' + ( resGot . indexOf ( k ) >= 0 ? '已兑换' : priceTxt ( r ) ) + '</em>' +
'</span></span></button>' ;
}
function bindResCards ( root ) {
@@ -2810,7 +2767,7 @@
/* fav 不是分类,是「只看收藏过的」,所以单走一支 */
const fav = state . resCat === 'fav' ;
const keys = fav ? RES _ORDER . filter ( isFav )
: RES _ORDER . filter ( k => state . resCat === 'all' || RES [ k ] . cat === state . resCat ) ;
: RES _ORDER . slice ( ) ; // 11-05 后台资料没有分类字段,分类 chip 已隐藏,只剩「全部 / 收藏」
$ ( '#resList' ) . innerHTML = keys . map ( resCardHTML ) . join ( '' ) ;
bindResCards ( $ ( '#resList' ) ) ;
$ ( '#resEmptyHint' ) . textContent = keys . length
@@ -2827,22 +2784,23 @@
} ) ) ;
function fillRes ( key ) {
const r = RES [ key ] || RES . book ;
state . resKey = RES [ key ] ? key : 'book' ;
const r = RES [ key ] || RES [ RES _ORDER [ 0 ] ] ;
if ( ! r ) return ;
state . resKey = RES [ key ] ? key : RES _ORDER [ 0 ] ;
$ ( '#rdImg' ) . src = r . img ;
$ ( '#rdCover' ) . className = 'rd-cover ' + r . tint ;
$ ( '#rdCat' ) . textContent = r . cat ;
$ ( '#rdCat' ) . textContent = wkTxt ( r ) ;
$ ( '#rdTitle' ) . textContent = r . title ;
$ ( '#rdDesc' ) . textContent = r . desc ;
$ ( '#rdMeta' ) . innerHTML = r . meta . map ( m => '<span>' + m + '</span>' ) . join ( '' ) ;
const pk = PACK [ state . resKey ] ;
$ ( '#rdPack' ) . innerHTML = pk ? '<h3 class="d-sec">这份资料里有什么</h3>' +
'<div class="rp-box"><div class="rp-fmt">' + pk . fmt . map ( f => '<span>' + f + '</span>' ) . join ( '' ) + '</div >' +
'<ul class="rp-list ">' + pk . item s . map ( t => '<li>' + t + '</li >' ) . join ( '' ) + '</ul>' +
'<p class="rp-how"><b class="res-price-n">' + RES _PRICE + '</b> 兜豆兑换,兑换后马上给你网盘地址和提取码,复制去下载;兑换过的再点也能看,不重复扣豆。</p></div>' +
'<h3 class="d-sec">内容抢先看</h3>' : '' ;
$ ( '#rdBody' ) . innerHTML = r . body
. map ( p => '<h4>' + p [ 0 ] + '</h4><p>' + p [ 1 ] + '</p>' ) . join ( '' ) ;
$ ( '#rdMeta' ) . innerHTML = '<span>适用 ' + wkTxt ( r ) + '</span><span>' + ( r . price > 0 ? r . price + ' 兜豆兑换' : '免费领取' ) + '</span>' ;
/* 「这份资料里有什么」= 后台填的多行详情(一行一段)+ 详情图 */
const paras = r . detail . split ( /\n+/ ) . map ( t => t . trim ( ) ) . filter ( Boolean ) ;
$ ( '#rdPack' ) . innerHTML = ( paras . length || r . images . length ) ? '<h3 class="d-sec">这份资料里有什么</h3 >' +
'<div class="rp-box ">' + para s . map ( t => '<p class="rp-p">' + escR ( t ) + '</p >' ) . join ( '' ) +
r . images . map ( u => '<img class="rp-img" src="' + escR ( u ) + '" alt="" loading="lazy">' ) . join ( '' ) +
'<p class="rp-how">' + ( r . price > 0 ? '<b>' + r . price + '</b> 兜豆兑换,' : '免费领取,' ) +
'马上给你网盘地址和提取码,复制去下载;领过的再点也能看' + ( r . price > 0 ? ',不重复扣豆' : '' ) + '。</p></div>' : '' ;
$ ( '#rdBody' ) . innerHTML = '' ;
$ ( '#rdMore' ) . innerHTML = RES _ORDER
. filter ( k => k !== state . resKey ) . slice ( 0 , 3 ) . map ( resCardHTML ) . join ( '' ) ;
bindResCards ( $ ( '#rdMore' ) ) ;
@@ -2903,8 +2861,8 @@
function setRdGet ( ) {
const b = $ ( '#rdGet' ) ;
if ( ! b ) return ;
const got = resGot . indexOf ( state . resKey ) >= 0 ;
b . textContent = got ? '查看网盘地址' : RES _PRICE + ' 兜豆兑换 ';
const got = resGot . indexOf ( state . resKey ) >= 0 , r = RES [ state . resKey ] ;
b . textContent = got ? '查看网盘地址' : r && r . price > 0 ? r . price + ' 兜豆兑换' : '免费领取 ';
b . classList . toggle ( 'is-got' , got ) ;
}
let resBusy = false ;
@@ -2923,11 +2881,12 @@
if ( resGot . indexOf ( key ) < 0 ) resGot . push ( key ) ;
setRdGet ( ) ;
renderResList ( state . resCat ) ;
renderGiftShelf ( ) ;
showPan ( key , x . pan , x . spent > 0 ? x . spent : 0 ) ;
if ( x . spent > 0 ) loadDou ( ) ; // 刷新「我的」页兜豆余额
} else if ( j && j . code === 409 && x . insufficient ) {
closeModal ( ) ;
$ ( '#rsShort' ) . textContent = x . short || RES _PRICE ;
$ ( '#rsShort' ) . textContent = x . short || ( RES [ key ] && RES [ key ] . price ) || '' ;
$ ( '#rsBal' ) . textContent = typeof x . balance === 'number' ? x . balance : 0 ;
openModal ( 'modalResShort' ) ;
} else {
@@ -2966,16 +2925,17 @@
$ ( '#rdGet' ) . addEventListener ( 'click' , ( ) => {
const key = state . resKey ;
if ( ! hashParam ( 'openid' ) ) { toast ( '请从小程序里打开后再兑换' ) ; return ; }
if ( resGot . indexOf ( key ) >= 0 ) { redeemRes ( key ) ; return ; } // 兑换过:直接拿链接,不扣豆
const r = RES [ key ] || { } ;
if ( resGot . indexOf ( key ) >= 0 || ! ( r . price > 0 ) ) { redeemRes ( key ) ; return ; } // 兑换过 / 免费:直接拿链接,不扣豆
$ ( '#rbName' ) . textContent = '《' + String ( r . title || '' ) . replace ( /[《》]/g , '' ) + '》' ;
$ ( '#rbPrice' ) . textContent = RES _PRICE ;
$ ( '#rbPrice' ) . textContent = r . price ;
const n = $ ( '#meDouN' ) && ! $ ( '#meDouBal' ) . classList . contains ( 'hide' ) ? $ ( '#meDouN' ) . textContent : '' ;
$ ( '#rbBal' ) . textContent = n ? '你现在有 ' + n + ' 兜豆' : '' ;
openModal ( 'modalResBuy' ) ;
} ) ;
$ ( '#rbOk' ) . addEventListener ( 'click' , ( ) => redeemRes ( state . resKey ) ) ;
$ ( '#rsGo' ) . addEventListener ( 'click' , ( ) => { closeModal ( ) ; openExchange ( ) ; } ) ;
loadPerks ( ) ;
loadResGot ( ) ;
/* ================= 企业微信顾问弹窗(单态) =================
@@ -6069,7 +6029,7 @@
j ( base + 'content?key=about' ) ,
] ) . then ( function ( rs ) {
var rr = rs [ 0 ] , rec = rs [ 1 ] , ct = rs [ 2 ] ;
if ( rr && rr . code === 200 && rr . result ) _ _applyResources ( rr . result . items ) ;
/* 11-05 资料改由数胎动后台提供( loadPerks) , box_app 那份内置 8 条不再覆盖 RES */
if ( rec && rec . code === 200 && rec . result ) _ _applyRecords ( rec . result ) ;
if ( ct && ct . code === 200 && ct . result ) _ _applyAbout ( ct . result ) ;
} ) . catch ( function ( ) { /* 静默回退内置值 */ } ) ;