3 Commits 
		
	
	
		
			252f9d01a0
			...
			1fd9806f47
		
	
    | Author | SHA1 | Message | Date | 
|---|---|---|---|
|  | 1fd9806f47 | 宋杰4.29页面整合完成 | 6 months ago | 
|  | a55a800e50 | Merge branch 'songjie' into dev | 6 months ago | 
|  | 8c81241998 | gyq_huodong_4.28 | 6 months ago | 
				 9 changed files with 748 additions and 34 deletions
			
			
		- 
					112package-lock.json
- 
					3package.json
- 
					17src/App.vue
- 
					14src/api/axiosConfig.js
- 
					BINsrc/assets/images/日历.png
- 
					32src/main.js
- 
					10src/router/index.js
- 
					12src/views/ActivityManagement.vue
- 
					582src/views/VotingManagement.vue
| @ -1,13 +1,18 @@ | |||
| <template> | |||
|  <RouterView/> | |||
| 
 | |||
|   <!-- <div id="app"> | |||
|     <voting-management></voting-management> | |||
|        | |||
|   </div> --> | |||
|   <router-view></router-view> | |||
| </template> | |||
| 
 | |||
| <script setup> | |||
| import { RouterView } from 'vue-router'; | |||
| 
 | |||
| <script> | |||
| // export default { | |||
| //   name: 'App', | |||
| // }; | |||
| </script> | |||
| 
 | |||
| <style scoped> | |||
| <style> | |||
| /* 添加全局样式 */ | |||
| 
 | |||
| </style> | |||
| @ -0,0 +1,14 @@ | |||
| import axios from 'axios'; | |||
| 
 | |||
| const instance = axios.create({ | |||
|   baseURL: 'http://192.168.8.235:8000/api/vote', // 后端 API 基地址
 | |||
|   timeout: 3000, | |||
| }); | |||
| 
 | |||
| export default instance; | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| After Width: 200 | Height: 200 | Size: 5.0 KiB | 
| @ -1,28 +1,28 @@ | |||
| 
 | |||
| 
 | |||
| import { createApp } from 'vue' | |||
| import { createPinia } from 'pinia' | |||
| 
 | |||
| import App from './App.vue' | |||
| import router from './router' | |||
| 
 | |||
| import { createApp } from 'vue' // 引入vue实例
 | |||
| import App from './App.vue'  // 引入App.vue
 | |||
| import router from './router'  // 引入router
 | |||
| import axios from './api/axiosConfig'; // 引入axiosConfig
 | |||
| import VotingManagement from './views/VotingManagement.vue' // 引入VotingManagement.vue
 | |||
| import ElementPlus from 'element-plus' | |||
| import 'element-plus/dist/index.css' | |||
| 
 | |||
| import * as ElementPlusIconsVue from '@element-plus/icons-vue' | |||
| import zhCn from 'element-plus/es/locale/lang/zh-cn' | |||
| import { createPinia } from 'pinia' | |||
| 
 | |||
| const app = createApp(App) // 创建vue实例
 | |||
| 
 | |||
| 
 | |||
| const app = createApp(App) | |||
| 
 | |||
| for (const [key, component] of Object.entries(ElementPlusIconsVue)) { | |||
|     app.component(key, component) | |||
|   } | |||
|   app.component(key, component) | |||
| } | |||
| 
 | |||
| app.use(ElementPlus, { | |||
|   locale: zhCn, | |||
| }) | |||
| 
 | |||
| app.component('VotingManagement', VotingManagement) // 注册组件
 | |||
| app.config.globalProperties.axios = axios; // 全局挂载axios
 | |||
| 
 | |||
|   app.use(ElementPlus, { | |||
|     locale: zhCn, | |||
|   }) | |||
| app.use(createPinia()) | |||
| app.use(router) | |||
| app.use(ElementPlus) | |||
|  | |||
| @ -0,0 +1,582 @@ | |||
| <template> | |||
|   <div class="container"> | |||
|     <!-- 左侧菜单栏 --> | |||
|     <div class="sidebar"> | |||
|       <ul class="menu"> | |||
|         <li class="menu-item active">投票管理</li> | |||
|         <li class="menu-item">盲盒管理</li> | |||
|         <li class="menu-item">大转盘管理</li> | |||
|       </ul> | |||
|     </div> | |||
| 
 | |||
