小说小程序前端代码仓库(小程序)
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.

287 lines
5.7 KiB

  1. <template>
  2. <view class="chapter-popup-container" :class="{'dark-mode': isDarkMode}">
  3. <uv-popup ref="popup" :round="30" :customStyle="popupStyle">
  4. <view class="catalog-popup-fullscreen theme-transition">
  5. <view class="catalog-header theme-transition">
  6. <view class="header-left" @click.stop="close">
  7. <uv-icon name="arrow-down" size="46" :color="isDarkMode ? '#ccc' : '#333'"/>
  8. </view>
  9. <view class="header-title theme-transition">目录</view>
  10. <view class="header-right theme-transition" @click.stop="orderAsc = !orderAsc">倒序</view>
  11. </view>
  12. <scroll-view scroll-y class="catalog-list">
  13. <view v-for="(item, idx) in (orderAsc ? chapterList : [...chapterList].reverse())" :key="item.id"
  14. @click="selectChapter(orderAsc ? idx : chapterList.length - 1 - idx)"
  15. :class="['catalog-item theme-transition', {active: (orderAsc ? idx : chapterList.length - 1 - idx) === currentIndex}]">
  16. <view class="item-main">
  17. <text class="item-title theme-transition">{{ item.title }}</text>
  18. <text v-if="item.vip" class="vip-tag theme-transition">付费</text>
  19. </view>
  20. </view>
  21. </scroll-view>
  22. </view>
  23. </uv-popup>
  24. </view>
  25. </template>
  26. <script>
  27. import themeMixin from '@/mixins/themeMode.js'
  28. export default {
  29. mixins: [themeMixin],
  30. data() {
  31. return {
  32. chapterCount: 2814,
  33. orderAsc : true,
  34. currentIndex : 0,
  35. chapterList: [{
  36. id: 1,
  37. title: '第一章 重回2004',
  38. vip: false
  39. },
  40. {
  41. id: 2,
  42. title: '第二章 陈年旧恨',
  43. vip: false
  44. },
  45. {
  46. id: 3,
  47. title: '第三章 再相见',
  48. vip: false
  49. },
  50. {
  51. id: 4,
  52. title: '第四章 李东的邀请',
  53. vip: false
  54. },
  55. {
  56. id: 5,
  57. title: '第五章 小气的男',
  58. vip: false
  59. },
  60. {
  61. id: 6,
  62. title: '第六章 先送谁?',
  63. vip: false
  64. },
  65. {
  66. id: 7,
  67. title: '第七章 打听行情',
  68. vip: false
  69. },
  70. {
  71. id: 8,
  72. title: '第八章 省城探路',
  73. vip: false
  74. },
  75. {
  76. id: 9,
  77. title: '第九章 订货',
  78. vip: false
  79. },
  80. {
  81. id: 10,
  82. title: '第十章 第一桶金',
  83. vip: true
  84. },
  85. {
  86. id: 11,
  87. title: '第十一章 高富帅来袭',
  88. vip: true
  89. },
  90. {
  91. id: 12,
  92. title: '第十二章 故学后,挥场见!',
  93. vip: true
  94. },
  95. {
  96. id: 13,
  97. title: '第十三章 你来我往',
  98. vip: true
  99. },
  100. {
  101. id: 14,
  102. title: '第十四章 你来我往',
  103. vip: true
  104. },
  105. {
  106. id: 15,
  107. title: '第十五章 你来我往',
  108. vip: true
  109. },
  110. {
  111. id: 16,
  112. title: '第十六章 你来我往',
  113. vip: true
  114. },
  115. {
  116. id: 17,
  117. title: '第十七章 你来我往',
  118. vip: true
  119. },
  120. {
  121. id: 18,
  122. title: '第十八章 你来我往',
  123. vip: true
  124. }
  125. ]
  126. }
  127. },
  128. computed: {
  129. popupStyle() {
  130. return {
  131. height: '70vh',
  132. background: this.isDarkMode ? '#222' : '#fff'
  133. }
  134. }
  135. },
  136. methods: {
  137. open() {
  138. this.$refs.popup.open('bottom')
  139. },
  140. close() {
  141. this.$refs.popup.close()
  142. },
  143. selectChapter(idx) {
  144. this.currentIndex = idx
  145. this.showCatalog = false
  146. // TODO: 跳转到对应章节内容
  147. },
  148. }
  149. }
  150. </script>
  151. <style scoped lang="scss">
  152. .chapter-popup-container {
  153. .catalog-popup-fullscreen {
  154. position: relative;
  155. height: 100%;
  156. width: 100vw;
  157. background: #fff;
  158. display: flex;
  159. flex-direction: column;
  160. overflow: hidden;
  161. .catalog-header {
  162. display: flex;
  163. align-items: center;
  164. justify-content: space-between;
  165. padding: 0 24rpx;
  166. height: 96rpx;
  167. border-bottom: 1px solid #eee;
  168. position: sticky;
  169. top: 0;
  170. background: #fff;
  171. z-index: 2;
  172. }
  173. .header-left {
  174. width: 60rpx;
  175. display: flex;
  176. align-items: center;
  177. justify-content: flex-start;
  178. }
  179. .header-title {
  180. flex: 1;
  181. text-align: center;
  182. font-size: 32rpx;
  183. font-weight: bold;
  184. color: #222;
  185. }
  186. .header-right {
  187. color: #223a7a;
  188. font-size: 28rpx;
  189. font-weight: 500;
  190. min-width: 80rpx;
  191. text-align: right;
  192. }
  193. .catalog-list {
  194. height: calc(100% - 180rpx);
  195. overflow: auto;
  196. padding-bottom: 40rpx;
  197. }
  198. .catalog-item {
  199. padding: 0 32rpx;
  200. min-height: 80rpx;
  201. display: flex;
  202. flex-direction: column;
  203. justify-content: center;
  204. border-bottom: 1px solid #f5f5f5;
  205. background: #fff;
  206. color: #222;
  207. font-size: 30rpx;
  208. position: relative;
  209. }
  210. .catalog-item.active {
  211. color: #ff5a5f;
  212. background: #fff7f7;
  213. }
  214. .item-main {
  215. display: flex;
  216. align-items: center;
  217. gap: 16rpx;
  218. }
  219. .item-title {
  220. font-size: 30rpx;
  221. }
  222. .vip-tag {
  223. background: #ffe1b2;
  224. color: #ff9900;
  225. border-radius: 20rpx;
  226. font-size: 24rpx;
  227. padding: 2rpx 18rpx;
  228. margin-left: 16rpx;
  229. }
  230. }
  231. }
  232. /* 暗色主题样式 */
  233. .chapter-popup-container.dark-mode {
  234. .catalog-popup-fullscreen {
  235. background: $dark-bg-color-secondary;
  236. .catalog-header {
  237. background: $dark-bg-color-secondary;
  238. border-bottom: 1px solid $dark-border-color;
  239. .header-title {
  240. color: $dark-text-color-primary;
  241. }
  242. .header-right {
  243. color: $dark-accent-color;
  244. }
  245. }
  246. .catalog-list {
  247. .catalog-item {
  248. background: $dark-bg-color-secondary;
  249. color: $dark-text-color-secondary;
  250. border-bottom: 1px solid $dark-border-color;
  251. &.active {
  252. color: #ff5a5f;
  253. background: rgba(255, 90, 95, 0.1);
  254. }
  255. .item-title {
  256. color: $dark-text-color-secondary;
  257. }
  258. .vip-tag {
  259. background: rgba(255, 153, 0, 0.2);
  260. color: #ff9900;
  261. }
  262. }
  263. }
  264. }
  265. }
  266. </style>