小说小程序前端代码仓库(小程序)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

398 lines
8.8 KiB

  1. <template>
  2. <view class="subscription-popup" :class="{'dark-mode': isDarkMode}">
  3. <uv-popup ref="popup"
  4. mode="bottom"
  5. :closeOnClickOverlay="false"
  6. @maskClick="$emit('maskClick')"
  7. :customStyle="popupStyle">
  8. <view class="content theme-transition">
  9. <view class="popup-title theme-transition">{{ title }}</view>
  10. <!-- 默认订阅界面 -->
  11. <view v-if="!showBatchDialog" class="popup-btns">
  12. <button class="popup-btn theme-transition" @click="handleSubscribe">订阅本章</button>
  13. <button class="popup-btn theme-transition" @click="handleVideoUnlock">观看视频解锁</button>
  14. <button class="popup-btn theme-transition" @click="showBatchSubscribe">批量订阅</button>
  15. </view>
  16. <!-- 批量订阅界面 -->
  17. <view v-else class="batch-subscribe-content">
  18. <view class="batch-title">选择订阅章节数量</view>
  19. <view class="batch-info">
  20. <text>从当前章节开始可订阅 {{ availableChaptersCount }} </text>
  21. </view>
  22. <view v-if="availableChaptersCount === 0" class="no-chapters-tip">
  23. <text>暂无需要付费的章节</text>
  24. </view>
  25. <view v-else>
  26. <view class="batch-current-info">
  27. <text>连续订阅 {{ batchCount }} </text>
  28. </view>
  29. <view class="batch-counter">
  30. <button class="counter-btn" @click="decreaseBatchCount" :disabled="batchCount <= 1">-</button>
  31. <input type="number" v-model="batchCount" class="counter-input"
  32. :max="maxBatchCount" @input="validateBatchCount" />
  33. <button class="counter-btn" @click="increaseBatchCount" :disabled="batchCount >= maxBatchCount">+</button>
  34. </view>
  35. </view>
  36. <view class="batch-btns">
  37. <button class="batch-cancel-btn theme-transition" @click="cancelBatchSubscribe">取消</button>
  38. <button class="batch-confirm-btn theme-transition"
  39. @click="handleBatchSubscribe"
  40. :disabled="availableChaptersCount === 0">确认订阅</button>
  41. </view>
  42. </view>
  43. </view>
  44. </uv-popup>
  45. </view>
  46. </template>
  47. <script>
  48. import themeMixin from '@/mixins/themeMode.js'
  49. export default {
  50. name: 'subscriptionPopup',
  51. mixins: [themeMixin],
  52. props: {
  53. title: {
  54. type: String,
  55. default: '这是付费章节 需要订阅后才能阅读'
  56. },
  57. chapterList: {
  58. type: Array,
  59. default: () => []
  60. },
  61. currentChapter: {
  62. type: Object,
  63. default: () => ({})
  64. },
  65. currentIndex: {
  66. type: Number,
  67. default: 0
  68. },
  69. bookId: {
  70. type: [String, Number],
  71. default: ''
  72. }
  73. },
  74. data() {
  75. return {
  76. showBatchDialog: false,
  77. batchCount: 5
  78. }
  79. },
  80. computed: {
  81. popupStyle() {
  82. return {
  83. 'background': this.isDarkMode ? '#232323' : '#fff',
  84. 'padding': '48rpx 32rpx',
  85. 'text-align': 'center',
  86. 'border-radius': '24rpx',
  87. 'min-width': '500rpx'
  88. }
  89. },
  90. // 计算从当前章节开始可以订阅的章节数量
  91. availableChaptersCount() {
  92. if (!this.chapterList.length || this.currentIndex < 0) return 0;
  93. let count = 0;
  94. for (let i = this.currentIndex; i < this.chapterList.length; i++) {
  95. const chapter = this.chapterList[i];
  96. if (chapter.isPay === 'Y' && !chapter.pay) {
  97. count++;
  98. }
  99. }
  100. return count;
  101. },
  102. // 限制批量订阅数量不能超过可订阅章节数
  103. maxBatchCount() {
  104. return Math.max(1, this.availableChaptersCount);
  105. }
  106. },
  107. methods: {
  108. // 打开弹窗
  109. open() {
  110. this.$refs.popup.open();
  111. },
  112. // 关闭弹窗
  113. close() {
  114. this.$refs.popup.close();
  115. },
  116. // 处理订阅按钮点击
  117. handleSubscribe() {
  118. this.$emit('subscribe');
  119. this.close();
  120. },
  121. // 处理视频解锁按钮点击
  122. handleVideoUnlock() {
  123. this.$emit('videoUnlock');
  124. this.close();
  125. },
  126. // 显示批量订阅选择界面
  127. showBatchSubscribe() {
  128. // 根据可订阅章节数设置合理的默认值
  129. this.batchCount = Math.min(5, this.maxBatchCount);
  130. this.showBatchDialog = true;
  131. },
  132. // 取消批量订阅
  133. cancelBatchSubscribe() {
  134. this.showBatchDialog = false;
  135. },
  136. // 处理批量订阅
  137. handleBatchSubscribe() {
  138. this.$emit('batchSubscribe', this.batchCount);
  139. this.showBatchDialog = false;
  140. },
  141. // 减少批量订阅数量
  142. decreaseBatchCount() {
  143. if (this.batchCount > 1) {
  144. this.batchCount--;
  145. }
  146. },
  147. // 增加批量订阅数量
  148. increaseBatchCount() {
  149. if (this.batchCount < this.maxBatchCount) {
  150. this.batchCount++;
  151. }
  152. },
  153. // 验证批量订阅数量
  154. validateBatchCount() {
  155. this.batchCount = Math.max(1, Math.min(this.maxBatchCount, parseInt(this.batchCount)));
  156. }
  157. }
  158. }
  159. </script>
  160. <style lang="scss" scoped>
  161. .subscription-popup {
  162. .content {
  163. .popup-title {
  164. font-size: 32rpx;
  165. font-weight: bold;
  166. color: #222;
  167. margin-bottom: 24rpx;
  168. word-wrap: break-word;
  169. white-space: normal;
  170. }
  171. .popup-desc {
  172. font-size: 26rpx;
  173. color: #999;
  174. margin-bottom: 40rpx;
  175. word-wrap: break-word;
  176. white-space: normal;
  177. }
  178. .popup-btns {
  179. display: flex;
  180. flex-wrap: wrap;
  181. justify-content: center;
  182. gap: 24rpx;
  183. .popup-btn {
  184. background: #ff9800;
  185. color: #fff;
  186. border-radius: 32rpx;
  187. font-size: 28rpx;
  188. padding: 0 32rpx;
  189. border: none;
  190. margin-bottom: 16rpx;
  191. word-break: keep-all;
  192. &.popup-btn-video {
  193. background: #fff3e0;
  194. color: #ff9800;
  195. border: 1px solid #ff9800;
  196. }
  197. &.popup-btn-batch {
  198. background: #fff;
  199. color: #ff9800;
  200. border: 1px solid #ff9800;
  201. }
  202. }
  203. }
  204. .batch-subscribe-content {
  205. .batch-title {
  206. font-size: 28rpx;
  207. color: #333;
  208. margin-bottom: 16rpx;
  209. text-align: center;
  210. }
  211. .batch-info {
  212. font-size: 24rpx;
  213. color: #666;
  214. margin-bottom: 32rpx;
  215. text-align: center;
  216. }
  217. .batch-current-info {
  218. font-size: 24rpx;
  219. color: #666;
  220. text-align: center;
  221. margin-bottom: 16rpx;
  222. }
  223. .batch-counter {
  224. display: flex;
  225. align-items: center;
  226. justify-content: center;
  227. gap: 16rpx;
  228. margin-bottom: 32rpx;
  229. .counter-btn {
  230. width: 64rpx;
  231. height: 64rpx;
  232. border-radius: 50%;
  233. background: #f5f5f5;
  234. border: none;
  235. font-size: 32rpx;
  236. display: flex;
  237. align-items: center;
  238. justify-content: center;
  239. color: #333;
  240. &:disabled {
  241. opacity: 0.5;
  242. cursor: not-allowed;
  243. }
  244. }
  245. .counter-input {
  246. width: 120rpx;
  247. height: 64rpx;
  248. text-align: center;
  249. border: 1px solid #ddd;
  250. border-radius: 8rpx;
  251. font-size: 28rpx;
  252. }
  253. }
  254. .batch-btns {
  255. display: flex;
  256. gap: 24rpx;
  257. justify-content: center;
  258. .batch-cancel-btn {
  259. background: #f5f5f5;
  260. color: #666;
  261. border-radius: 32rpx;
  262. font-size: 28rpx;
  263. padding: 0 32rpx;
  264. border: none;
  265. }
  266. .batch-confirm-btn {
  267. background: #ff9800;
  268. color: #fff;
  269. border-radius: 32rpx;
  270. font-size: 28rpx;
  271. padding: 0 32rpx;
  272. border: none;
  273. &:disabled {
  274. background: #ccc;
  275. color: #666;
  276. cursor: not-allowed;
  277. }
  278. }
  279. }
  280. .no-chapters-tip {
  281. font-size: 24rpx;
  282. color: #999;
  283. text-align: center;
  284. }
  285. }
  286. }
  287. &.dark-mode {
  288. .content {
  289. .popup-title {
  290. color: $dark-text-color-primary;
  291. }
  292. .popup-desc {
  293. color: $dark-text-color-tertiary;
  294. }
  295. .popup-btns {
  296. .popup-btn {
  297. background: #ff9800;
  298. color: #fff;
  299. &.popup-btn-video {
  300. background: rgba(255, 152, 0, 0.1);
  301. color: #ff9800;
  302. border: 1px solid #ff9800;
  303. }
  304. &.popup-btn-batch {
  305. background: $dark-bg-color-secondary;
  306. color: #ff9800;
  307. border: 1px solid #ff9800;
  308. }
  309. }
  310. }
  311. .batch-subscribe-content {
  312. .batch-title {
  313. color: $dark-text-color-primary;
  314. }
  315. .batch-info {
  316. color: $dark-text-color-tertiary;
  317. }
  318. .batch-current-info {
  319. color: $dark-text-color-primary;
  320. }
  321. .batch-counter {
  322. .counter-btn {
  323. background: $dark-bg-color-tertiary;
  324. color: $dark-text-color-primary;
  325. }
  326. .counter-input {
  327. background: $dark-bg-color-secondary;
  328. border: 1px solid $dark-border-color;
  329. color: $dark-text-color-primary;
  330. }
  331. }
  332. .batch-btns {
  333. .batch-cancel-btn {
  334. background: $dark-bg-color-tertiary;
  335. color: $dark-text-color-secondary;
  336. }
  337. .batch-confirm-btn {
  338. background: #ff9800;
  339. color: #fff;
  340. &:disabled {
  341. background: $dark-bg-color-tertiary;
  342. color: $dark-text-color-tertiary;
  343. }
  344. }
  345. }
  346. .no-chapters-tip {
  347. color: $dark-text-color-tertiary;
  348. }
  349. }
  350. }
  351. }
  352. }
  353. </style>