|     <!-- 主内容区域 --> | |||
|     <div class="main-content"> | |||
|       <!-- 页面头部 --> | |||
|       <header class="header"> | |||
|         <div class="header-title">活动管理后台</div> | |||
|       </header> | |||
| 
 | |||
|       <div class="content-container"> | |||
|         <!-- 卡片容器 --> | |||
|         <div class="card"> | |||
|           <div class="card-header"> | |||
|             <span class="card-title">查看详情</span> | |||
|             <button class="back-btn" @click="goBack">返回上一页</button> | |||
|           </div> | |||
| 
 | |||
|           <!-- 搜索按钮区域 --> | |||
|           <div class="search-bar"> | |||
|             <div class="search-input-area"> | |||
|               <input type="text" class="search-input" placeholder="请输入精网号" v-model="searchId"> | |||
|               <div class="dropdown"> | |||
|                 <select class="region-select" v-model="selectedRegion"> | |||
|                   <option value="">请选择地区</option> | |||
|                   <option value="北京">北京</option> | |||
|                   <option value="上海">上海</option> | |||
|                   <option value="香港">香港</option> | |||
|                 </select> | |||
|               </div> | |||
|               <div class="date-range"> | |||
|                 <div class="date-picker"> | |||
|                   <img src="../assets/images/日历.png" alt="Calendar" | |||
|                     class="calendar-icon"> | |||
|                   <input type="date" class="date-input" placeholder="开始日期" v-model="startDate"> | |||
|                 </div> | |||
|                 <span class="date-separator">至</span> | |||
|                 <div class="date-picker"> | |||
|                   <img src="../assets/images/日历.png" alt="Calendar" | |||
|                     class="calendar-icon"> | |||
|                   <input type="date" class="date-input" placeholder="结束日期" v-model="endDate"> | |||
|                 </div> | |||
|               </div> | |||
|             </div> | |||
|             <div class="search-buttons"> | |||
|               <button class="search-btn" @click="searchVoteRecords">搜索</button> | |||
|               <button class="export-btn" @click="exportExcel">导出Excel</button> | |||
|             </div> | |||
|           </div> | |||
| 
 | |||
| 
 | |||
|           <!-- 表格数据展示 --> | |||
|           <div class="table-container"> | |||
|             <table class="data-table"> | |||
|               <thead> | |||
|                 <tr> | |||
|                   <th>序号</th> | |||
|                   <th>姓名</th> | |||
|                   <th>精网号</th> | |||
|                   <th>地区</th> | |||
|                   <th>投票明细</th> | |||
|                   <th>投票时间</th> | |||
|                 </tr> | |||
|               </thead> | |||
|               <tbody> | |||
|                 <tr v-for="(record, index) in voteRecords" :key="index"> | |||
|                   <td>{{ index + 1 }}</td> | |||
|                   <td>{{ record.nickname }}</td> | |||
|                   <td>{{ record.jwcode }}</td> | |||
|                   <td>{{ record.dept }}</td> | |||
|                   <td>{{ record.options_title }}</td> | |||
|                   <td>{{ record.time }}</td> | |||
|                 </tr> | |||
|               </tbody> | |||
|             </table> | |||
|           </div> | |||
| 
 | |||
|           <!-- 分页 --> | |||
|           <el-pagination class="pagination" v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[5, 10, 20]" | |||
|             :total="totalPages" @size-change="handleSizeChange" @current-change="handlePageChange" | |||
|             layout="total, sizes, prev, pager, next, jumper" /> | |||
| 
 | |||
