10 changed files with 345 additions and 94 deletions
-
13package-lock.json
-
4package.json
-
2src/App.vue
-
13src/api/homeApi.js
-
5src/api/index.js
-
86src/assets/base.css
-
6src/assets/main.css
-
27src/main.js
-
7src/router/index.js
-
276src/views/ActivityManagement.vue
@ -0,0 +1,13 @@ |
|||||
|
import service from "."; |
||||
|
const homeApi = { |
||||
|
//分页查询
|
||||
|
getHomeData(PageNo,PageSize) { |
||||
|
return service.post("/api/activity",{ |
||||
|
params:{ |
||||
|
PageNo, |
||||
|
PageSize |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
export default homeApi; |
@ -0,0 +1,5 @@ |
|||||
|
import axios from "axios"; |
||||
|
const service = axios.create({ |
||||
|
baseURL:"http://192.168.8.235:8000" |
||||
|
}); |
||||
|
export default service; |
@ -1,86 +0,0 @@ |
|||||
/* color palette from <https://github.com/vuejs/theme> */ |
|
||||
:root { |
|
||||
--vt-c-white: #ffffff; |
|
||||
--vt-c-white-soft: #f8f8f8; |
|
||||
--vt-c-white-mute: #f2f2f2; |
|
||||
|
|
||||
--vt-c-black: #181818; |
|
||||
--vt-c-black-soft: #222222; |
|
||||
--vt-c-black-mute: #282828; |
|
||||
|
|
||||
--vt-c-indigo: #2c3e50; |
|
||||
|
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29); |
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12); |
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); |
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); |
|
||||
|
|
||||
--vt-c-text-light-1: var(--vt-c-indigo); |
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66); |
|
||||
--vt-c-text-dark-1: var(--vt-c-white); |
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64); |
|
||||
} |
|
||||
|
|
||||
/* semantic color variables for this project */ |
|
||||
:root { |
|
||||
--color-background: var(--vt-c-white); |
|
||||
--color-background-soft: var(--vt-c-white-soft); |
|
||||
--color-background-mute: var(--vt-c-white-mute); |
|
||||
|
|
||||
--color-border: var(--vt-c-divider-light-2); |
|
||||
--color-border-hover: var(--vt-c-divider-light-1); |
|
||||
|
|
||||
--color-heading: var(--vt-c-text-light-1); |
|
||||
--color-text: var(--vt-c-text-light-1); |
|
||||
|
|
||||
--section-gap: 160px; |
|
||||
} |
|
||||
|
|
||||
@media (prefers-color-scheme: dark) { |
|
||||
:root { |
|
||||
--color-background: var(--vt-c-black); |
|
||||
--color-background-soft: var(--vt-c-black-soft); |
|
||||
--color-background-mute: var(--vt-c-black-mute); |
|
||||
|
|
||||
--color-border: var(--vt-c-divider-dark-2); |
|
||||
--color-border-hover: var(--vt-c-divider-dark-1); |
|
||||
|
|
||||
--color-heading: var(--vt-c-text-dark-1); |
|
||||
--color-text: var(--vt-c-text-dark-2); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
*, |
|
||||
*::before, |
|
||||
*::after { |
|
||||
box-sizing: border-box; |
|
||||
margin: 0; |
|
||||
font-weight: normal; |
|
||||
} |
|
||||
|
|
||||
body { |
|
||||
min-height: 100vh; |
|
||||
color: var(--color-text); |
|
||||
background: var(--color-background); |
|
||||
transition: |
|
||||
color 0.5s, |
|
||||
background-color 0.5s; |
|
||||
line-height: 1.6; |
|
||||
font-family: |
|
||||
Inter, |
|
||||
-apple-system, |
|
||||
BlinkMacSystemFont, |
|
||||
'Segoe UI', |
|
||||
Roboto, |
|
||||
Oxygen, |
|
||||
Ubuntu, |
|
||||
Cantarell, |
|
||||
'Fira Sans', |
|
||||
'Droid Sans', |
|
||||
'Helvetica Neue', |
|
||||
sans-serif; |
|
||||
font-size: 15px; |
|
||||
text-rendering: optimizeLegibility; |
|
||||
-webkit-font-smoothing: antialiased; |
|
||||
-moz-osx-font-smoothing: grayscale; |
|
||||
} |
|
@ -1,9 +1,14 @@ |
|||||
import { createRouter, createWebHistory } from 'vue-router' |
import { createRouter, createWebHistory } from 'vue-router' |
||||
|
import ActivityManagement from '@/views/ActivityManagement.vue' |
||||
|
|
||||
const router = createRouter({ |
const router = createRouter({ |
||||
history: createWebHistory(import.meta.env.BASE_URL), |
history: createWebHistory(import.meta.env.BASE_URL), |
||||
routes: [ |
routes: [ |
||||
|
|
||||
|
{ |
||||
|
path: '/', |
||||
|
name: 'activityManagement', |
||||
|
component: ActivityManagement, |
||||
|
}, |
||||
], |
], |
||||
}) |
}) |
||||
|
|
||||
|
@ -0,0 +1,276 @@ |
|||||
|
<template> |
||||
|
<el-container> |
||||
|
<el-header> |
||||
|
<h1>活动管理后台</h1> |
||||
|
</el-header> |
||||
|
|
||||
|
<el-main> |
||||
|
<el-row justify="start" align="middle"> |
||||
|
<el-col :span="24" class="header-actions"> |
||||
|
<el-button type="danger" @click="openAddActivityDialog">添加活动</el-button> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<el-table :data="paginatedActivities" style="width: 100%"> |
||||
|
<!-- <el-table-column label="序号" type="index" width="80" align="center" header-align="center"> |
||||
|
<template #default="{ $index }"> |
||||
|
{{ $index + 1 }} |
||||
|
</template> |
||||
|
</el-table-column> --> |
||||
|
<el-table-column type="index" :index="indexMethod" width="80" label="活动标题" /> |
||||
|
<el-table-column prop="title" label="活动标题" /> |
||||
|
<el-table-column prop="detail" label="活动详情" /> |
||||
|
<el-table-column prop="visit_count" label="访问人数" width="120" /> |
||||
|
<el-table-column prop="vote_count" label="投票人数" width="120" /> |
||||
|
<el-table-column prop="start" label="活动开始时间" /> |
||||
|
<el-table-column prop="end" label="活动结束时间" /> |
||||
|
<el-table-column prop="created_at" label="活动创建时间" /> |
||||
|
<el-table-column prop="status" label="活动状态"> |
||||
|
<template #default="scope"> |
||||
|
<span v-if="scope.row.status === 1">未开始</span> |
||||
|
<span v-if="scope.row.status === 2">进行中</span> |
||||
|
<span v-if="scope.row.status === 3">已结束</span> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
<el-table-column label="操作" width="180"> |
||||
|
<template #default="scope"> |
||||
|
<div class="operation-buttons"> |
||||
|
<el-button size="mini" type="default" @click="editActivity(scope.row)">修改</el-button> |
||||
|
<el-button size="mini" type="primary" @click="viewDetails(scope.row)">查看详情</el-button> |
||||
|
</div> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
</el-table> |
||||
|
|
||||
|
<div class="pagination-container"> |
||||
|
<el-pagination background layout="prev, pager, next" :total="total" :page-size="itemsPerPage" |
||||
|
v-model:current-page="currentPage" @current-change="handlePageChange"> |
||||
|
</el-pagination> |
||||
|
</div> |
||||
|
</el-main> |
||||
|
|
||||
|
<!-- 添加活动对话框开始 --> |
||||
|
<el-dialog v-model="showAddActivityDialog" title="添加活动"> |
||||
|
<el-form :model="newActivity" ref="activityForm" label-width="120px"> |
||||
|
<el-form-item label="活动标题" :rules="[{ required: true, message: '请输入活动标题' }]"> |
||||
|
<el-input v-model="newActivity.title"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="活动详情" :rules="[{ required: true, message: '请输入活动详情' }]"> |
||||
|
<el-input type="textarea" v-model="newActivity.details"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="活动图标"> |
||||
|
<el-upload action="#" list-type="picture-card" :on-preview="handlePictureCardPreview" |
||||
|
:on-remove="handleRemove" :on-success="handleSuccess" :before-upload="beforeUpload"> |
||||
|
<el-icon class="avatar-uploader-icon"> |
||||
|
<Plus /> |
||||
|
</el-icon> |
||||
|
</el-upload> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="活动时间" :locale="zhCn" :rules="[{ required: true, message: '请选择活动时间' }]"> |
||||
|
<el-date-picker v-model="newActivity.date" type="datetimerange" start-placeholder="开始日期" |
||||
|
end-placeholder="结束日期"></el-date-picker> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="活动网址" :rules="[{ required: true, message: '请输入活动网址' }]"> |
||||
|
<el-input v-model="newActivity.url"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="选择市场" :rules="[{ required: true, message: '请选择活动面向的市场' }]"> |
||||
|
<el-select v-model="newActivity.market" placeholder="请选择市场"> |
||||
|
<el-option label="市场1" value="market1"></el-option> |
||||
|
<el-option label="市场2" value="market2"></el-option> |
||||
|
</el-select> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="客户权限" :rules="[{ required: true, message: '请选择面向客户的级别' }]"> |
||||
|
<el-radio-group v-model="newActivity.clientLevel"> |
||||
|
<el-radio label="非网">非网</el-radio> |
||||
|
<el-radio label="半年版">半年版</el-radio> |
||||
|
<el-radio label="终免">终免</el-radio> |
||||
|
</el-radio-group> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
<span slot="footer" class="dialog-footer"> |
||||
|
<el-button @click="showAddActivityDialog = false">取 消</el-button> |
||||
|
<el-button type="primary" @click="addActivity">确 定</el-button> |
||||
|
</span> |
||||
|
</el-dialog> |
||||
|
<!-- 添加活动对话框结束 --> |
||||
|
</el-container> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, computed } from 'vue'; |
||||
|
import { ElMessage } from 'element-plus'; |
||||
|
import zhCn from 'element-plus/es/locale/lang/zh-cn' |
||||
|
import homeApi from '@/api/homeApi'; |
||||
|
|
||||
|
|
||||
|
function indexMethod(index){ |
||||
|
return itemsPerPage*(currentPage.value-1)+index+1; |
||||
|
} |
||||
|
//定义假id |
||||
|
const fakeId = ref(1); |
||||
|
|
||||
|
// 活动列表数据 |
||||
|
const activities = ref([]); |
||||
|
|
||||
|
// 分页获取所有活动 |
||||
|
function getAllActivities(currentPage, itemsPerPage) { |
||||
|
homeApi.getHomeData(currentPage, itemsPerPage) |
||||
|
.then(response => { |
||||
|
activities.value = response.data.data.list; |
||||
|
total.value = response.data.data.total; |
||||
|
console.log(activities.value); |
||||
|
console.log(total.value); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 默认第1页 |
||||
|
const currentPage = ref(1); |
||||
|
// 每页10条数据 |
||||
|
const itemsPerPage = 10; |
||||
|
//总条目数 |
||||
|
const total = ref(0); |
||||
|
getAllActivities(currentPage.value, itemsPerPage); |
||||
|
|
||||
|
|
||||
|
// 分页处理活动数据 |
||||
|
const paginatedActivities = computed(() => { |
||||
|
const start = (currentPage.value - 1) * itemsPerPage; |
||||
|
const end = start + itemsPerPage; |
||||
|
return activities.value.slice(start, end); |
||||
|
}); |
||||
|
|
||||
|
// 当前页改变时触发的事件 |
||||
|
const handlePageChange = (newPage) => { |
||||
|
getAllActivities(newPage, itemsPerPage); |
||||
|
}; |
||||
|
|
||||
|
// 添加的活动 |
||||
|
const newActivity = ref({ |
||||
|
id: null, |
||||
|
title: '', |
||||
|
details: '', |
||||
|
date: '', |
||||
|
url: '', |
||||
|
market: '', |
||||
|
clientLevel: '' |
||||
|
}); |
||||
|
|
||||
|
// 展示添加活动对话框 |
||||
|
const showAddActivityDialog = ref(false); |
||||
|
|
||||
|
// 添加新活动的方法 |
||||
|
const addActivity = () => { |
||||
|
newActivity.value.id = activities.value.length + 1; |
||||
|
newActivity.value.create_at = new Date().toISOString().split('T')[0]; // 设置当前时间为创建时间 |
||||
|
activities.value.push({ ...newActivity.value }); |
||||
|
newActivity.value = { |
||||
|
id: null, |
||||
|
title: '', |
||||
|
details: '', |
||||
|
date: '', |
||||
|
url: '', |
||||
|
market: '', |
||||
|
clientLevel: '' |
||||
|
}; |
||||
|
showAddActivityDialog.value = true; |
||||
|
ElMessage.success('活动添加成功'); |
||||
|
}; |
||||
|
|
||||
|
// 修改活动的方法 |
||||
|
const editActivity = (activity) => { |
||||
|
newActivity.value = { ...activity }; |
||||
|
showAddActivityDialog.value = true; |
||||
|
}; |
||||
|
|
||||
|
// 查看详情 |
||||
|
const viewDetails = (activity) => { |
||||
|
ElMessage.info(`活动ID: ${activity.id}, 活动标题: ${activity.title}, 日期: ${activity.start} - ${activity.end}, 访问人数: ${activity.visit_count}`); |
||||
|
}; |
||||
|
|
||||
|
const handlePictureCardPreview = (file) => { |
||||
|
console.log('Preview:', file); |
||||
|
}; |
||||
|
|
||||
|
const handleRemove = (file, fileList) => { |
||||
|
console.log('Remove:', file, fileList); |
||||
|
}; |
||||
|
|
||||
|
const handleSuccess = (response, file, fileList) => { |
||||
|
console.log('Success:', response, file, fileList); |
||||
|
}; |
||||
|
|
||||
|
const beforeUpload = (file) => { |
||||
|
const isJPG = file.type === 'image/jpeg'; |
||||
|
const isPNG = file.type === 'image/png'; |
||||
|
const isLt2M = file.size / 1024 / 1024 < 2; |
||||
|
|
||||
|
if (!isJPG && !isPNG) { |
||||
|
ElMessage.error('上传头像图片只能是 JPG 或 PNG 格式!'); |
||||
|
} |
||||
|
if (!isLt2M) { |
||||
|
ElMessage.error('上传头像图片大小不能超过 2MB!'); |
||||
|
} |
||||
|
return isJPG || isPNG && isLt2M; |
||||
|
}; |
||||
|
|
||||
|
// 状态对应的样式类 |
||||
|
const statusClassMap = { |
||||
|
'进行中': 'status-active', |
||||
|
'已完成': 'status-finished', |
||||
|
}; |
||||
|
|
||||
|
// 根据活动状态获取对应的样式类 |
||||
|
const getStatusClass = (status) => { |
||||
|
return statusClassMap[status] || 'status-default'; |
||||
|
}; |
||||
|
|
||||
|
// 打开添加活动对话框 |
||||
|
const openAddActivityDialog = () => { |
||||
|
newActivity.value = { |
||||
|
id: null, |
||||
|
title: '', |
||||
|
details: '', |
||||
|
date: '', |
||||
|
url: '', |
||||
|
market: '', |
||||
|
clientLevel: '' |
||||
|
}; |
||||
|
showAddActivityDialog.value = true; |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.header-actions { |
||||
|
margin-left: 20px; |
||||
|
/* 调整按钮与标题之间的距离 */ |
||||
|
} |
||||
|
|
||||
|
.pagination-container { |
||||
|
position: absolute; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
margin-top: 10rem; |
||||
|
left: 45%; |
||||
|
} |
||||
|
|
||||
|
.dialog-footer { |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.operation-buttons { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.status-active { |
||||
|
color: #409eff; |
||||
|
} |
||||
|
|
||||
|
.status-finished { |
||||
|
color: #6c757d; |
||||
|
text-decoration: line-through; |
||||
|
} |
||||
|
|
||||
|
.status-default { |
||||
|
color: #000; |
||||
|
} |
||||
|
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue