294 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <KlNavTab />
 | |
|   <div class="sign-content w-1440px ma-auto">
 | |
|     <!-- 顶部统计 -->
 | |
|     <div class="sign-header">
 | |
|       <div class="sign-icon">
 | |
|         <div class="icon-text">签</div>
 | |
|       </div>
 | |
|       <div class="sign-info">
 | |
|         <div class="search-container">
 | |
|           <div class="search-group">
 | |
|             <span class="search-label">积分标题</span>
 | |
|             <el-input v-model="query.title" placeholder="请输入关键词" class="search-input" clearable>
 | |
|               <template #prefix>
 | |
|                 <el-icon><Search /></el-icon>
 | |
|               </template>
 | |
|             </el-input>
 | |
|             <el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
 | |
|           </div>
 | |
| 
 | |
|           <div class="sign-center ml-[10px]">
 | |
|             <el-button type="success" class="sign-btn" @click="handleClickSign"> 立即签到 </el-button>
 | |
|           </div>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|     <!-- Tab切换 -->
 | |
|     <!-- <div class="sign-tabs">
 | |
|       <div class="tab" @click="handleClickTab('today')" :class="{ active: sign_status_tab === 'today' }">今日签到</div>
 | |
|       <div class="tab" @click="handleClickTab('allRanking')" :class="{ active: sign_status_tab === 'allRanking' }">总排行</div>
 | |
|       <div class="tab" @click="handleClickTab('rewardRanking')" :class="{ active: sign_status_tab === 'rewardRanking' }">奖励排行</div>
 | |
|     </div> -->
 | |
| 
 | |
|     <!-- 签到列表 -->
 | |
|     <div class="sign-table">
 | |
|       <div class="table-header">
 | |
|         <!-- <div>昵称</div> -->
 | |
|         <div>积分标题</div>
 | |
|         <div>积分描述</div>
 | |
|         <div>积分</div>
 | |
|         <div>发生时间</div>
 | |
|       </div>
 | |
|       <div v-for="item in result?.list" :key="item.id" class="table-row">
 | |
|         <!-- <div class="avatar"> -->
 | |
|         <!-- <img :src="item.avatar" alt="avatar" /> -->
 | |
|         <!-- <span>{{ item.nickname }}</span> -->
 | |
|         <!-- </div> -->
 | |
|         <div>{{ item.title }}</div>
 | |
|         <div>{{ item.description }}</div>
 | |
|         <div>{{ item.point }}</div>
 | |
|         <div>{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}</div>
 | |
|       </div>
 | |
|     </div>
 | |
|     <!-- 分页组件 -->
 | |
|     <div class="mt-[10px] flex justify-center">
 | |
|       <el-pagination
 | |
|         v-model:current-page="query.pageNo"
 | |
|         :page-size="query.pageSize"
 | |
|         layout="prev, pager, next"
 | |
|         :total="result?.total"
 | |
|         @current-change="handleCurrentChange"
 | |
|       />
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script setup lang="ts">
 | |
|   import { reactive } from 'vue'
 | |
|   import { Search } from '@element-plus/icons-vue'
 | |
|   import { signIn, getUserPointPage } from '~/api/personal-center/index'
 | |
|   import type { PageResultMemberPointRecordRespVO } from '~/api/personal-center/types'
 | |
|   import useUserStore from '~/stores/user'
 | |
|   import dayjs from 'dayjs'
 | |
|   const user = useUserInfo()
 | |
| 
 | |
|   const query = reactive({
 | |
|     pageNo: 1,
 | |
|     pageSize: 10,
 | |
|     userId: user.value.id,
 | |
|     title: '',
 | |
|   })
 | |
| 
 | |
|   // const result = reactive<PageResultMemberPointRecordRespVO>({
 | |
|   //   total: 0,
 | |
|   //   list: [],
 | |
|   // })
 | |
|   // const signList = ref([
 | |
|   //   {
 | |
|   //     avatar: 'https://dummyimage.com/40x40/ccc/fff.png&text=美',
 | |
|   //     name: '头街',
 | |
|   //     totalDays: 756,
 | |
|   //     continuousDays: 33,
 | |
|   //     lastSignTime: '2025-05-11 09:22:13',
 | |
|   //     reward: '3积分',
 | |
|   //   },
 | |
|   //   {
 | |
|   //     avatar: 'https://dummyimage.com/40x40/ccc/fff.png&text=小',
 | |
|   //     name: 'xiaoy94',
 | |
|   //     totalDays: 648,
 | |
|   //     continuousDays: 21,
 | |
|   //     lastSignTime: '2025-05-11 09:21:15',
 | |
|   //     reward: '3积分',
 | |
|   //   },
 | |
|   //   // ... 其余数据
 | |
|   // ])
 | |
| 
 | |
|   // const sign_status_tab = ref('today') // today allRanking  rewardRanking
 | |
|   // const handleClickTab = (val: string) => {
 | |
|   //   sign_status_tab.value = val
 | |
|   // }
 | |
| 
 | |
|   const handleCurrentChange = (val: number) => {
 | |
|     console.log(1)
 | |
|     query.pageNo = val // 更新当前页
 | |
|     getUserPointPageList()
 | |
|   }
 | |
| 
 | |
