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

322 lines
7.8 KiB

  1. <template>
  2. <view class="chapter-container">
  3. <navbar title="章节列表" leftClick @leftClick="$utils.navigateBack"/>
  4. <view class="tabs">
  5. <uv-tabs :list="tabs"
  6. :activeStyle="{color : '#0A2463', fontWeight : 600}"
  7. lineColor="#0A2463"
  8. :inactiveStyle="{color: '#0A2463'}"
  9. lineHeight="8rpx"
  10. lineWidth="50rpx"
  11. :scrollable="false"
  12. :current="activeTab"
  13. @click="clickTabs"></uv-tabs>
  14. </view>
  15. <view class="box">
  16. <view class="draft-header">
  17. <text class="draft-title">{{ activeTab === 0 ? '草稿箱章节' : '已发布章节' }}</text>
  18. <text class="delete-btn" @click="reverseList">{{ queryParams.reverse ? '正序' : '倒序' }}</text>
  19. </view>
  20. <view class="chapter-list">
  21. <!-- 章节列表 -->
  22. <uv-swipe-action>
  23. <uv-swipe-action-item
  24. v-for="(chapter, index) in list"
  25. :key="chapter.id"
  26. :options="swipeOptions"
  27. @click="deleteChapter(chapter, index)"
  28. >
  29. <view
  30. class="chapter-item"
  31. @click="editChapter(chapter)"
  32. >
  33. <view class="chapter-info">
  34. <text class="chapter-title">章节名</text>
  35. <text class="chapter-number">
  36. {{ chapter.title }}
  37. <text v-if="chapter.isPay == 'Y'" class="vip-tag theme-transition">付费</text>
  38. <text v-if="activeTab == 1 && chapter.state != null"
  39. class="status-tag"
  40. :class="'status-' + (chapter.state == 0 ? 'pending' : chapter.state == 1 ? 'approved' : chapter.state == 2 ? 'rejected' : '')">
  41. {{ chapter.state == 0 ? '审核中' : chapter.state == 1 ? '已发布' : chapter.state == 2 ? '已驳回' : '' }}</text>
  42. </text>
  43. </view>
  44. <uv-icon name="arrow-right" color="#999" size="28"></uv-icon>
  45. </view>
  46. </uv-swipe-action-item>
  47. </uv-swipe-action>
  48. <!-- 空状态 -->
  49. <view style="padding-bottom: 60rpx;"
  50. v-if="list.length == 0" >
  51. <uv-empty
  52. :text="activeTab == 0 ? '还没有发布章节' : '还没有草稿章节'"
  53. :icon="activeTab == 0 ? 'list' : 'edit-pen'"
  54. iconSize="60"
  55. iconColor="#ccc"
  56. textColor="#999"
  57. textSize="28"
  58. mode="data"
  59. />
  60. </view>
  61. </view>
  62. </view>
  63. <view class="bottom-actions">
  64. <button class="btn-settings" @click="handleSettings">设置作品</button>
  65. <button class="btn-new" @click="addNewChapter">新建章节</button>
  66. </view>
  67. </view>
  68. </template>
  69. <script>
  70. import mixinsList from '@/mixins/list.js'
  71. export default {
  72. mixins: [mixinsList],
  73. components: {
  74. },
  75. data() {
  76. return {
  77. tabs : [
  78. {
  79. name : '草稿箱',
  80. index : 1
  81. },
  82. {
  83. name : '已发布',
  84. index : 0
  85. }
  86. ],
  87. activeTab: 0,
  88. mixinsListApi : 'getMyShopNovelPage',
  89. id : 0,
  90. swipeOptions: [{
  91. text: '删除',
  92. style: {
  93. backgroundColor: '#f56c6c'
  94. }
  95. }]
  96. }
  97. },
  98. onLoad(options) {
  99. this.queryParams.reverse = 0
  100. // 根据tab参数决定初始tab
  101. if (options.activeTab) {
  102. this.activeTab = options.activeTab;
  103. }
  104. if(options.id){
  105. this.queryParams.bookId = options.id
  106. this.id = options.id
  107. this.queryParams.status = this.activeTab
  108. }
  109. },
  110. methods: {
  111. clickTabs(tab) {
  112. this.activeTab = tab.index;
  113. this.queryParams.status = this.activeTab
  114. this.list = []
  115. this.getData()
  116. },
  117. reverseList() {
  118. this.queryParams.reverse = [1, 0][this.queryParams.reverse]
  119. this.getData()
  120. },
  121. addNewChapter() {
  122. uni.navigateTo({
  123. url: '/pages_order/author/editor?id=' + this.id
  124. })
  125. },
  126. editChapter(chapter) {
  127. uni.navigateTo({
  128. url: '/pages_order/author/editor?cid=' + chapter.id + '&id=' + this.id
  129. })
  130. },
  131. handleSettings() {
  132. uni.navigateTo({
  133. url: '/pages_order/author/createNovel?id=' + this.id
  134. })
  135. },
  136. // 删除章节
  137. deleteChapter(chapter, index) {
  138. uni.showModal({
  139. title: '提示',
  140. content: `确定要删除章节"${chapter.title}"吗?`,
  141. success: async (res) => {
  142. if (res.confirm) {
  143. try {
  144. await this.$fetch('deleteMyNovel', {
  145. id: chapter.id
  146. })
  147. uni.showToast({
  148. title: '删除成功',
  149. icon: 'success'
  150. })
  151. // 重新获取列表数据
  152. this.getData()
  153. } catch (error) {
  154. uni.showToast({
  155. title: '删除失败',
  156. icon: 'none'
  157. })
  158. }
  159. }
  160. }
  161. })
  162. },
  163. deleteAll() {
  164. uni.showModal({
  165. title: '提示',
  166. content: '确定要删除所有草稿章节吗?',
  167. success: (res) => {
  168. if (res.confirm) {
  169. // 调用删除草稿API
  170. this.$api.deleteAllDrafts({bookId: this.id}).then(res => {
  171. if (res.code === 200) {
  172. this.$utils.showToast('删除成功')
  173. this.getData()
  174. }
  175. })
  176. }
  177. }
  178. })
  179. }
  180. }
  181. }
  182. </script>
  183. <style lang="scss" scoped>
  184. .chapter-container {
  185. min-height: 100vh;
  186. background-color: #f7f7f7;
  187. padding-bottom: 70px;
  188. .tabs{
  189. background-color: #fff;
  190. }
  191. .box{
  192. background-color: #fff;
  193. margin: 50rpx 40rpx;
  194. border-radius: 20rpx;
  195. .draft-header {
  196. padding: 20rpx 40rpx;
  197. display: flex;
  198. justify-content: space-between;
  199. align-items: center;
  200. padding-bottom: 20rpx;
  201. border-bottom: 1px dashed #eee;
  202. margin-bottom: 10rpx;
  203. .draft-title {
  204. font-size: 30rpx;
  205. color: #000;
  206. font-weight: 900;
  207. }
  208. .delete-btn {
  209. font-size: 28rpx;
  210. color: #999;
  211. }
  212. }
  213. .chapter-list {
  214. .chapter-item {
  215. padding: 20rpx 40rpx;
  216. display: flex;
  217. justify-content: space-between;
  218. align-items: center;
  219. border-bottom: 1px solid #eee;
  220. .chapter-info {
  221. .chapter-title {
  222. font-size: 14px;
  223. color: #999;
  224. margin-bottom: 5px;
  225. display: block;
  226. }
  227. .chapter-number {
  228. font-size: 16px;
  229. color: #333;
  230. display: block;
  231. }
  232. .vip-tag {
  233. background: #ffe1b2;
  234. color: #ff9900;
  235. border-radius: 20rpx;
  236. font-size: 24rpx;
  237. padding: 2rpx 18rpx;
  238. margin-left: 16rpx;
  239. }
  240. .status-tag {
  241. border-radius: 20rpx;
  242. font-size: 24rpx;
  243. padding: 2rpx 18rpx;
  244. margin-left: 16rpx;
  245. }
  246. .status-pending {
  247. background: #ff9500;
  248. color: #fff;
  249. }
  250. .status-approved {
  251. background: #07c160;
  252. color: #fff;
  253. }
  254. .status-rejected {
  255. background: #e23d3d;
  256. color: #fff;
  257. }
  258. }
  259. .icon-arrow {
  260. color: #999;
  261. font-size: 16px;
  262. }
  263. }
  264. }
  265. }
  266. .bottom-actions {
  267. padding-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
  268. position: fixed;
  269. bottom: 0;
  270. left: 0;
  271. right: 0;
  272. display: flex;
  273. padding: 10px 15px;
  274. background: #fff;
  275. box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
  276. button {
  277. flex: 1;
  278. height: 40px;
  279. border-radius: 20px;
  280. font-size: 16px;
  281. margin: 0 5px;
  282. &.btn-settings {
  283. background: #fff;
  284. border: 1px solid #ddd;
  285. color: #333;
  286. }
  287. &.btn-new {
  288. background: #2b4acb;
  289. color: #fff;
  290. border: none;
  291. }
  292. }
  293. }
  294. }
  295. </style>