Files
Mycontent/miniprogram/pages/read/read.wxml
2026-04-13 14:32:32 +08:00

510 lines
29 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--pages/read/read.wxml-->
<!--卡若创业派对 - 阅读页-->
<view class="page">
<!-- 阅读进度条 -->
<view class="progress-bar-fixed" style="top: {{statusBarHeight}}px;">
<view class="progress-fill" style="width: {{readingProgress}}%;"></view>
</view>
<!-- 顶部导航栏 -->
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
<view class="nav-content">
<view class="nav-back" bindtap="goBack">
<icon name="chevron-left" size="44" color="#ffffff" customClass="back-arrow"></icon>
</view>
<view class="nav-info">
<text class="nav-chapter" wx:if="{{section.title || chapterTitle}}">{{section.title || chapterTitle}}</text>
</view>
<view class="nav-right-placeholder"></view>
</view>
</view>
<!-- 导航栏占位 -->
<view class="nav-placeholder" style="height: {{statusBarHeight + 44}}px;"></view>
<!-- 阅读内容 -->
<view class="read-content">
<!-- 骨架屏:加载中时展示,模拟章节标题+正文布局 -->
<view class="skeleton-wrap" wx:if="{{accessState === 'unknown' && loading}}">
<view class="skeleton-header">
<view class="skeleton-meta"></view>
<view class="skeleton-title"></view>
</view>
<view class="skeleton-lines">
<view class="skeleton skeleton-1"></view>
<view class="skeleton skeleton-2"></view>
<view class="skeleton skeleton-3"></view>
<view class="skeleton skeleton-4"></view>
<view class="skeleton skeleton-5"></view>
<view class="skeleton skeleton-6"></view>
<view class="skeleton skeleton-7"></view>
<view class="skeleton skeleton-8"></view>
</view>
</view>
<!-- 章节标题(加载完成后) -->
<view class="chapter-header" wx:elif="{{!loading}}">
<view class="chapter-meta">
<text class="chapter-id">{{section.id}}</text>
<text class="tag tag-free" wx:if="{{section.isFree}}">免费</text>
</view>
<text class="chapter-title" user-select>{{section.title}}</text>
</view>
<!-- 完整内容 - 免费或已购买 -->
<view class="article" wx:if="{{accessState === 'free' || accessState === 'unlocked_purchased'}}">
<block wx:for="{{contentSegments}}" wx:key="index">
<view wx:if="{{item.length === 1 && item[0].type === 'heading'}}" class="seg-heading seg-h{{item[0].level}}">
<text user-select>{{item[0].text}}</text>
</view>
<view wx:elif="{{item.length === 1 && item[0].type === 'quote'}}" class="seg-quote">
<text user-select>{{item[0].text}}</text>
</view>
<scroll-view wx:elif="{{item.length === 1 && item[0].type === 'table'}}" scroll-x class="table-scroll">
<view class="content-table">
<view class="table-row table-header-row" wx:if="{{item[0].headers.length}}">
<text class="table-cell table-header-cell" wx:for="{{item[0].headers}}" wx:key="index" wx:for-item="hdr">{{hdr}}</text>
</view>
<view class="table-row" wx:for="{{item[0].rows}}" wx:key="index" wx:for-item="row">
<text class="table-cell" wx:for="{{row}}" wx:key="index" wx:for-item="cell">{{cell}}</text>
</view>
</view>
</scroll-view>
<view wx:elif="{{item.length === 1 && item[0].type === 'listItem'}}" class="seg-list-item">
<text class="seg-list-marker" wx:if="{{item[0].ordered}}">{{item[0].number}}.</text>
<text class="seg-list-marker" wx:else>•</text>
<text class="seg-list-text" user-select>{{item[0].text}}</text>
</view>
<view wx:elif="{{item.length === 1 && item[0].type === 'image'}}" class="paragraph">
<image class="content-image" src="{{item[0].src}}" mode="widthFix" show-menu-by-longpress bindtap="onImageTap" data-src="{{item[0].src}}"></image>
</view>
<view wx:else class="paragraph">
<text user-select><block wx:for="{{item}}" wx:key="index" wx:for-item="seg"><text wx:if="{{seg.type === 'text'}}">{{seg.text}}</text><text wx:elif="{{seg.type === 'mention'}}" class="mention" bindtap="onMentionTap" data-user-id="{{seg.userId}}" data-nickname="{{seg.nickname}}">{{seg.mentionDisplay}}</text><text wx:elif="{{seg.type === 'linkTag'}}" class="link-tag" bindtap="onLinkTagTap" data-url="{{seg.url}}" data-label="{{seg.label}}" data-tag-type="{{seg.tagType}}" data-page-path="{{seg.pagePath}}" data-tag-id="{{seg.tagId}}" data-app-id="{{seg.appId}}" data-mp-key="{{seg.mpKey}}">#{{seg.label}}</text></block></text>
<block wx:for="{{item}}" wx:key="index" wx:for-item="seg">
<image wx:if="{{seg.type === 'image'}}" class="content-image" src="{{seg.src}}" mode="widthFix" show-menu-by-longpress bindtap="onImageTap" data-src="{{seg.src}}"></image>
</block>
</view>
</block>
<!-- 章节导航 -->
<view class="chapter-nav">
<view class="nav-buttons">
<view
class="nav-btn nav-prev {{!prevSection ? 'nav-disabled' : ''}}"
bindtap="goToPrev"
wx:if="{{prevSection}}"
>
<text class="btn-label">上一篇</text>
<text class="btn-title">{{prevSection.title}}</text>
</view>
<view class="nav-btn-placeholder" wx:else></view>
<view
class="nav-btn nav-next"
bindtap="goToNext"
wx:if="{{nextSection}}"
>
<text class="btn-label">下一篇</text>
<view class="btn-row">
<text class="btn-title">{{nextSection.title}}</text>
<icon name="chevron-right" size="28" color="#00CED1" customClass="btn-arrow"></icon>
</view>
</view>
<view class="nav-btn nav-end" wx:else>
<text class="btn-end-text">已是最后一篇</text>
</view>
</view>
<!-- 分享区:仅好友/海报/代付;完整小程序发圈见右下角悬浮钮 -->
<view class="action-section">
<view class="action-row-inline">
<button plain class="action-share-native action-tile-unified" open-type="share" hover-class="action-share-native-hover" hover-stop-propagation>
<icon name="share" size="32" color="#00CED1" customClass="action-icon-small"></icon>
<text class="action-text-small">分享给好友</text>
</button>
<button plain class="action-share-native action-tile-unified" bindtap="generatePoster" hover-class="action-share-native-hover" hover-stop-propagation>
<icon name="image" size="32" color="#00CED1" customClass="action-icon-small"></icon>
<text class="action-text-small">生成海报</text>
</button>
<button plain class="action-share-native action-tile-unified" bindtap="showGiftShareModal" wx:if="{{isLoggedIn && !auditMode}}" hover-class="action-share-native-hover" hover-stop-propagation>
<icon name="gift" size="32" color="#00CED1" customClass="action-icon-small"></icon>
<text class="action-text-small">代付分享</text>
</button>
</view>
<view class="share-tip-inline" wx:if="{{!auditMode}}">
<text class="share-tip-text">{{readUi.shareTipLine}}</text>
</view>
</view>
</view>
</view>
<!-- 预览内容 + 付费墙 - 未登录(规则更新:前端按百分比裁切显示,后端不截断正文) -->
<view class="article preview" wx:if="{{accessState === 'locked_not_login'}}">
<view class="preview-wrap">
<view
id="previewContentMeasure"
class="preview-body"
style="{{previewMaxHeightPx > 0 ? ('max-height:' + previewMaxHeightPx + 'px; overflow:hidden;') : ''}}"
>
<block wx:for="{{contentSegments}}" wx:key="index">
<view wx:if="{{item.length === 1 && item[0].type === 'heading'}}" class="seg-heading seg-h{{item[0].level}}"><text user-select>{{item[0].text}}</text></view>
<view wx:elif="{{item.length === 1 && item[0].type === 'quote'}}" class="seg-quote"><text user-select>{{item[0].text}}</text></view>
<scroll-view wx:elif="{{item.length === 1 && item[0].type === 'table'}}" scroll-x class="table-scroll"><view class="content-table"><view class="table-row table-header-row" wx:if="{{item[0].headers.length}}"><text class="table-cell table-header-cell" wx:for="{{item[0].headers}}" wx:key="index" wx:for-item="hdr">{{hdr}}</text></view><view class="table-row" wx:for="{{item[0].rows}}" wx:key="index" wx:for-item="row"><text class="table-cell" wx:for="{{row}}" wx:key="index" wx:for-item="cell">{{cell}}</text></view></view></scroll-view>
<view wx:elif="{{item.length === 1 && item[0].type === 'listItem'}}" class="seg-list-item"><text class="seg-list-marker" wx:if="{{item[0].ordered}}">{{item[0].number}}.</text><text class="seg-list-marker" wx:else>•</text><text class="seg-list-text" user-select>{{item[0].text}}</text></view>
<view wx:elif="{{item.length === 1 && item[0].type === 'image'}}" class="paragraph"><image class="content-image" src="{{item[0].src}}" mode="widthFix" show-menu-by-longpress bindtap="onImageTap" data-src="{{item[0].src}}"></image></view>
<view wx:else class="paragraph"><text user-select><block wx:for="{{item}}" wx:key="index" wx:for-item="seg"><text wx:if="{{seg.type === 'text'}}">{{seg.text}}</text><text wx:elif="{{seg.type === 'mention'}}" class="mention" bindtap="onMentionTap" data-user-id="{{seg.userId}}" data-nickname="{{seg.nickname}}">{{seg.mentionDisplay}}</text><text wx:elif="{{seg.type === 'linkTag'}}" class="link-tag" bindtap="onLinkTagTap" data-url="{{seg.url}}" data-label="{{seg.label}}" data-tag-type="{{seg.tagType}}" data-page-path="{{seg.pagePath}}" data-tag-id="{{seg.tagId}}" data-app-id="{{seg.appId}}" data-mp-key="{{seg.mpKey}}">#{{seg.label}}</text></block></text><block wx:for="{{item}}" wx:key="index" wx:for-item="seg"><image wx:if="{{seg.type === 'image'}}" class="content-image" src="{{seg.src}}" mode="widthFix" show-menu-by-longpress bindtap="onImageTap" data-src="{{seg.src}}"></image></block></view>
</block>
</view>
<view class="fade-mask"></view>
</view>
<!-- 付费墙 - 未登录(营销主标题与「购买本章」同框体系) -->
<view class="paywall {{readSinglePageMode ? 'paywall--single-preview paywall--compact-sp' : ''}}">
<view class="paywall-icon paywall-icon--compact" wx:if="{{readSinglePageMode}}"><icon name="lock" size="64" color="#00CED1"></icon></view>
<view class="paywall-icon" wx:elif="{{!readSinglePageMode}}"><icon name="lock" size="80" color="#00CED1"></icon></view>
<block wx:if="{{readSinglePageMode}}">
<view class="paywall-marketing-box">
<view class="paywall-title-row paywall-title-row--boxed">
<text class="paywall-title paywall-title--inline">解锁完整内容,分享得到</text>
<text class="paywall-highlight-pct">{{shareRate || 90}}</text>
<text class="paywall-title paywall-title--inline">% 收益</text>
</view>
</view>
<view class="purchase-options paywall-sp-compact-btns" wx:if="{{!auditMode}}">
<view class="purchase-btn purchase-section purchase-btn--fulltext purchase-btn--compact-sp" bindtap="onUnlockTapInSinglePage">
<text class="btn-label btn-label--block">{{readUi.singlePagePayButtonText}}</text>
</view>
</view>
<view class="paywall-audit-tip" wx:if="{{auditMode}}">审核中,暂不支持购买</view>
</block>
<block wx:else>
<view class="paywall-marketing-box" wx:if="{{!auditMode}}">
<view class="paywall-title-row paywall-title-row--boxed">
<text class="paywall-title paywall-title--inline">解锁完整内容,分享得到</text>
<text class="paywall-highlight-pct">{{shareRate || 90}}</text>
<text class="paywall-title paywall-title--inline">% 收益</text>
</view>
</view>
<view class="purchase-options" wx:if="{{!auditMode}}">
<view class="purchase-btn purchase-section purchase-section--primary" bindtap="handlePurchaseSection">
<text class="btn-label">购买本章</text>
<text class="btn-price">¥{{section && section.price != null ? section.price : sectionPrice}}</text>
</view>
</view>
<view class="login-btn" bindtap="showLoginModal" style="margin-top:12px">
<text class="login-btn-text">手机号登录后购买</text>
</view>
</block>
</view>
<!-- 章节导航 -->
<view class="chapter-nav chapter-nav-locked">
<view class="nav-buttons">
<view
class="nav-btn nav-prev {{!prevSection ? 'nav-disabled' : ''}}"
bindtap="goToPrev"
wx:if="{{prevSection}}"
>
<text class="btn-label">上一篇</text>
<text class="btn-title">章节 {{prevSection.id}}</text>
</view>
<view class="nav-btn-placeholder" wx:else></view>
<view
class="nav-btn nav-next"
bindtap="goToNext"
wx:if="{{nextSection}}"
>
<text class="btn-label">下一篇</text>
<view class="btn-row">
<text class="btn-title">{{nextSection.title}}</text>
<icon name="chevron-right" size="28" color="#00CED1" customClass="btn-arrow"></icon>
</view>
</view>
<view class="nav-btn nav-end" wx:else>
<text class="btn-end-text">已是最后一篇</text>
</view>
</view>
</view>
</view>
<!-- 预览内容 + 付费墙 - 已登录未购买 -->
<view class="article preview" wx:if="{{accessState === 'locked_not_purchased'}}">
<view class="preview-wrap">
<view
id="previewContentMeasure"
class="preview-body"
style="{{previewMaxHeightPx > 0 ? ('max-height:' + previewMaxHeightPx + 'px; overflow:hidden;') : ''}}"
>
<block wx:for="{{contentSegments}}" wx:key="index">
<view wx:if="{{item.length === 1 && item[0].type === 'heading'}}" class="seg-heading seg-h{{item[0].level}}"><text user-select>{{item[0].text}}</text></view>
<view wx:elif="{{item.length === 1 && item[0].type === 'quote'}}" class="seg-quote"><text user-select>{{item[0].text}}</text></view>
<scroll-view wx:elif="{{item.length === 1 && item[0].type === 'table'}}" scroll-x class="table-scroll"><view class="content-table"><view class="table-row table-header-row" wx:if="{{item[0].headers.length}}"><text class="table-cell table-header-cell" wx:for="{{item[0].headers}}" wx:key="index" wx:for-item="hdr">{{hdr}}</text></view><view class="table-row" wx:for="{{item[0].rows}}" wx:key="index" wx:for-item="row"><text class="table-cell" wx:for="{{row}}" wx:key="index" wx:for-item="cell">{{cell}}</text></view></view></scroll-view>
<view wx:elif="{{item.length === 1 && item[0].type === 'listItem'}}" class="seg-list-item"><text class="seg-list-marker" wx:if="{{item[0].ordered}}">{{item[0].number}}.</text><text class="seg-list-marker" wx:else>•</text><text class="seg-list-text" user-select>{{item[0].text}}</text></view>
<view wx:elif="{{item.length === 1 && item[0].type === 'image'}}" class="paragraph"><image class="content-image" src="{{item[0].src}}" mode="widthFix" show-menu-by-longpress bindtap="onImageTap" data-src="{{item[0].src}}"></image></view>
<view wx:else class="paragraph"><text user-select><block wx:for="{{item}}" wx:key="index" wx:for-item="seg"><text wx:if="{{seg.type === 'text'}}">{{seg.text}}</text><text wx:elif="{{seg.type === 'mention'}}" class="mention" bindtap="onMentionTap" data-user-id="{{seg.userId}}" data-nickname="{{seg.nickname}}">{{seg.mentionDisplay}}</text><text wx:elif="{{seg.type === 'linkTag'}}" class="link-tag" bindtap="onLinkTagTap" data-url="{{seg.url}}" data-label="{{seg.label}}" data-tag-type="{{seg.tagType}}" data-page-path="{{seg.pagePath}}" data-tag-id="{{seg.tagId}}" data-app-id="{{seg.appId}}" data-mp-key="{{seg.mpKey}}">#{{seg.label}}</text></block></text><block wx:for="{{item}}" wx:key="index" wx:for-item="seg"><image wx:if="{{seg.type === 'image'}}" class="content-image" src="{{seg.src}}" mode="widthFix" show-menu-by-longpress bindtap="onImageTap" data-src="{{seg.src}}"></image></block></view>
</block>
</view>
<view class="fade-mask"></view>
</view>
<!-- 付费墙 - 已登录未购买:营销框 + 双按钮(浏览满 N 篇凸显读书会) -->
<view class="paywall {{readSinglePageMode ? 'paywall--single-preview paywall--compact-sp' : ''}} {{(!readSinglePageMode && ((paywall365Primary && showFullBookCta) || pay365AnchorVisible)) ? 'paywall--pay365-focus' : ''}}">
<view class="paywall-icon paywall-icon--compact" wx:if="{{readSinglePageMode}}"><icon name="lock" size="64" color="#00CED1"></icon></view>
<view class="paywall-icon" wx:elif="{{!readSinglePageMode && !pay365AnchorVisible}}"><icon name="lock" size="80" color="#00CED1"></icon></view>
<block wx:if="{{readSinglePageMode}}">
<view class="paywall-marketing-box">
<view class="paywall-title-row paywall-title-row--boxed">
<text class="paywall-title paywall-title--inline">解锁完整内容,分享得到</text>
<text class="paywall-highlight-pct">{{shareRate || 90}}</text>
<text class="paywall-title paywall-title--inline">% 收益</text>
</view>
</view>
<view class="purchase-options paywall-sp-compact-btns" wx:if="{{!auditMode}}">
<view class="purchase-btn purchase-section purchase-btn--fulltext purchase-btn--compact-sp" bindtap="onUnlockTapInSinglePage">
<text class="btn-label btn-label--block">{{readUi.singlePagePayButtonText}}</text>
</view>
</view>
<view class="paywall-audit-tip" wx:if="{{auditMode}}">审核中,暂不支持购买</view>
</block>
<block wx:else>
<view class="paywall-marketing-box" wx:if="{{!auditMode}}">
<view class="paywall-title-row paywall-title-row--boxed">
<text class="paywall-title paywall-title--inline">解锁完整内容,分享得到</text>
<text class="paywall-highlight-pct">{{shareRate || 90}}</text>
<text class="paywall-title paywall-title--inline">% 收益</text>
</view>
</view>
<view class="pay365-anchor-row" wx:if="{{pay365AnchorVisible && !readSinglePageMode}}" id="pay365-marketing-anchor" bindtap="onPay365AnchorTap">
<text class="pay365-anchor-row-badge">365</text>
<text class="pay365-anchor-row-text">{{pay365AnchorLabel}}</text>
<text class="pay365-anchor-row-chevron"></text>
</view>
<view class="purchase-options {{paywall365Primary && showFullBookCta ? 'purchase-options--365-first' : ''}}" wx:if="{{!auditMode}}">
<view class="{{sectionPurchaseBtnClass}}" bindtap="handlePurchaseSection">
<text class="btn-label">购买本章</text>
<text class="btn-price">¥{{section && section.price != null ? section.price : sectionPrice}}</text>
</view>
<view class="{{fullbookPurchaseBtnClass}}" bindtap="handlePurchaseFullBook" wx:if="{{showFullBookCta}}">
<text class="btn-label">加入读书会</text>
<text class="btn-price">¥{{fullBookPrice}}</text>
</view>
</view>
<view class="paywall-audit-tip" wx:if="{{auditMode}}">审核中,暂不支持购买</view>
</block>
</view>
<!-- 章节导航 -->
<view class="chapter-nav chapter-nav-locked">
<view class="nav-buttons">
<view
class="nav-btn nav-prev {{!prevSection ? 'nav-disabled' : ''}}"
bindtap="goToPrev"
wx:if="{{prevSection}}"
>
<text class="btn-label">上一篇</text>
<text class="btn-title">章节 {{prevSection.id}}</text>
</view>
<view class="nav-btn-placeholder" wx:else></view>
<view
class="nav-btn nav-next"
bindtap="goToNext"
wx:if="{{nextSection}}"
>
<text class="btn-label">下一篇</text>
<view class="btn-row">
<text class="btn-title">{{nextSection.title}}</text>
<icon name="chevron-right" size="28" color="#00CED1" customClass="btn-arrow"></icon>
</view>
</view>
<view class="nav-btn nav-end" wx:else>
<text class="btn-end-text">已是最后一篇</text>
</view>
</view>
</view>
</view>
<!-- 错误状态 - 网络异常 -->
<view class="article preview" wx:if="{{accessState === 'error'}}">
<view class="paragraph" wx:for="{{previewParagraphs}}" wx:key="index" wx:if="{{item}}">
<text user-select>{{item}}</text>
</view>
<!-- 渐变遮罩 -->
<view class="fade-mask"></view>
<!-- 错误提示 -->
<view class="paywall">
<view class="paywall-icon"><icon name="warning" size="80" color="#ff9500"></icon></view>
<text class="paywall-title">网络异常</text>
<text class="paywall-desc">无法确认权限,请检查网络后重试</text>
<view class="login-btn" bindtap="handleRetry">
<text class="login-btn-text">重新加载</text>
</view>
</view>
</view>
</view>
<!-- 海报生成弹窗:居中 + z-index 高于右下角悬浮,避免「空白」错觉 -->
<view class="modal-overlay modal-overlay-center" wx:if="{{showPosterModal}}" bindtap="closePosterModal">
<view class="modal-content modal-content-center poster-modal" catchtap="stopPropagation">
<view class="modal-header">
<text class="modal-title">生成海报</text>
<view class="modal-close" bindtap="closePosterModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
</view>
<!-- 海报预览 -->
<view class="poster-preview">
<canvas type="2d" id="posterCanvas" class="poster-canvas" style="width: 300px; height: 450px;"></canvas>
</view>
<view class="poster-actions">
<view class="poster-btn btn-save" bindtap="savePoster">
<icon name="save" size="36" color="#8e8e93" customClass="btn-icon"></icon>
<text>保存到相册</text>
</view>
</view>
<text class="poster-tip">长按海报可直接分享给好友</text>
</view>
</view>
<!-- 代付分享弹窗:阅读页内发起代付并支付 -->
<view class="modal-overlay modal-overlay-center" wx:if="{{showGiftModal}}" bindtap="closeGiftModal">
<view class="modal-content modal-content-center gift-modal-v2" catchtap="stopPropagation">
<view class="modal-header">
<text class="modal-title">{{giftPaid ? '代付已完成' : '生成代付链接'}}</text>
<view class="modal-close" bindtap="closeGiftModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
</view>
<view class="gift-article-card">
<text class="gift-article-title">{{section.title || '代付商品'}}</text>
<text class="gift-article-desc" wx:if="{{section.desc}}">{{section.desc}}</text>
</view>
<view wx:if="{{!giftPaid}}">
<text class="gift-label">选择代付名额数</text>
<view class="gift-spots-grid">
<view class="gift-spot-btn {{giftQuantity===6?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="6">6</view>
<view class="gift-spot-btn {{giftQuantity===30?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="30">30</view>
<view class="gift-spot-btn {{giftQuantity===100?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="100">100</view>
<view class="gift-spot-btn {{giftQuantity===1000?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="1000">1000</view>
</view>
<view class="gift-price-box">
<text class="gift-price-label">待支付总价格</text>
<view class="gift-price-row">
<text class="gift-price-formula">¥{{giftUnitPrice}} × {{giftQuantity}} =</text>
<text class="gift-price-total">¥{{giftTotalPrice}}</text>
</view>
</view>
<button class="gift-pay-btn" bindtap="confirmGiftPay" disabled="{{giftPaying}}">
{{giftPaying ? '支付中...' : '确认并支付'}}
</button>
<view class="gift-cancel-text" bindtap="closeGiftModal">取消</view>
</view>
<view wx:else class="gift-paid-wrap">
<text class="gift-paid-tip">支付成功,点击下方按钮直接分享给好友。好友打开阅读页将自动领取并解锁。</text>
<button class="gift-share-btn" open-type="share" data-gift="1" data-request-sn="{{giftRequestSn}}">
发送给好友
</button>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件) -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可购买章节、解锁更多内容"
showPrivacyModal="{{showPrivacyModal}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 支付中提示 -->
<view class="modal-overlay" wx:if="{{isPaying}}" catchtap="">
<view class="loading-box">
<view class="loading-spinner"></view>
<text class="loading-text">支付处理中...</text>
</view>
</view>
<!-- 单页预览(朋友圈):指向底栏「前往小程序」,字少;完整小程序仍保留发圈悬浮钮 -->
<view class="singlepage-launch-pointer" wx:if="{{readSinglePageMode && momentsPaywallExpanded}}" aria-hidden="true">
<view class="singlepage-launch-pointer__arrow">↓</view>
</view>
<view class="fab-share-moments" wx:if="{{!readSinglePageMode}}" bindtap="shareToMoments" hover-class="fab-share-moments-hover" aria-label="分享到朋友圈">
<icon name="share" size="44" color="#ffffff" customClass="fab-share-moments-icon"></icon>
</view>
<!-- 分享到朋友圈 自定义弹窗 -->
<view class="modal-overlay modal-overlay-center" wx:if="{{showMomentsModal}}" bindtap="closeMomentsModal">
<view class="modal-content modal-content-center moments-modal" catchtap="stopPropagation">
<view class="modal-header">
<text class="modal-title">分享到朋友圈</text>
<view class="modal-close" bindtap="closeMomentsModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
</view>
<view class="moments-earn-banner">
<text class="moments-earn-text">好友购买,你获得</text>
<text class="moments-earn-pct">{{shareRate || 90}}%</text>
<text class="moments-earn-text">收益</text>
</view>
<view class="moments-steps">
<view class="moments-step">
<view class="moments-step-num">1</view>
<text class="moments-step-text">点击下方按钮复制文案</text>
</view>
<view class="moments-step">
<view class="moments-step-num">2</view>
<text class="moments-step-text">点击右上角「···」→「分享到朋友圈」</text>
</view>
<view class="moments-step">
<view class="moments-step-num">3</view>
<text class="moments-step-text">粘贴文案发布即可</text>
</view>
</view>
<view class="moments-copy-btn {{momentsCopied ? 'moments-copy-btn--done' : ''}}" bindtap="onMomentsCopy">
<text>{{momentsCopied ? '已复制,去发朋友圈' : '复制发圈文案'}}</text>
</view>
</view>
</view>
<!-- 朋友圈单页预览:点「支付解锁全文」→ 半透明遮罩 + 底部提示 + 向下箭头指向系统「前往小程序」底栏 -->
<view
class="moments-launch-guide-mask"
wx:if="{{readSinglePageMode && showMomentsLaunchGuideModal}}"
bindtap="closeMomentsLaunchGuideModal"
>
<view class="moments-launch-guide-sheet" catchtap="stopPropagation">
<text class="moments-launch-guide-text">请点击下方「前往小程序」查看全文</text>
<view class="moments-launch-guide-arrow-wrap" aria-hidden="true">
<text class="moments-launch-guide-arrow">↓</text>
</view>
</view>
</view>
<!-- 已解锁阅读时365 营销锚点(规则 revealMode=anchor点击后再弹窗确认支付 -->
<view
class="pay365-anchor-float"
wx:if="{{pay365AnchorVisible && !readSinglePageMode && (accessState === 'free' || accessState === 'unlocked_purchased')}}"
bindtap="onPay365AnchorTap"
>
<text class="pay365-anchor-float-text">{{pay365AnchorLabel}}</text>
<text class="pay365-anchor-float-chevron"></text>
</view>
</view>