|           <!-- <div class="pagination"> | |||
|             <div class="pagination-info">第 {{ currentPage }} 页</div> | |||
|             <div class="page-size"> | |||
|               <select class="page-size-select" v-model="pageSize"> | |||
|                 <option value="8">8条/页</option> | |||
|               </select> | |||
|             </div> | |||
|             <div class="page-numbers"> | |||
|               <button class="page-btn" @click="changePage(currentPage - 1)" :disabled="currentPage === 1"><</button> | |||
|               <button class="page-btn" v-for="page in totalPages" :key="page" @click="changePage(page)":class="{ active: page === currentPage }">{{ page }}</button> | |||
|               <button class="page-btn" @click="changePage(currentPage + 1)":disabled="currentPage === totalPages">></button> | |||
|             </div> | |||
|             <div class="go-to-page"> | |||
|               <span>前往第</span> | |||
|               <input type="number" class="page-input" v-model.number="currentPage" @change="changePage(currentPage)" | |||
|                 min="1" :max="totalPages"> | |||
|               <span>页</span> | |||
|             </div> | |||
|           </div> --> | |||
|         </div> | |||
|       </div> | |||
|     </div> | |||
|   </div> | |||
| </template> | |||
| 
 | |||
| <script> | |||
| import { ref } from 'vue'; | |||
| import axiosInstance from '@/api/axiosConfig'; | |||
| import axiosexport from '@/api/axiosConfig'; | |||
| import { ElTable } from 'element-plus'; | |||
| import { useRoute } from 'vue-router'; | |||
| 
 | |||
| export default { | |||
| 
 | |||
|   // 组件数据 | |||
|   data() { | |||
|     return { | |||
|       // detailId: window.location.pathname.split('/').pop() || '24', | |||
|       detailId: ref(0), | |||
|       //detailId: 24, | |||
|       searchId: '', | |||
|       selectedRegion: '', | |||
|       startDate: '', | |||
|       endDate: '', | |||
|       // currentPage: 1, | |||
|       // pageSize: 8, | |||
|       voteRecords: {}, | |||
|       totalPages: ref(0), | |||
|       totalRecords: 0, | |||
|       currentPage: ref(1), | |||
|       pageSize: ref(10), | |||
|       route: useRoute(), | |||
|     }; | |||
|   }, | |||
| 
 | |||
| 
 | |||
|   methods: { | |||
|     // 分页组件的 current-change 事件处理函数 | |||
|     handlePageChange(val) { | |||
|       console.log(`current page: ${val}`); | |||
|       this.fetchVoteRecords(); // 当页码改变时,重新获取数据 | |||
|     }, | |||
|     handleSizeChange(val) { | |||
|       this.fetchVoteRecords(); | |||
|     }, | |||
| 
 | |||
|     // 获取投票记录 | |||
|     async fetchVoteRecords(detailId) { | |||
|       try { | |||
|         const params = { | |||
|           PageNo: this.currentPage, | |||
|           PageSize: this.pageSize, | |||
|           ActivityId: this.detailId, | |||
|         }; | |||
|         const response = await axiosInstance.post('', params); | |||
|         this.voteRecords = response.data.data.list; | |||
|         this.totalPages = response.data.data.total; | |||
|         console.log(response.data.data.list); | |||
|         // this.totalRecords = response.data.data.total; | |||
|       } catch (error) { | |||
|         console.error('获取投票记录失败:', error); | |||
|       } | |||
|     }, | |||
| 
 | |||
|     // 搜索投票记录 | |||
|     async searchVoteRecords() { | |||
|       try { | |||
|         const params = { | |||
|           jwcode: this.searchId, | |||
|           dept: this.selectedRegion, | |||
|           startDate: this.startDate, | |||
|           endDate: this.endDate, | |||
|           PageNo: this.currentPage, | |||
|           PageSize: this.pageSize, | |||
|           ActivityId: this.detailId, | |||
|         }; | |||
|         const response = await axiosInstance.post('', params); | |||
|         this.voteRecords = response.data.data.list; | |||
|         this.totalRecords = response.data.data.total; | |||
|         this.currentPage = 1; | |||
|         this.totalPages = Math.ceil(this.totalRecords / this.pageSize); | |||
|       } catch (error) { | |||
|         console.error('搜索投票记录失败:', error); | |||
|       } | |||
|     }, | |||
| 
 | |||
|     // 导出Excel | |||
|     async exportExcel() { | |||
|       try { | |||
|         // 构建请求参数 | |||
|         const params = { | |||
|           jwcode: this.searchId, | |||
|           dept: this.selectedRegion, | |||
|           startDate: this.startDate, | |||
|           endDate: this.endDate, | |||
|           ActivityId: this.detailId | |||
|         }; | |||
|         // 发起 POST 请求,设置响应类型为 blob | |||
|         const response = await axiosInstance.post('http://192.168.8.235:8000/api/export', params, { | |||
|           responseType: 'blob' | |||
|         }); | |||
| 
 | |||
|         // 创建 Blob 对象并生成临时 URL | |||
|         const url = window.URL.createObjectURL(new Blob([response.data])); | |||
|         // 创建 <a> 标签用于触发下载 | |||
|         const link = document.createElement('a'); | |||
|         link.href = url; | |||
|         // 设置下载文件名 | |||
|         link.setAttribute('download', '投票记录.xlsx'); | |||
|         document.body.appendChild(link); | |||
|         // 模拟点击下载 | |||
|         link.click(); | |||
|         // 释放临时 URL | |||
|         window.URL.revokeObjectURL(url); | |||
|         // 移除 <a> 标签 | |||
|         document.body.removeChild(link); | |||
|       } catch (error) { | |||
|         console.error('导出 Excel 失败:', error); | |||
|         // 可以添加提示用户导出失败的逻辑,如使用 Element Plus 的消息提示 | |||
|         // ElMessage.error('导出 Excel 失败,请稍后重试'); | |||
|       } | |||
|     }, | |||
| 
 | |||
|     // 切换页码 | |||
|     // changePage(page) { | |||
|     //   if (page >= 1 && page <= this.totalPages) { | |||
|     //     this.currentPage = page; | |||
|     //     this.fetchVoteRecords(); | |||
|     //   } | |||
|     // }, | |||
| 
 | |||
|     // 返回上一页 | |||
|     goBack() { | |||
|       window.history.back(); | |||
|     }, | |||
| 
 | |||
|   }, | |||
| 
 | |||
|   //组件挂载后获取投票记录 | |||
|   mounted() { | |||
|     this.detailId = this.route.params.id;  | |||
|     console.log(this.route.params.id); | |||
|     console.log(this.detailId); | |||
|     this.fetchVoteRecords(this.detailId); | |||
|   } | |||
| 
 | |||
| }; | |||
| 
 | |||