|   const { data: result, refresh: getUserPointPageList } = await useAsyncData(
 | |
|     'getUserPointPage',
 | |
|     async () => {
 | |
|       const res = await getUserPointPage(query)
 | |
|       return res.data
 | |
|     },
 | |
|     {
 | |
|       immediate: true, // 立即请求
 | |
|     }
 | |
|   )
 | |
| 
 | |
|   // const getUserPointPageList = async () => {
 | |
|   //   const res = await getUserPointPage(query)
 | |
|   //   if (res.code === 0) {
 | |
|   //     result.list = res.data.list
 | |
|   //     result.total = res.data.total
 | |
|   //   }
 | |
|   // }
 | |
|   // getUserPointPageList()
 | |
| 
 | |
|   const handleClickSign = async () => {
 | |
|     const res = await signIn()
 | |
|     if (res.code === 0) {
 | |
|       ElMessage.success(res.msg)
 | |
|       query.pageNo = 1
 | |
|       getUserPointPageList()
 | |
|     }
 | |
|     console.log(res)
 | |
|   }
 | |
| 
 | |
|   const handleSearch = () => {
 | |
|     query.pageNo = 1
 | |
|     getUserPointPageList()
 | |
|   }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
|   .sign-content {
 | |
|     // background: #f5f5f5;
 | |
|     padding: 24px;
 | |
|     .sign-header {
 | |
|       display: flex;
 | |
|       align-items: center;
 | |
|       background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
 | |
|       border-radius: 12px;
 | |
|       padding: 24px;
 | |
|       margin-bottom: 24px;
 | |
|       box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
 | |
|       border: 1px solid #e9ecef;
 | |
| 
 | |
|       .sign-icon {
 | |
|         .icon-text {
 | |
|           font-size: 32px;
 | |
|           color: #fff;
 | |
|           background: linear-gradient(45deg, #4f46e5, #8b5cf6);
 | |
|           width: 60px;
 | |
|           height: 60px;
 | |
|           display: flex;
 | |
|           align-items: center;
 | |
|           justify-content: center;
 | |
|           border-radius: 8px;
 | |
|           box-shadow: 0 2px 4px rgba(79, 70, 229, 0.2);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .search-container {
 | |
|         flex: 1;
 | |
|         display: flex;
 | |
|         align-items: center;
 | |
|         justify-content: space-between;
 | |
|         margin-left: 32px;
 | |
| 
 | |
|         .search-group {
 | |
|           flex: 1;
 | |
|           display: flex;
 | |
|           align-items: center;
 | |
|           max-width: 600px;
 | |
| 
 | |
|           .search-label {
 | |
|             font-size: 14px;
 | |
|             color: #495057;
 | |
|             margin-right: 12px;
 | |
|             white-space: nowrap;
 | |
|           }
 | |
| 
 | |
|           .search-input {
 | |
|             flex: 1;
 | |
|             margin-right: 12px;
 | |
| 
 | |
|             .el-input__inner {
 | |
|               height: 40px;
 | |
|               border-radius: 8px;
 | |
|               border-color: #dee2e6;
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           .search-btn {
 | |
|             height: 40px;
 | |
|             padding: 0 24px;
 | |
|             border-radius: 8px;
 | |
|             font-weight: 500;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         .sign-btn {
 | |
|           height: 40px;
 | |
|           padding: 0 24px;
 | |
|           border-radius: 8px;
 | |
|           font-weight: 500;
 | |
|           background: linear-gradient(45deg, #10b981, #34d399);
 | |
|           border: none;
 | |
| 
 | |
|           &:hover {
 | |
|             opacity: 0.9;
 | |
|           }
 | |
| 
 | |
|           .el-icon {
 | |
|             margin-right: 8px;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     .sign-tabs {
 | |
|       display: flex;
 | |
|       background: #fff;
 | |
|       border-radius: 8px 8px 0 0;
 | |
|       overflow: hidden;
 | |
|       border: 1px solid #eee;
 | |
|       .tab {
 | |
|         flex: 1;
 | |
|         text-align: center;
 | |
|         padding: 16px 0;
 | |
|         font-size: 16px;
 | |
|         cursor: pointer;
 | |
|         &.active {
 | |
|           background: #f44336;
 | |
|           color: #fff;
 | |
|           font-weight: bold;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     .sign-table {
 | |
|       background: #fff;
 | |
|       border-radius: 0 0 8px 8px;
 | |
|       border: 1px solid #eee;
 | |
|       .table-header,
 | |
|       .table-row {
 | |
|         display: flex;
 | |
|         padding: 12px 0;
 | |
|         border-bottom: 1px solid #eee;
 | |
|         div {
 | |
|           flex: 1;
 | |
|           text-align: center;
 | |
|         }
 | |
|         .avatar {
 | |
|           display: flex;
 | |
|           align-items: center;
 | |
|           justify-content: center;
 | |
|           img {
 | |
|             width: 32px;
 | |
|             height: 32px;
 | |
|             border-radius: 50%;
 | |
|             margin-right: 8px;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       .table-header {
 | |
|         background: #fafafa;
 | |
|         font-weight: bold;
 | |
|       }
 | |
|       .table-row:last-child {
 | |
|         border-bottom: none;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| </style>
 | 
