Browse Source

Merge branch 'milestone-20260405-新增推送和浮窗' into dev

dev
zhaowenkang 7 days ago
parent
commit
7e5798fe76
  1. 18
      src/api/advertisingManagement.js
  2. 6
      src/router/index.js
  3. 14
      src/views/AdvertisingManagement/FloatingWindow.vue
  4. 419
      src/views/AdvertisingManagement/PushManagement.vue

18
src/api/advertisingManagement.js

@ -18,3 +18,21 @@ export function floatingActivitySaveApi(params) {
data: params, 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,
});
}

6
src/router/index.js

@ -182,6 +182,12 @@ const routes = [
component: () => import('../views/AdvertisingManagement/FloatingWindow.vue'), component: () => import('../views/AdvertisingManagement/FloatingWindow.vue'),
meta: { title: '首页浮窗活动', showSidebar: true }, meta: { title: '首页浮窗活动', showSidebar: true },
}, },
{
path: 'PushManagement',
name: 'PushManagement',
component: () => import('../views/AdvertisingManagement/PushManagement.vue'),
meta: { title: 'APP推送管理', showSidebar: true },
},
] ]
}, },
] ]

14
src/views/AdvertisingManagement/FloatingWindow.vue

@ -74,7 +74,7 @@
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
:current-page="currentPage" :current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[5, 10, 20, 50, 100]"
:page-size="pageSize" :page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:total="datatotal" :total="datatotal"
@ -138,9 +138,7 @@
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button> <el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="danger" @click="submitForm">
提交
</el-button>
<el-button type="danger" @click="submitForm"> 提交 </el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -148,10 +146,9 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, computed, watch, nextTick } from "vue";
import { ElMessage, genFileId, ElMessageBox } from "element-plus";
import { ref, reactive, onMounted, computed, nextTick } from "vue";
import { ElMessage, genFileId } from "element-plus";
import { Plus } from "@element-plus/icons-vue"; // <Plus /> import { Plus } from "@element-plus/icons-vue"; // <Plus />
import router from "../../router";
import { import {
floatingActivityListApi, floatingActivityListApi,
floatingActivitySaveApi, floatingActivitySaveApi,
@ -286,7 +283,7 @@ const tableData = ref([]);
const tableLoading = ref(false); const tableLoading = ref(false);
const datatotal = ref(0); const datatotal = ref(0);
const currentPage = ref(1); const currentPage = ref(1);
const pageSize = ref(10);
const pageSize = ref(5);
const resetForm = () => { const resetForm = () => {
form.id = undefined; form.id = undefined;
@ -319,7 +316,6 @@ const submitForm = async () => {
...form, ...form,
token: token, token: token,
}; };
console.log(params);
// //
await floatingActivitySaveApi(params); await floatingActivitySaveApi(params);
ElMessage.success("提交成功"); ElMessage.success("提交成功");

419
src/views/AdvertisingManagement/PushManagement.vue

@ -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>
Loading…
Cancel
Save