| </script> | |||
| 
 | |||
| 
 | |||
| 
 | |||
| <style scoped> | |||
| /* 全局容器样式 */ | |||
| .container { | |||
|   font-family: "PingFang SC", "Microsoft YaHei", sans-serif; | |||
|   width: 100%; | |||
|   height: 100vh; | |||
|   background-color: #f5f5f5; | |||
|   display: flex; | |||
|   flex-direction: row; | |||
| } | |||
| 
 | |||
| /* 左侧菜单栏样式 */ | |||
| .sidebar { | |||
|   width: 9%; | |||
|   height: 85.5%; | |||
|   background-color: #fff; | |||
|   padding: 0.5% 0; | |||
|   box-shadow: 3px 0 4px rgba(0, 0, 0, 0.05); | |||
|   margin-top: 5.6rem; | |||
|   margin-left: 1.6%; | |||
| } | |||
| 
 | |||
| 
 | |||
| .menu { | |||
|   list-style: none; | |||
|   padding: 0; | |||
|   margin: 0; | |||
| } | |||
| 
 | |||
| .menu-item { | |||
|   padding: 1rem 2.4rem; | |||
|   cursor: pointer; | |||
|   color: #666; | |||
|   transition: background-color 0.3s; | |||
| } | |||
| 
 | |||
| .menu-item:hover { | |||
|   background-color: #e6e6e6; | |||
| } | |||
| 
 | |||
| .menu-item.active { | |||
|   background-color: #fff; | |||
|   color: #ff6b6b; | |||
|   font-weight: bold; | |||
|   border-left: 3px solid #ff6b6b; | |||
| } | |||
| 
 | |||
