3 changed files with 528 additions and 1 deletions
-
20src/api/advertisingManagement.js
-
15src/router/index.js
-
494src/views/AdvertisingManagement/FloatingWindow.vue
@ -0,0 +1,20 @@ |
|||
import request from '../utils/myAxios'; |
|||
var base_url = import.meta.env.VITE_API_BASE_URL |
|||
|
|||
// 广告管理--首页浮窗活动--获取首页浮窗活动列表
|
|||
export function floatingActivityListApi(params) { |
|||
return request({ |
|||
url: base_url + "/admin/advertising/floating/activity/list", |
|||
method: "post", |
|||
data: params, |
|||
}); |
|||
} |
|||
|
|||
// 广告管理--首页浮窗活动--保存/修改首页浮窗活动
|
|||
export function floatingActivitySaveApi(params) { |
|||
return request({ |
|||
url: base_url + "/admin/advertising/floating/activity/save", |
|||
method: "post", |
|||
data: params, |
|||
}); |
|||
} |
|||
@ -0,0 +1,494 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="search-container"> |
|||
<el-button type="danger" @click="add">添加图片</el-button> |
|||
</div> |
|||
|
|||
<!-- 数据 --> |
|||
<el-table |
|||
:data="tableData" |
|||
style="width: 100%; margin-top: 20px" |
|||
header-cell-class-name="table-header" |
|||
:default-sort="{ prop: null, order: null }" |
|||
class="table-rounded" |
|||
:loading="tableLoading" |
|||
> |
|||
<el-table-column |
|||
prop="id" |
|||
label="序号" |
|||
align="center" |
|||
header-align="center" |
|||
width="80" |
|||
> |
|||
<template #default="scope"> |
|||
{{ (currentPage - 1) * pageSize + scope.$index + 1 }} |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="入口图" align="center" header-align="center"> |
|||
<template #default="scope"> |
|||
<el-image |
|||
:src="scope.row.image" |
|||
style="width: 100px; height: 100px" |
|||
fit="cover" |
|||
/> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="name" |
|||
label="活动名称" |
|||
align="center" |
|||
header-align="center" |
|||
/> |
|||
<el-table-column label="客户权限" align="center" header-align="center"> |
|||
<template #default="scope"> |
|||
{{ formatUserRole(scope.row.user_role) }} |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="活动时间" align="center" header-align="center"> |
|||
<template #default="scope"> |
|||
{{ scope.row.start_time }} 到 {{ scope.row.end_time }} |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column |
|||
prop="created_at" |
|||
label="创建时间" |
|||
align="center" |
|||
header-align="center" |
|||
/> |
|||
<el-table-column |
|||
label="状态" |
|||
prop="status_str" |
|||
align="center" |
|||
header-align="center" |
|||
/> |
|||
<el-table-column label="操作" align="center" header-align="center"> |
|||
<template #default="scope"> |
|||
<el-button type="text" @click="handleEdit(scope.row)">修改</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
|
|||
<!-- 分页组件 --> |
|||
<div class="demo-pagination-block"> |
|||
<el-pagination |
|||
@size-change="handleSizeChange" |
|||
@current-change="handleCurrentChange" |
|||
:current-page="currentPage" |
|||
:page-sizes="[10, 20, 50, 100]" |
|||
:page-size="pageSize" |
|||
layout="total, sizes, prev, pager, next, jumper" |
|||
:total="datatotal" |
|||
/> |
|||
</div> |
|||
<el-dialog |
|||
v-model="dialogFormVisible" |
|||
width="500" |
|||
:show-close="false" |
|||
title="添加图片" |
|||
> |
|||
<el-form |
|||
:model="form" |
|||
style="width: 450px; margin: 0 auto" |
|||
:rules="rules" |
|||
ref="formRef" |
|||
> |
|||
<el-form-item label="活动标题" prop="name"> |
|||
<el-input v-model="form.name" placeholder="请输入" clearable> |
|||
</el-input> |
|||
</el-form-item> |
|||
<el-form-item label="活动图标" prop="image"> |
|||
<el-upload |
|||
ref="uploadRef" |
|||
v-model:file-list="fileList" |
|||
class="avatar-uploader" |
|||
:action="uploadUrl" |
|||
:limit="1" |
|||
list-type="picture-card" |
|||
:on-success="handleSuccess" |
|||
:before-upload="beforeUpload" |
|||
:on-remove="handleRemove" |
|||
:on-exceed="handleExceed" |
|||
> |
|||
<el-icon><Plus /></el-icon> |
|||
</el-upload> |
|||
<div class="tip">建议上传图片大小750*1200像素,支持PNG、JPG格式</div> |
|||
</el-form-item> |
|||
<el-form-item label="活动时间" prop="timeRange"> |
|||
<el-date-picker |
|||
v-model="timeRange" |
|||
type="datetimerange" |
|||
range-separator="至" |
|||
start-placeholder="开始时间" |
|||
end-placeholder="结束时间" |
|||
value-format="YYYY-MM-DD HH:mm:ss" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item label="活动地址" prop="jump_url"> |
|||
<el-input v-model="form.jump_url" placeholder="请输入" clearable> |
|||
</el-input> |
|||
</el-form-item> |
|||
<el-form-item label="客户权限" prop="user_role"> |
|||
<el-checkbox-group v-model="userRoleArray"> |
|||
<el-checkbox label="网员" value="1" /> |
|||
<el-checkbox label="非网" value="2" /> |
|||
<el-checkbox label="游客" value="3" /> |
|||
</el-checkbox-group> |
|||
</el-form-item> |
|||
</el-form> |
|||
<template #footer> |
|||
<div class="dialog-footer"> |
|||
<el-button @click="dialogFormVisible = false">取消</el-button> |
|||
<el-button type="danger" @click="submitForm"> |
|||
提交 |
|||
</el-button> |
|||
</div> |
|||
</template> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, reactive, onMounted, computed, watch, nextTick } from "vue"; |
|||
import { ElMessage, genFileId, ElMessageBox } from "element-plus"; |
|||
import { Plus } from "@element-plus/icons-vue"; // 加上这个引用,否则上面的 <Plus /> 可能会报错 |
|||
import router from "../../router"; |
|||
import { |
|||
floatingActivityListApi, |
|||
floatingActivitySaveApi, |
|||
} from "../../api/advertisingManagement"; |
|||
|
|||
const uploadUrl = import.meta.env.VITE_API_BASE_URLXXCG + "hljw/api/aws/upload"; |
|||
const uploadRef = ref(); |
|||
const fileList = ref([]); |
|||
const formRef = ref(); |
|||
const isEdit = ref(false); |
|||
|
|||
const roleMap = { |
|||
1: "会员", |
|||
2: "非网", |
|||
3: "游客", |
|||
}; |
|||
|
|||
const formatUserRole = (userRole) => { |
|||
if (!userRole) return "-"; |
|||
const roles = userRole.split(",").map((role) => { |
|||
return roleMap[role.trim()] || role.trim(); |
|||
}); |
|||
return roles.join(","); |
|||
}; |
|||
|
|||
const form = reactive({ |
|||
name: "", |
|||
image: "", |
|||
jump_url: "", |
|||
user_role: "", |
|||
start_time: "", |
|||
end_time: "", |
|||
}); |
|||
|
|||
// 赋值后手动清除时间校验报错 |
|||
const timeRange = computed({ |
|||
get() { |
|||
if (form.start_time && form.end_time) { |
|||
return [form.start_time, form.end_time]; |
|||
} |
|||
return []; |
|||
}, |
|||
set(val) { |
|||
if (val && val.length === 2) { |
|||
form.start_time = val[0]; |
|||
form.end_time = val[1]; |
|||
// 手动清除时间校验报错 |
|||
if (formRef.value) formRef.value.clearValidate("start_time"); |
|||
} else { |
|||
form.start_time = ""; |
|||
form.end_time = ""; |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
// 赋值后手动清除权限校验报错 |
|||
const userRoleArray = computed({ |
|||
get() { |
|||
if (form.user_role) { |
|||
return form.user_role.split(","); |
|||
} |
|||
return []; |
|||
}, |
|||
set(val) { |
|||
if (val && val.length > 0) { |
|||
form.user_role = val.join(","); |
|||
// 手动清除客户权限校验报错 |
|||
if (formRef.value) formRef.value.clearValidate("user_role"); |
|||
} else { |
|||
form.user_role = ""; |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
const rules = { |
|||
name: [{ required: true, message: "请输入活动名称", trigger: "blur" }], |
|||
image: [{ required: true, message: "请上传活动图片", trigger: "change" }], |
|||
jump_url: [{ required: true, message: "请输入活动地址", trigger: "blur" }], |
|||
timeRange: [ |
|||
{ |
|||
required: true, |
|||
validator: (rule, value, callback) => { |
|||
if (!form.start_time || !form.end_time) { |
|||
callback(new Error("请选择活动时间")); |
|||
} else { |
|||
callback(); |
|||
} |
|||
}, |
|||
trigger: "change", |
|||
}, |
|||
], |
|||
user_role: [{ required: true, message: "请选择客户权限", trigger: "change" }], |
|||
}; |
|||
|
|||
const handleSuccess = (response, uploadFile) => { |
|||
form.image = response.data.url; // 以前写成了 form.img,已修复 |
|||
if (formRef.value) { |
|||
formRef.value.clearValidate("image"); // 上传成功清除红框报错 |
|||
} |
|||
}; |
|||
|
|||
const beforeUpload = (rawFile) => { |
|||
if (!rawFile.type.startsWith("image/")) { |
|||
ElMessage.error("请上传图片文件!"); |
|||
return false; |
|||
} else if (rawFile.size / 1024 > 100) { |
|||
ElMessage.error("图片大小必须小于100K!"); |
|||
return false; |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
// 删除图片时清空内容并触发重新验证 |
|||
const handleRemove = (file, fileList) => { |
|||
form.image = ""; // 以前写成了 form.img,已修复 |
|||
if (formRef.value) { |
|||
formRef.value.validateField("image"); // 触发报错 |
|||
} |
|||
}; |
|||
|
|||
const handleExceed = (files) => { |
|||
uploadRef.value.clearFiles(); |
|||
const file = files[0]; |
|||
file.uid = genFileId(); |
|||
uploadRef.value.handleStart(file); |
|||
uploadRef.value.submit(); |
|||
}; |
|||
|
|||
const token = localStorage.getItem("token"); |
|||
const dialogFormVisible = ref(false); |
|||
const tableData = ref([]); |
|||
const tableLoading = ref(false); |
|||
const datatotal = ref(0); |
|||
const currentPage = ref(1); |
|||
const pageSize = ref(10); |
|||
|
|||
const resetForm = () => { |
|||
form.id = undefined; |
|||
form.name = ""; |
|||
form.image = ""; |
|||
form.jump_url = ""; |
|||
form.user_role = ""; |
|||
form.start_time = ""; |
|||
form.end_time = ""; |
|||
fileList.value = []; |
|||
}; |
|||
|
|||
const add = () => { |
|||
isEdit.value = false; |
|||
resetForm(); |
|||
dialogFormVisible.value = true; |
|||
nextTick(() => { |
|||
if (formRef.value) { |
|||
formRef.value.clearValidate(); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const submitForm = async () => { |
|||
if (!formRef.value) return; |
|||
|
|||
await formRef.value.validate(async (valid) => { |
|||
if (valid) { |
|||
const params = { |
|||
...form, |
|||
token: token, |
|||
}; |
|||
console.log(params); |
|||
// 提交表单数据 |
|||
await floatingActivitySaveApi(params); |
|||
ElMessage.success("提交成功"); |
|||
dialogFormVisible.value = false; |
|||
fetchTableData(); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const handleEdit = (row) => { |
|||
isEdit.value = true; |
|||
resetForm(); |
|||
form.id = row.id; |
|||
form.name = row.name; |
|||
form.image = row.image; |
|||
form.jump_url = row.jump_url; |
|||
form.user_role = row.user_role; |
|||
form.start_time = row.start_time; |
|||
form.end_time = row.end_time; |
|||
|
|||
if (row.image) { |
|||
fileList.value = [{ name: "图片", url: row.image }]; |
|||
} |
|||
|
|||
dialogFormVisible.value = true; |
|||
|
|||
nextTick(() => { |
|||
isEdit.value = false; |
|||
if (formRef.value) { |
|||
formRef.value.clearValidate(); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const fetchTableData = async () => { |
|||
try { |
|||
tableLoading.value = true; |
|||
const requestParams = { |
|||
token: token, |
|||
page: currentPage.value, |
|||
page_size: pageSize.value, |
|||
}; |
|||
const data = await floatingActivityListApi(requestParams); |
|||
tableData.value = data.list; |
|||
datatotal.value = data.total; |
|||
} catch (error) { |
|||
console.error("获取表格数据失败:", error); |
|||
tableData.value = []; |
|||
datatotal.value = 0; |
|||
} finally { |
|||
tableLoading.value = false; |
|||
} |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
fetchTableData(); |
|||
}); |
|||
|
|||
const handleSizeChange = (val) => { |
|||
pageSize.value = val; |
|||
fetchTableData(); |
|||
}; |
|||
|
|||
const handleCurrentChange = (val) => { |
|||
currentPage.value = val; |
|||
fetchTableData(); |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
/* 父容器 */ |
|||
.page-container { |
|||
position: relative; |
|||
min-height: 600px; |
|||
} |
|||
|
|||
/* 搜索区域 */ |
|||
.search-container { |
|||
display: flex; |
|||
height: auto; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: flex-start; |
|||
gap: 12px; |
|||
align-self: stretch; |
|||
border-radius: 8px; |
|||
background: #fefaf9; |
|||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); |
|||
padding: 15px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
/* 表格样式 */ |
|||
.table-rounded { |
|||
border-radius: 12px !important; |
|||
overflow: hidden !important; |
|||
border: 1px solid #e4e7ed !important; |
|||
height: 750px; |
|||
} |
|||
|
|||
.table-header { |
|||
text-align: center !important; |
|||
font-weight: 800 !important; |
|||
font-size: 15px !important; |
|||
color: #333 !important; |
|||
background-color: #f8f9fa !important; |
|||
} |
|||
|
|||
.el-table__cell { |
|||
border-right: none !important; |
|||
border-bottom: 1px solid #e4e7ed !important; |
|||
} |
|||
|
|||
.el-table__header th.el-table__cell { |
|||
border-right: none !important; |
|||
border-bottom: 1px solid #e4e7ed !important; |
|||
} |
|||
|
|||
.el-table__row:hover .el-table__cell { |
|||
background-color: #fafafa !important; |
|||
} |
|||
|
|||
/* 分页组件样式 */ |
|||
.demo-pagination-block { |
|||
display: flex; |
|||
width: 100%; |
|||
height: 44px; |
|||
padding: 0 16px; |
|||
align-items: center; |
|||
gap: 16px; |
|||
position: absolute; |
|||
margin-top: 10px; |
|||
border-radius: 0 0 3px 3px; |
|||
border-top: 1px solid #eaeaea; |
|||
background: #fefbfb; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.tip { |
|||
font-size: 12px; |
|||
color: #8c939d; |
|||
} |
|||
|
|||
.avatar-uploader .avatar { |
|||
width: 120px; |
|||
height: 120px; |
|||
display: block; |
|||
} |
|||
</style> |
|||
|
|||
<style> |
|||
.avatar-uploader .el-upload { |
|||
border: 1px dashed var(--el-border-color); |
|||
border-radius: 6px; |
|||
cursor: pointer; |
|||
position: relative; |
|||
overflow: hidden; |
|||
transition: var(--el-transition-duration-fast); |
|||
} |
|||
|
|||
.avatar-uploader .el-upload:hover { |
|||
border-color: var(--el-color-primary); |
|||
} |
|||
|
|||
.el-icon.avatar-uploader-icon { |
|||
font-size: 28px; |
|||
color: #8c939d; |
|||
width: 120px; |
|||
height: 120px; |
|||
text-align: center; |
|||
} |
|||
</style> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue