You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

521 lines
19 KiB

<template>
<el-card class="card1" style="margin-bottom: 1vh;">
<div class="condition">
<div class="condition-item1">
<el-text size="large">活动名称</el-text>
<el-input v-model="searchForm.activityName" style="width: 10vw" placeholder="请输入活动名称" clearable />
</div>
<div class="condition-item1">
<el-text size="large">业绩归属:</el-text>
<!-- <el-cascader v-model="searchForm.businessBelong" :options="marketOptions" placeholder="请选择所属地区" clearable
style="width: 10vw" /> -->
<el-select v-model="searchForm.businessBelong" placeholder="请选择业绩归属" style="width: 10vw" clearable>
<el-option label="客户归属地" value="客户归属地" />
<el-option label="活动归属地" value="活动归属地" />
</el-select>
</div>
<div class="condition-item2">
<el-text size="large">开始时间:</el-text>
<el-date-picker v-model="searchForm.startTime" type="datetime" placeholder="请选择开始时间"
format="YYYY-MM-DD HH:mm:ss" :default-time="defaultStartTime" clearable />
</div>
<div class="condition-item2">
<el-text size="large">结束时间:</el-text>
<el-date-picker v-model="searchForm.endTime" type="datetime" placeholder="请选择结束时间"
format="YYYY-MM-DD HH:mm:ss" :default-time="defaultEndTime" clearable />
</div>
<el-button type="primary" @click="getActivity">查询</el-button>
<el-button type="success" @click="reset">重置</el-button>
</div>
</el-card>
<el-card class="card2">
<div class="add-item">
<el-button type="success" @click="showAdd = true" style="margin-top: 1vh;">新增活动</el-button>
</div>
<div>
<el-table :data="tableData" style="width: 82vw;height:70vh;" :row-style="{ height: '50px' }">
<el-table-column type="index" label="序号" width="100px" fixed="left">
<template #default="scope">
<span>{{ scope.$index + 1 + (pagination.pageNum - 1) * pagination.pageSize }}</span>
</template>
</el-table-column>
<el-table-column prop="activityName" label="活动名称" width="150px" show-overflow-tooltip />
<el-table-column prop="businessBelong" label="业绩归属地" width="150px" />
<el-table-column prop="areaName" label="归属地" width="150px" />
<el-table-column prop="startTime" label="开始时间" width="200px">
<template #default="scope">
{{ moment(scope.row.startTime).format('YYYY-MM-DD HH:mm:ss') }}
</template>
</el-table-column>
<el-table-column prop="endTime" label="结束时间" width="200px">
<template #default="scope">
{{
moment(scope.row.endTime).format('YYYY-MM-DD HH:mm:ss')
}}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="150px">
<template #default="scope">
{{ scope.row.status === '0' ? '未开始' :
scope.row.status === '1' ? '进行中' :
scope.row.status === '2' ? '已结束' : scope.row.status
}}
</template>
</el-table-column>
<el-table-column prop="creatorName" label="添加人" width="150px" />
<el-table-column prop="operation" label="操作" width="220px">
<template #default="scope">
<el-button type="primary" text @click="editOpen(scope.row)">编辑</el-button>
<el-button type="danger" text @click="openDel(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div style="margin-top: 20px;display: flex;">
<el-pagination background v-model:current-page="pagination.pageNum" v-model:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" style="margin-top: 1vh;"
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
</div>
</el-card>
<el-dialog v-model="showAdd" width="20vw" draggable align-center style="background-color: rgb(243,250,254);">
<div class="add-item">
<el-text size="large">活动名称:</el-text>
<el-input v-model="addForm.activityName" style="width: 12vw" placeholder="请输入活动名称" maxlength="200" clearable />
</div>
<div class="add-item">
<el-text size="large">业绩归属:</el-text>
<el-radio-group v-model="addForm.businessBelong" style="width: 12vw">
<el-radio size="large" value="客户归属地">客户归属地</el-radio>
<el-radio size="large" value="活动归属地">活动归属地</el-radio>
</el-radio-group>
</div>
<div class="add-item" v-show="addForm.businessBelong === '活动归属地'">
<el-text size="large">所属地区:</el-text>
<el-cascader v-model="addForm.area" :options="marketOptions" placeholder="请选择所属地区" clearable
style="width: 12vw" />
</div>
<div class="add-item">
<el-text size="large">开始时间:</el-text>
<el-date-picker v-model="addForm.startTime" type="datetime" placeholder="请选择开始时间"
:default-time="defaultStartTime" style="width: 12vw" />
</div>
<div class="add-item">
<el-text size="large">结束时间:</el-text>
<el-date-picker v-model="addForm.endTime" type="datetime" placeholder="请选择结束时间"
:default-time="defaultEndTime" style="width: 12vw" />
</div>
<div style="display: flex; justify-content: center; margin-top: 5vh;">
<el-button type="primary" @click="hideAdd">取消</el-button>
<el-button type="primary" @click="throttleGetActivity">确定</el-button>
</div>
</el-dialog>
<el-dialog v-model="showEdit" width="20vw" draggable align-center style="background-color: rgb(243,250,254);">
<div class="edit-item">
<el-text size="large">活动名称:</el-text>
<el-input v-model="editForm.activityName" style="width: 12vw" placeholder="请输入活动名称" maxlength="200" clearable />
</div>
<div class="edit-item">
<el-text size="large">业绩归属:</el-text>
<el-radio-group v-model="editForm.businessBelong" style="width: 12vw">
<el-radio size="large" value="客户归属地">客户归属地</el-radio>
<el-radio size="large" value="活动归属地">活动归属地</el-radio>
</el-radio-group>
</div>
<div class="edit-item" v-show="editForm.businessBelong === '活动归属地'">
<el-text size="large">所属地区:</el-text>
<el-cascader v-model="editForm.area" :options="marketOptions" placeholder="请选择所属地区" clearable
style="width: 12vw" />
</div>
<div class="edit-item">
<el-text size="large">开始时间:</el-text>
<el-date-picker v-model="editForm.startTime" type="datetime" placeholder="请选择开始时间"
:default-time="defaultStartTime" style="width: 12vw" />
</div>
<div class="edit-item">
<el-text size="large">结束时间:</el-text>
<el-date-picker v-model="editForm.endTime" type="datetime" placeholder="请选择结束时间"
:default-time="defaultEndTime" style="width: 12vw" />
</div>
<div style="display: flex; justify-content: center; margin-top: 5vh;">
<el-button type="primary" @click="hideEdit">取消</el-button>
<el-button type="primary" @click="handleEdit">确定</el-button>
</div>
</el-dialog>
<ConfirmDialog v-model="showDel" message="删除该活动数据" @confirm="handleDel()" @cancel="hideDel" @close="hideDel" />
</template>
<script setup>
import { ElMessage, ElPagination } from 'element-plus';
import { onMounted, ref } from 'vue'
import API from "@/util/http.js"
import moment from 'moment'
import { useAdminStore } from "@/store/index.js"
import { storeToRefs } from "pinia"
import { permissionMapping, hasMenuPermission } from "@/utils/menuTreePermission.js"
const adminStore = useAdminStore();
const { adminData, menuTree } = storeToRefs(adminStore)
import ConfirmDialog from '@/components/dialogs/ConfirmDialog.vue'
import _ from 'lodash'
// 活动名称正则表达式
const activityNameReg = /^[\u4e00-\u9fa5a-zA-Z0-9,。!?、;:“”()‘’《》【】{}——~,.!?:;'--()""\[\]_&+=]+$/;
// 为什么一定要两个--才能成功?????????
const tableData = ref([])
const pagination = ref({
pageNum: 1,
pageSize: 10,
total: 0
})
const searchForm = ref({
activityName: ''
})
const showAdd = ref(false)
const showEdit = ref(false)
const showDel = ref(false)
const currentDelRow = ref(null)
const addForm = ref({
activityName: '',
area: []
})
const editForm = ref({
activityName: '',
businessBelong: '',
area: [],
startTime: null,
endTime: null,
id: ''
})
const marketOptions = ref([])
const getActivity = async function () {
const rechargeActivity = {
activityName: searchForm.value.activityName,
businessBelong: searchForm.value.businessBelong,
}
if (searchForm.value.startTime && moment(searchForm.value.startTime).isValid()) {
rechargeActivity.startTime = moment(searchForm.value.startTime).format('YYYY-MM-DD HH:mm:ss');
}
if (searchForm.value.endTime && moment(searchForm.value.endTime).isValid()) {
rechargeActivity.endTime = moment(searchForm.value.endTime).format('YYYY-MM-DD HH:mm:ss');
}
const params = {
pageNum: pagination.value.pageNum,
pageSize: pagination.value.pageSize,
rechargeActivity
}
const res = await API({
url: '/admin/coin/rechargeActivityCenter/queryActivity',
data: params
})
if (res.code === 200) {
tableData.value = res.data.list
pagination.value.total = res.data.total
}
}
const handleAdd = async function () {
const activityName = addForm.value.activityName
if (!validateActivityName(activityName)) return
if (!addForm.value.businessBelong) {
ElMessage.error('请选择业绩归属')
return
}
if (addForm.value.businessBelong === '活动归属地' && addForm.value.area.length === 0) {
ElMessage.error('请选择所属地区')
return
}
if (!addForm.value.startTime) {
ElMessage.error('请选择开始时间')
return
}
if (!addForm.value.endTime) {
ElMessage.error('请选择结束时间')
return
}
if (addForm.value.businessBelong === '客户归属地') {
addForm.value.area = []
}
const params = {
activityName: addForm.value.activityName,
businessBelong: addForm.value.businessBelong,
area: addForm.value.area.length > 0 ? addForm.value.area.slice(-1)[0] : null,
startTime: moment(addForm.value.startTime).format('YYYY-MM-DD HH:mm:ss'),
endTime: moment(addForm.value.endTime).format('YYYY-MM-DD HH:mm:ss'),
creator: adminData.value.id
}
const res = await API({
url: '/admin/coin/rechargeActivityCenter/addActivity',
data: params
})
if (res.code === 200) {
ElMessage.success('添加成功')
getActivity()
hideAdd()
addForm.value = {
activityName: '',
businessBelong: '',
area: [],
startTime: null,
endTime: null,
}
} else {
ElMessage.error(res.msg || '添加失败')
return
}
}
// 新增节流
const throttleGetActivity = _.throttle(handleAdd, 5000, { trailing: false });
const handleEdit = async function () {
const activityName = editForm.value.activityName
if (!validateActivityName(activityName)) return
if (!editForm.value.activityName) {
ElMessage.error('请输入活动名称')
return
}
if (!editForm.value.businessBelong) {
ElMessage.error('请选择业绩归属')
return
}
if (editForm.value.businessBelong === '活动归属地' && editForm.value.area.length === 0) {
ElMessage.error('请选择所属地区')
return
}
if (!editForm.value.startTime) {
ElMessage.error('请选择开始时间')
return
}
if (!editForm.value.endTime) {
ElMessage.error('请选择结束时间')
return
}
if(editForm.value.businessBelong === '客户归属地'){
editForm.value.area = []
}
const params = {
id: editForm.value.id,
activityName: editForm.value.activityName,
businessBelong: editForm.value.businessBelong,
area: editForm.value.area.length > 0 ? editForm.value.area.slice(-1)[0] : null,
startTime: moment(editForm.value.startTime).format('YYYY-MM-DD HH:mm:ss'),
endTime: moment(editForm.value.endTime).format('YYYY-MM-DD HH:mm:ss'),
creator: adminData.value.id
}
console.log('看看修改params', params)
const res = await API({
url: '/admin/coin/rechargeActivityCenter/updateActivity',
data: params
})
if (res.code === 200) {
ElMessage.success('修改成功')
getActivity()
hideEdit()
}
}
const handleDel = async function (row) {
if (!currentDelRow.value) {
ElMessage.error('当前选择无数据')
return
}
const res = await API({
url: '/admin/coin/rechargeActivityCenter/deleteActivity',
data: {
id: currentDelRow.value.id,
}
})
if (res.code === 200) {
ElMessage.success('删除成功')
getActivity()
showDel.value = false
}
}
const getmarkets = async function () {
try {
const result = await API({
url: '/market/selectMarket',
});
console.log('请求成功', result)
// 递归转换树形结构为级联选择器需要的格式(跳过第一级节点)
const transformTree = (nodes) => {
// 直接处理第一级节点的子节点
const allChildren = nodes.flatMap(node => node.children || []);
return allChildren.map(child => {
const grandchildren = child.children && child.children.length
? transformTree([child]) // 递归处理子节点
: null;
return {
value: child.id,
label: child.name,
children: grandchildren
}
})
}
marketOptions.value = transformTree(result.data)
console.log('转换后的地区树', marketOptions.value)
} catch (error) {
console.log('请求失败', error)
}
}
const defaultStartTime = [
new Date(2000, 1, 1, 0, 0, 0)
]
const defaultEndTime = [
new Date(2000, 2, 1, 23, 59, 59)
]
const hideEdit = () => {
showEdit.value = false
editForm.value = {
activityName: '',
businessBelong: '',
area: [],
startTime: null,
endTime: null,
id: ''
}
}
const editOpen = (row) => {
editForm.value = {
id: row.id,
activityName: row.activityName,
businessBelong: row.businessBelong,
area: row.area ? [...row.area] : []
}
if (row.startTime) {
editForm.value.startTime = moment(row.startTime).toDate()
}
if (row.endTime) {
editForm.value.endTime = moment(row.endTime).toDate()
}
console.log('看看editForm', editForm.value)
showEdit.value = true
}
const openDel = (row) => {
currentDelRow.value = row
showDel.value = true
}
const hideDel = () => {
showDel.value = false
currentDelRow.value = null
}
const reset = () => {
searchForm.value = {
activityName: '',
businessBelong: '',
startTime: null,
endTime: null
}
getActivity()
}
const hideAdd = () => {
showAdd.value = false
addForm.value = {
activityName: '',
area: [],
startTime: null,
endTime: null
}
}
const validateActivityName = (name) => {
// 非空校验
if (!name.trim()) {
ElMessage.error('活动名称不能为空');
return false;
}
// 长度校验(限制100字符)
if (name.length > 100) {
ElMessage.error('活动名称长度不能超过100字符');
return false;
}
// 字符格式校验
if (!activityNameReg.test(name)) {
ElMessage.error('活动名称仅支持汉字、英文字母、数字及常见标点,中文字符,。!?、;:“ ” ‘ ’ ()《》【】——~,英文字符, . ! ? : ; " ( ) [ ] - _ & + =/')
return false;
}
return true;
};
const handleSizeChange = function (val) {
pagination.pageSize = val
getActivity()
}
const handleCurrentChange = function (val) {
pagination.pageNum = val
getActivity()
}
onMounted(() => {
getActivity()
getmarkets()
console.log('看看adminData', adminData.value)
})
</script>
<style scoped lang="scss">
// 搜索的卡片样式
.card1 {
background: #F3FAFE;
}
// 表单的卡片样式
.card2 {
background: #E7F4FD;
}
// 表头背景等
:deep(.el-table__header-wrapper),
:deep(.el-table__body-wrapper),
:deep(.el-table__cell),
/* 表格 */
:deep(.el-table__body td) {
background-color: #F3FAFE !important;
}
/* 表头 */
:deep(.el-table__header th) {
background-color: #F3FAFE !important;
}
/* 鼠标悬停 */
:deep(.el-table__row:hover > .el-table__cell) {
background-color: #E5EBFE !important;
}
.condition {
display: flex;
align-items: center;
}
.condition-item1 {
display: flex;
align-items: center;
width: 15vw;
}
.condition-item2 {
display: flex;
align-items: center;
width: 17vw;
}
.add-item {
display: flex;
align-items: center;
width: 17vw;
margin-bottom: 1vh;
}
.edit-item {
display: flex;
align-items: center;
width: 17vw;
margin-bottom: 1vh;
}
</style>