| /* 主内容区域样式 */ | |||
| .main-content { | |||
|   flex: 1; | |||
|   display: flex; | |||
|   flex-direction: column; | |||
| } | |||
| 
 | |||
| /* 页面头部样式 */ | |||
| .header { | |||
|   display: flex; | |||
|   justify-content: space-between; | |||
|   align-items: center; | |||
|   height: 4.7rem; | |||
|   padding: 0 12.5rem; | |||
|   background-color: #fff; | |||
|   box-shadow: 0 5px 4px rgba(0, 0, 0, 0.05); | |||
|   margin-left: -16rem; | |||
| } | |||
| 
 | |||
| .header-title { | |||
|   font-size: 23px; | |||
|   /* font-weight: bold; */ | |||
|   color: #333; | |||
|   margin-top: -0.3rem; | |||
| } | |||
| 
 | |||
| 
 | |||
| /* 内容容器样式 */ | |||
| .content-container { | |||
|   flex: 1; | |||
|   padding: 20px; | |||
| } | |||
| 
 | |||
| /* 卡片样式 */ | |||
| .card { | |||
|   width: 96%; | |||
|   height: 100%; | |||
|   background-color: #fff; | |||
|   /* box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); */ | |||
|   box-shadow: 1px 5px 8px rgba(0, 0, 0, 0.05); | |||
|   overflow: hidden; | |||
|   margin-top: -0.3%; | |||
| } | |||
| 
 | |||
| /* 卡片头部样式 */ | |||
| .card-header { | |||
|   display: flex; | |||
|   justify-content: space-between; | |||
|   align-items: center; | |||
|   padding: 15px 20px; | |||
|   border-bottom: 1px solid #eee; | |||
| } | |||
| 
 | |||
| .card-title { | |||
|   font-size: 16px; | |||
|   font-weight: bold; | |||
|   color: #333; | |||
|   margin-left: 1rem; | |||
| } | |||
| 
 | |||
| .back-btn { | |||
|   padding: 6px 12px; | |||
|   border: 1px solid #e75d5d; | |||
|   border-radius: 4px; | |||
|   background-color: #fff; | |||
|   color: #e75d5d; | |||
|   font-size: 14px; | |||
|   cursor: pointer; | |||
|   margin-right: 2rem; | |||
| } | |||
| 
 | |||
| /* 搜索框区域样式 */ | |||
| .search-bar { | |||
|   padding: 20px; | |||
|   background-color: #fff; | |||
|   display: flex; | |||
|   justify-content: space-between; | |||
|   align-items: center; | |||
| } | |||
| 
 | |||
| .search-input-area { | |||
|   display: flex; | |||
|   align-items: center; | |||
|   gap: 18px; | |||
| } | |||
| 
 | |||
| .search-input { | |||
|   width: 8rem; | |||
|   padding: 8px 12px; | |||
|   border: 2px solid #ddd; | |||
|   border-radius: 7px; | |||
|   font-size: 14px; | |||
| 
 | |||
| 
 | |||
| } | |||
| 
 | |||
| .region-select { | |||
|   width: 9rem; | |||
|   padding: 8px 12px; | |||
|   border: 2px solid #ddd; | |||
|   border-radius: 7px; | |||
|   font-size: 14px; | |||
|   color: #999; | |||
|   /* 设置输入框内文字颜色 */ | |||
| } | |||
| 
 | |||
| .date-range { | |||
|   display: flex; | |||
|   align-items: center; | |||
|   gap: 10px; | |||
| 
 | |||
| } | |||
| 
 | |||
| .date-picker { | |||
|   position: relative; | |||
|   display: flex; | |||
|   align-items: center; | |||
| } | |||
| 
 | |||
| .calendar-icon { | |||
|   width: 14%; | |||
|   position: absolute; | |||
|   left: 8px; | |||
|   top: 49%; | |||
|   transform: translateY(-50%); | |||
|   color: #999; | |||
| } | |||
| 
 | |||
| .date-input { | |||
|   padding: 8px 12px 8px 28px; | |||
|   border: 2px solid #ddd; | |||
|   border-radius: 7px; | |||
|   font-size: 14px; | |||
|   color: #999; | |||
|   /* 设置输入框内文字颜色 */ | |||
| } | |||
| 
 | |||
