4 changed files with 967 additions and 1 deletions
-
38src/api/advertisingManagement.js
-
21src/router/index.js
-
490src/views/AdvertisingManagement/FloatingWindow.vue
-
419src/views/AdvertisingManagement/PushManagement.vue
@ -0,0 +1,38 @@ |
|||||
|
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, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 广告管理--APP推送管理--获取APP推送管理列表
|
||||
|
export function pushManagementListApi(params) { |
||||
|
return request({ |
||||
|
url: base_url + "/admin/advertising/app/push/list", |
||||
|
method: "post", |
||||
|
data: params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 广告管理--APP推送管理--添加推送
|
||||
|
export function pushManagementSaveApi(params) { |
||||
|
return request({ |
||||
|
url: base_url + "/admin/advertising/app/push/save", |
||||
|
method: "post", |
||||
|
data: params, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,490 @@ |
|||||
|
<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="[5, 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, nextTick } from "vue"; |
||||
|
import { ElMessage, genFileId } from "element-plus"; |
||||
|
import { Plus } from "@element-plus/icons-vue"; // 加上这个引用,否则上面的 <Plus /> 可能会报错 |
||||
|
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; |
||||
|
if (formRef.value) { |
||||
|
formRef.value.clearValidate("image"); // 上传成功清除红框报错 |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const beforeUpload = (rawFile) => { |
||||
|
if (!rawFile.type.startsWith("image/")) { |
||||
|
ElMessage.error("请上传图片文件!"); |
||||
|
return false; |
||||
|
} else if (rawFile.size / 1024 > 500) { |
||||
|
ElMessage.error("图片大小必须小于500K!"); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
}; |
||||
|
|
||||
|
// 删除图片时清空内容并触发重新验证 |
||||
|
const handleRemove = (file, fileList) => { |
||||
|
form.image = ""; |
||||
|
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(5); |
||||
|
|
||||
|
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, |
||||
|
}; |
||||
|
// 提交表单数据 |
||||
|
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> |
||||
@ -0,0 +1,419 @@ |
|||||
|
<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 |
||||
|
prop="title" |
||||
|
label="浮窗标题" |
||||
|
align="center" |
||||
|
header-align="center" |
||||
|
width="240" |
||||
|
/> |
||||
|
<el-table-column |
||||
|
prop="content" |
||||
|
label="浮窗正文" |
||||
|
align="center" |
||||
|
header-align="center" |
||||
|
/> |
||||
|
<el-table-column |
||||
|
label="客户权限" |
||||
|
align="center" |
||||
|
header-align="center" |
||||
|
width="120" |
||||
|
> |
||||
|
<template #default="scope"> |
||||
|
{{ formatUserRole(scope.row.user_role) }} |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
<el-table-column |
||||
|
prop="push_time" |
||||
|
label="推送时间" |
||||
|
align="center" |
||||
|
header-align="center" |
||||
|
width="180" |
||||
|
/> |
||||
|
<el-table-column |
||||
|
label="推送状态" |
||||
|
prop="status_str" |
||||
|
align="center" |
||||
|
header-align="center" |
||||
|
width="120" |
||||
|
/> |
||||
|
<el-table-column |
||||
|
label="操作" |
||||
|
align="center" |
||||
|
header-align="center" |
||||
|
width="120" |
||||
|
> |
||||
|
<template #default="scope"> |
||||
|
<el-button |
||||
|
type="text" |
||||
|
:disabled="scope.row.push_status !== 1" |
||||
|
@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="[5, 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="title"> |
||||
|
<el-input v-model="form.title" placeholder="请输入" clearable> |
||||
|
</el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="浮窗正文" prop="content"> |
||||
|
<el-input |
||||
|
v-model="form.content" |
||||
|
placeholder="请输入" |
||||
|
clearable |
||||
|
type="textarea" |
||||
|
> |
||||
|
</el-input> |
||||
|
</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-item label="推送时间" prop="push_time"> |
||||
|
<el-date-picker |
||||
|
v-model="form.push_time" |
||||
|
type="datetime" |
||||
|
placeholder="请选择推送时间" |
||||
|
value-format="YYYY-MM-DD HH:mm:ss" |
||||
|
:disabled-date="disabledDate" |
||||
|
:default-time="defaultTime" |
||||
|
/> |
||||
|
</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, nextTick } from "vue"; |
||||
|
import { ElMessage } from "element-plus"; |
||||
|
import { |
||||
|
pushManagementListApi, |
||||
|
pushManagementSaveApi, |
||||
|
} from "../../api/advertisingManagement"; |
||||
|
|
||||
|
const formRef = ref(); |
||||
|
const isEdit = ref(false); |
||||
|
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(5); |
||||
|
|
||||
|
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({ |
||||
|
id: undefined, // 建议加上 id 预设,防止响应式丢失 |
||||
|
title: "", |
||||
|
content: "", |
||||
|
jump_url: "", |
||||
|
user_role: "", |
||||
|
push_time: "", |
||||
|
}); |
||||
|
|
||||
|
const resetForm = () => { |
||||
|
form.id = undefined; |
||||
|
form.title = ""; |
||||
|
form.content = ""; |
||||
|
form.jump_url = ""; |
||||
|
form.user_role = ""; |
||||
|
form.push_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 = { |
||||
|
title: [ |
||||
|
{ required: true, message: "请输入浮窗标题", trigger: "blur" }, |
||||
|
{ min: 1, max: 20, message: "浮窗标题字数在20字以内", trigger: "blur" }, |
||||
|
], |
||||
|
content: [ |
||||
|
{ required: true, message: "请输入浮窗正文", trigger: "blur" }, |
||||
|
{ min: 1, max: 100, message: "浮窗正文字数在100字以内", trigger: "blur" }, // 提示文案修复为100字 |
||||
|
], |
||||
|
jump_url: [{ required: true, message: "请输入跳转链接", trigger: "blur" }], |
||||
|
user_role: [{ required: true, message: "请选择客户权限", trigger: "change" }], |
||||
|
push_time: [ |
||||
|
{ |
||||
|
validator: (rule, value, callback) => { |
||||
|
// 如果没有填值,直接通过校验(非必填) |
||||
|
if (!value) { |
||||
|
callback(); |
||||
|
return; |
||||
|
} |
||||
|
// 如果填写值,则将选择的值转换为时间戳 |
||||
|
const selectedTime = new Date(value).getTime(); |
||||
|
const currentTime = Date.now(); |
||||
|
|
||||
|
// 如果选择的时间早于当前时间,报错 |
||||
|
if (selectedTime < currentTime) { |
||||
|
callback(new Error("推送时间不能早于当前时间")); |
||||
|
} else { |
||||
|
callback(); |
||||
|
} |
||||
|
}, |
||||
|
trigger: "change", |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
|
||||
|
const disabledDate = (time) => { |
||||
|
// 获取今天的凌晨 00:00:00 时间戳 |
||||
|
const today = new Date(); |
||||
|
today.setHours(0, 0, 0, 0); |
||||
|
// time.getTime() 是面板上每个格子的时间,小于今天凌晨的全部禁用 |
||||
|
return time.getTime() < today.getTime(); |
||||
|
}; |
||||
|
|
||||
|
// 限制:点击日期面板时,默认时间填充为当前时间,而不是 00:00:00 |
||||
|
const defaultTime = ref(new Date()); |
||||
|
|
||||
|
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, |
||||
|
}; |
||||
|
// 提交表单数据 |
||||
|
await pushManagementSaveApi(params); |
||||
|
ElMessage.success("提交成功"); |
||||
|
dialogFormVisible.value = false; |
||||
|
fetchTableData(); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const handleEdit = (row) => { |
||||
|
isEdit.value = true; |
||||
|
resetForm(); |
||||
|
form.id = row.id; |
||||
|
form.title = row.title; |
||||
|
form.content = row.content; |
||||
|
form.jump_url = row.jump_url; |
||||
|
form.user_role = row.user_role; |
||||
|
form.push_time = row.push_time; |
||||
|
|
||||
|
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 pushManagementListApi(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; |
||||
|
} |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue