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

413 lines
8.3 KiB

  1. <template>
  2. <view class="page-container">
  3. <navbar title="任务中心" leftClick @leftClick="$utils.navigateBack" />
  4. <view class="task-center">
  5. <!-- 账户剩余 -->
  6. <view class="account-balance">
  7. <view class="balance-label">账户剩余</view>
  8. <view class="balance-value"><text class="num">{{ maxVote }}</text> <text class="unit"> 推荐票</text></view>
  9. </view>
  10. <!-- 打卡得奖励 -->
  11. <view class="checkin-section">
  12. <view class="section-header">
  13. <text>打卡得奖励</text>
  14. <view class="record-btn">打卡记录</view>
  15. </view>
  16. <view class="checkin-grid">
  17. <view v-for="day in clockList"
  18. :key="day"
  19. class="checkin-day"
  20. :class="{ active: day.commonSignLog }">
  21. <view class="day-label"
  22. :class="{ bold: day.commonSignLog }">
  23. {{ day.title }}
  24. </view>
  25. <image class="ticket-img"
  26. :src="day.image"
  27. mode="aspectFit" />
  28. <view class="ticket-num">+ {{ day.num }}</view>
  29. </view>
  30. </view>
  31. <button class="checkin-btn" :class="{ 'checked-btn': isSign }" :disabled="isSign"
  32. @click="clickSignTask">
  33. {{ isSign ? '已签到' : '签到得奖励' }}
  34. </button>
  35. </view>
  36. <!-- 更多任务 -->
  37. <view class="more-tasks">
  38. <view class="more-header">更多任务</view>
  39. <view class="task-list">
  40. <view class="task-item" v-for="(task, idx) in list" :key="idx"
  41. :class="{ 'no-border': idx === tasks.length - 1 }">
  42. <view class="task-info">
  43. <view class="task-title">{{ task.title }}</view>
  44. <view class="task-desc">推荐票 +{{ task.num }}</view>
  45. </view>
  46. <button class="get-btn" :class="{ 'received-btn': task.commonTaskLog }"
  47. :disabled="task.commonTaskLog"
  48. @click="clickMoreTask(task.id)">
  49. {{ task.commonTaskLog ? '已领取' : '去领取' }}
  50. </button>
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </template>
  57. <script>
  58. import mixinsList from '@/mixins/list.js'
  59. export default {
  60. mixins: [mixinsList],
  61. components: {
  62. },
  63. data() {
  64. return {
  65. checkedDays: 3, // 已签到天数
  66. tasks: [{
  67. title: '观看视频广告',
  68. received: false
  69. },
  70. {
  71. title: '每日首阅三个章节',
  72. received: false
  73. },
  74. {
  75. title: '每日首条评论',
  76. received: false
  77. },
  78. ],
  79. clockList : [],
  80. isChecked: false, // 新增:签到按钮状态
  81. maxVote : 0,
  82. mixinsListApi : '',
  83. }
  84. },
  85. computed : {
  86. isSign(){
  87. let taskId = 0
  88. this.clockList.forEach(n => {
  89. if(!n.commonSignLog){
  90. taskId = n.id
  91. }
  92. })
  93. return !taskId
  94. },
  95. },
  96. onShow() {
  97. this.getMyRecommendTicketNum()
  98. this.getSignTaskList()
  99. this.getMoreTaskList()
  100. },
  101. methods: {
  102. getMyRecommendTicketNum(){
  103. this.$fetch('getMyRecommendTicketNum')
  104. .then(res => {
  105. this.maxVote = res
  106. })
  107. },
  108. getSignTaskList(){
  109. this.$fetch('getSignTaskList', {
  110. token : uni.getStorageSync('token')
  111. })
  112. .then(res => {
  113. this.clockList = res
  114. })
  115. },
  116. getMoreTaskList(){
  117. this.$fetch('getMoreTaskList', {
  118. token : uni.getStorageSync('token')
  119. })
  120. .then(res => {
  121. this.list = res
  122. })
  123. },
  124. async clickSignTask(){
  125. let taskId = 0
  126. for (var index = 0; index < this.clockList.length; index++) {
  127. var element = this.clockList[index];
  128. if(!element.commonSignLog){
  129. taskId = element.id
  130. break
  131. }
  132. }
  133. if(!taskId){
  134. uni.showToast({
  135. title: '已全部签到',
  136. icon: 'none'
  137. })
  138. return
  139. }
  140. await this.$fetch('clickSignTask', {
  141. taskId,
  142. })
  143. uni.showToast({
  144. title: '签到成功',
  145. icon: 'none'
  146. });
  147. this.getSignTaskList()
  148. this.getMyRecommendTicketNum()
  149. },
  150. async clickMoreTask(taskId){
  151. await this.$fetch('clickMoreTask', {
  152. taskId,
  153. })
  154. uni.showToast({
  155. title: '领取成功',
  156. icon: 'none'
  157. });
  158. this.getMoreTaskList()
  159. this.getMyRecommendTicketNum()
  160. },
  161. handleCheckin() {
  162. if (this.checkedDays < 8) {
  163. this.checkedDays++;
  164. this.isChecked = true;
  165. uni.showToast({
  166. title: '签到成功',
  167. icon: 'none'
  168. });
  169. } else {
  170. this.isChecked = true;
  171. uni.showToast({
  172. title: '已全部签到',
  173. icon: 'none'
  174. });
  175. }
  176. },
  177. handleReceive(idx) {
  178. this.tasks[idx].received = true;
  179. uni.showToast({
  180. title: '领取成功',
  181. icon: 'success'
  182. });
  183. },
  184. },
  185. }
  186. </script>
  187. <style scoped lang="scss">
  188. .page-container {
  189. height: 100vh;
  190. overflow: hidden;
  191. }
  192. .task-center {
  193. background: #f8f8f8;
  194. height: 100vh;
  195. padding-bottom: 40rpx;
  196. overflow: hidden;
  197. box-sizing: border-box;
  198. }
  199. .navbar-placeholder {
  200. height: 100rpx;
  201. }
  202. .account-balance {
  203. background: linear-gradient(90deg, #ffe16b, #ffd700);
  204. border-radius: 20rpx;
  205. margin: 24rpx 24rpx 0 24rpx;
  206. padding: 24rpx 32rpx;
  207. display: flex;
  208. align-items: center;
  209. justify-content: space-between;
  210. font-size: 30rpx;
  211. color: #333;
  212. .balance-label {
  213. font-weight: 500;
  214. }
  215. .balance-value {
  216. font-weight: bold;
  217. color: #bfa100;
  218. .num {
  219. font-size: 24rpx;
  220. }
  221. .unit {
  222. font-size: 22rpx;
  223. }
  224. }
  225. }
  226. .checkin-section {
  227. background: #fff;
  228. border-radius: 20rpx;
  229. margin: 24rpx;
  230. padding: 32rpx 24rpx 24rpx 24rpx;
  231. box-shadow: 0 2rpx 8rpx rgba(255, 215, 0, 0.08);
  232. border: 4rpx solid #ffe16b;
  233. .section-header {
  234. display: flex;
  235. justify-content: space-between;
  236. align-items: center;
  237. font-size: 28rpx;
  238. font-weight: 600;
  239. margin-bottom: 24rpx;
  240. .record-btn {
  241. background: #d6ff4b;
  242. color: #383938;
  243. border-radius: 24rpx;
  244. padding: 6rpx 28rpx;
  245. font-size: 24rpx;
  246. }
  247. }
  248. .checkin-grid {
  249. display: flex;
  250. flex-wrap: wrap;
  251. gap: 18rpx;
  252. margin-bottom: 32rpx;
  253. .checkin-day {
  254. width: 22%;
  255. background: #f7f7f7;
  256. border-radius: 12rpx;
  257. display: flex;
  258. flex-direction: column;
  259. align-items: center;
  260. padding: 18rpx 0 10rpx 0;
  261. border: 2rpx solid #f0f0f0;
  262. &.active {
  263. background: #d6ff4b !important;
  264. border-color: #b6e900 !important;
  265. .day-label,
  266. .ticket-num {
  267. color: #222 !important;
  268. font-weight: bold;
  269. }
  270. }
  271. .day-label {
  272. font-size: 24rpx;
  273. font-weight: 600;
  274. height: 90rpx;
  275. margin-bottom: 8rpx;
  276. color: #333;
  277. &.bold {
  278. font-weight: bold;
  279. }
  280. }
  281. .ticket-img {
  282. width: 48rpx;
  283. height: 36rpx;
  284. margin-bottom: 6rpx;
  285. display: flex;
  286. }
  287. .ticket-num {
  288. font-size: 22rpx;
  289. color: #bfa100;
  290. }
  291. }
  292. }
  293. .checkin-btn {
  294. width: 600rpx;
  295. background: linear-gradient(90deg, #ffe16b, #ffd700);
  296. color: #333;
  297. font-size: 30rpx;
  298. border-radius: 46rpx;
  299. padding: 18rpx 0;
  300. font-weight: bold;
  301. margin-top: 8rpx;
  302. transition: background 0.2s;
  303. }
  304. }
  305. .checked-btn {
  306. background: linear-gradient(90deg, #e0e0e0, #bdbdbd) !important;
  307. color: #444 !important;
  308. cursor: not-allowed;
  309. }
  310. .more-tasks {
  311. background: #faffea;
  312. border-radius: 20rpx;
  313. margin: 0 24rpx;
  314. padding: 24rpx 24rpx 8rpx 24rpx;
  315. margin-top: 100rpx;
  316. .more-header {
  317. font-size: 28rpx;
  318. color: #bfa100;
  319. font-weight: 600;
  320. margin-bottom: 18rpx;
  321. }
  322. .task-list {
  323. .task-item {
  324. display: flex;
  325. align-items: center;
  326. justify-content: space-between;
  327. background: #fff;
  328. border-radius: 0;
  329. margin: 0;
  330. padding: 18rpx 20rpx 10rpx 20rpx;
  331. border-bottom: 1rpx solid #f2f2f2;
  332. .task-info {
  333. display: flex;
  334. flex-direction: column;
  335. align-items: flex-start;
  336. flex: 1;
  337. min-width: 0;
  338. margin-top: 30rpx;
  339. .task-title {
  340. font-size: 26rpx;
  341. color: #222;
  342. font-weight: bold;
  343. }
  344. .task-desc {
  345. font-size: 20rpx;
  346. color: #bbb;
  347. margin-top: 4rpx;
  348. }
  349. }
  350. .get-btn {
  351. background: #ffd700;
  352. color: #fff;
  353. font-size: 24rpx;
  354. border-radius: 24rpx;
  355. padding: 0 28rpx;
  356. font-weight: bold;
  357. border: none;
  358. height: 48rpx;
  359. display: flex;
  360. align-items: center;
  361. justify-content: center;
  362. box-shadow: none;
  363. white-space: nowrap;
  364. margin-left: 18rpx;
  365. transition: background 0.2s;
  366. }
  367. .received-btn {
  368. background: linear-gradient(90deg, #e0e0e0, #bdbdbd) !important;
  369. color: #444 !important;
  370. cursor: not-allowed;
  371. }
  372. &.no-border {
  373. border-bottom: none;
  374. }
  375. }
  376. }
  377. }
  378. </style>