| .date-separator { | |||
|   margin: 0 10px; | |||
|   color: #666; | |||
| } | |||
| 
 | |||
| .search-buttons { | |||
|   display: flex; | |||
|   gap: 5px; | |||
|   margin-right: 38rem; | |||
| } | |||
| 
 | |||
| .search-btn, | |||
| .export-btn { | |||
|   padding: 9px 20px; | |||
|   border: none; | |||
|   border-radius: 6px; | |||
|   font-size: 14px; | |||
|   cursor: pointer; | |||
|   /* margin-right: 19.3rem; */ | |||
| } | |||
| 
 | |||
| .search-btn { | |||
|   background-color: #e63946; | |||
|   color: #fff; | |||
| 
 | |||
| } | |||
| 
 | |||
| .export-btn { | |||
|   background-color: #e63946; | |||
|   color: #fff; | |||
|   /* margin-right: 20rem; */ | |||
| } | |||
| 
 | |||
| /* 表格区域样式 */ | |||
| .table-container { | |||
|   padding: 3px 13px; | |||
| } | |||
| 
 | |||
| .data-table { | |||
|   width: 100%; | |||
|   border-collapse: collapse; | |||
| } | |||
| 
 | |||
| .data-table th { | |||
|   padding: 15px; | |||
|   text-align: center; | |||
|   background-color: #f5f5f5; | |||
|   font-weight: normal; | |||
|   color: #666; | |||
|   border-bottom: 1px solid #ddd; | |||
| } | |||
| 
 | |||
| .data-table td { | |||
|   padding: 14px 16px; | |||
|   text-align: center; | |||
|   border-bottom: 2px solid #eee; | |||
|   font-size: 15px; | |||
| } | |||
| 
 | |||
| .even-row { | |||
|   background-color: #fff; | |||
| } | |||
| 
 | |||
| .odd-row { | |||
|   background-color: #fff; | |||
| } | |||
| 
 | |||
| /* 分页区域样式 */ | |||
| .pagination { | |||
|   width: 10%; | |||
| 
 | |||
|   display: flex; | |||
|   justify-content: space-between; | |||
|   align-items: center; | |||
|   padding: 20px 20px; | |||
|   border-top: 1px solid #eee; | |||
|   margin-top: 2.2rem; | |||
|   margin-left: 65rem; | |||
| } | |||
| 
 | |||
| .pagination-info { | |||
|   font-size: 14px; | |||
|   color: #666; | |||
|   font-weight: bold; | |||
|   margin-left: 45rem; | |||
| } | |||
| 
 | |||
| .page-size { | |||
|   margin-left: -11rem; | |||
| } | |||
| 
 | |||
| .page-size-select { | |||
|   padding: 5px 12px; | |||
|   border: 2px solid #ddd; | |||
|   font-size: 14px; | |||
| } | |||
| 
 | |||
| .page-numbers { | |||
|   display: flex; | |||
|   align-items: center; | |||
|   gap: 0px; | |||
|   margin-left: -6rem; | |||
| } | |||
| 
 | |||
| .page-btn { | |||
|   width: 1.5rem; | |||
|   display: flex; | |||
|   justify-content: center; | |||
|   align-items: center; | |||
|   border: 0px solid #ddd; | |||
|   background-color: #fff; | |||
|   cursor: pointer; | |||
|   font-size: 15px; | |||
| } | |||
| 
 | |||
| .page-btn.active { | |||
|   background-color: #f0f0f0; | |||
|   font-weight: bold; | |||
| } | |||
| 
 | |||
| .go-to-page { | |||
|   display: flex; | |||
|   align-items: center; | |||
|   gap: 5px; | |||
|   font-size: 14px; | |||
| } | |||
| 
 | |||
| .page-input { | |||
|   width: 40px; | |||
|   padding: 5px 4px; | |||
|   border: 2px solid #ddd; | |||
|   border-radius: 4px; | |||
|   text-align: center; | |||
|   font-size: 14px; | |||
| } | |||
| </style> | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue