提交 9ce234cc authored 作者: lidongxu's avatar lidongxu

refactor(promotion/plan): 优化了促销计划的全部代码_并且设置 7 号开始及以后当月城市经理无法新增和上传计划

同上
上级 b27ea9dc
// 促销系统身份
export const CITY_MANAGER = 'cityManager' // 城市经理
export const FUNCTION_ROLE = 'functionRole' // 职能角色
const promotionRoles = {
0: FUNCTION_ROLE, // 职能角色
1: CITY_MANAGER // 城市经理
}
export const getPromotionRole = (role) => {
return promotionRoles[role] || '未知身份'
}
// 促销活动状态
export const NOT_EXECUTION = 'NOT_EXECUTION' // 未执行
export const EXECUTION = 'EXECUTION' // 执行
// 后台:返回数字,又让我传给他英文字符
export const PROMOTION_STATUS = {
0: {
label: '未执行',
value: NOT_EXECUTION
},
1: {
label: '执行',
value: EXECUTION
}
}
export const getPromotionActiveStatus = (statusNum) => {
return PROMOTION_STATUS[statusNum] || { label: '未知状态', value: '' }
}
export * from './promotion/index.js'
export * from './date.js'
export * from './resize.js'
export const usePromotionHooks = () => {
/**
* 判断某个身份在指定日期号码是否有上传权限
* @param {*} isCityManager 城市经理 true,职能角色 false
* @param {*} dateNum 指定日期号码 1-31
* @returns
*/
const isUpDisRef = ref(true)
const checkUpDis = (isCityManager, dateNum) => {
isUpDisRef.value = (new Date().getDate() >= dateNum && isCityManager.value)
}
return {
isUpDisRef,
checkUpDis
}
}
<template>
<div class="mobile-container">
<van-nav-bar
right-text="搜索"
<van-nav-bar right-text="搜索"
@click-right="showSearch = true"
placeholder
fixed />
......@@ -40,8 +39,7 @@
<!-- 快捷时间 -->
<van-field readonly
label="快捷时间"
placeholder="选择时间"
>
placeholder="选择时间">
<template #input>
<van-button size="small"
type="primary"
......@@ -121,7 +119,7 @@
<template #title>
<van-search v-model="searchEmployeeName"
placeholder="搜索归属人"
@update:model-value="onSearch"/>
@update:model-value="onSearch" />
</template>
</van-picker>
</van-popup>
......@@ -420,7 +418,7 @@ const resetFn = () => {
font-size: 14px !important;
}
.van-search{
.van-search {
width: 60%;
}
</style>
\ No newline at end of file
......@@ -90,6 +90,16 @@ export default defineStore(
// })
})
}
},
getters: {
// 获取促销系统身份
getPromotionIdentity(state) {
return state.userInfo.privilegeId
},
// 获取员工工号
getEmployeeNo(state) {
return state.userInfo.userName
}
}
})
......@@ -82,7 +82,7 @@
@change="getPlanList"
filterable
remote
:remote-method="remoteMethod"
:remote-method="zoneRemoteSearch"
clearable>
<el-option v-for="item in zoneList"
:key="item.value"
......@@ -93,10 +93,10 @@
<el-form-item label="战区"
prop="warzone">
<el-select v-model="queryParams.warzoneId"
placeholder="请选择战区"
placeholder="搜索战区"
filterable
clearable
:disabled="cityManagerPrivilege"
:disabled="isCityManager"
@change="getPlanList">
<el-option v-for="item in warZoneList"
:key="item.value"
......@@ -105,24 +105,24 @@
</el-select>
</el-form-item>
<el-form-item label="归属人"
prop="manager">
prop="belongPer">
<el-select v-model="queryParams.employeeId"
placeholder="请选择归属人(搜索)"
placeholder="搜索归属人"
filterable
clearable
:disabled="cityManagerPrivilege"
:disabled="isCityManager"
@change="getPlanList">
<el-option v-for="item in managerList"
<el-option v-for="item in belongPerList"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="终端名"
<el-form-item label="店铺名"
prop="store">
<el-input v-model="queryParams.storeName"
clearable
placeholder="请输入门店名称"
placeholder="搜索店铺名"
@input="getPlanList" />
</el-form-item>
</el-row>
......@@ -134,15 +134,17 @@
<el-button type="danger"
plain
icon="Delete"
:disabled="multiple"
:disabled="delMultipleBtnDis"
@click="handleDelete">删除</el-button>
<el-button type="success"
plain
icon="Plus"
:disabled="isUpDisRef"
@click="handleAdd">新增</el-button>
<el-button type="primary"
plain
icon="Edit"
:disabled="editMultipleBtnDis"
@click="handleEditEmp">修改归属人</el-button>
<el-button type="warning"
plain
......@@ -158,7 +160,11 @@
:http-request="uploadFile"
:show-file-list="false">
<template #trigger>
<el-button type="primary">{{ cityManagerPrivilege ? '城市经理' : '职能角色' }}-新增计划上传</el-button>
<el-button type="primary"
:disabled="isUpDisRef">
{{ isCityManager ? '城市经理' : '职能角色' }}
{{ isUpDisRef ? '当月 ' + upDisDate + ' 号后无法新增上传' : '-新增计划上传' }}
</el-button>
</template>
</el-upload>
<el-upload class="upload-demo"
......@@ -331,7 +337,7 @@
clearable
style="width: 95%"
@change="selEmployee">
<el-option v-for="item in managerList"
<el-option v-for="item in belongPerList"
:key="item.employeeNo"
:label="item.label"
:value="item.employeeNo" />
......@@ -418,7 +424,7 @@
placeholder="请选择归属人(搜索)"
filterable
clearable>
<el-option v-for="item in managerList"
<el-option v-for="item in belongPerList"
:key="item.value"
:label="item.label"
:value="item.value" />
......@@ -449,45 +455,51 @@ import { getPlanListAPI, uploadFileToOSSAPI, addPlanAPI, savePlanAPI, deletePlan
import { useDatePickerOptions } from '@/hooks'
import { v4 as uuidv4 } from 'uuid';
import store from '@/store'
import userStore from '@/store/modules/user'
import { getPromotionRole, getPromotionActiveStatus } from '@/dicts'
import { CITY_MANAGER, PROMOTION_STATUS } from '@/dicts'
import { parseTime } from '@/utils'
import { ElMessage, ElMessageBox } from 'element-plus';
import { usePromotionHooks } from '@/hooks'
const { proxy } = getCurrentInstance();
// 城市经理状态为 true
const cityManagerPrivilege = computed(() => {
return store.state?.value?.user?.userInfo?.privilegeId == 1
})
const isCityManager = ref(getPromotionRole(userStore().getPromotionIdentity) === CITY_MANAGER)
const { isUpDisRef, checkUpDis } = usePromotionHooks()
const upDisDate = 7
checkUpDis(isCityManager, upDisDate) // 几号以后城市经理禁止上传新增计划
const { recentPickerOptions: pickerOptions, thisYearDate } = useDatePickerOptions(0)
const { recentPickerOptions: pickerOptions } = useDatePickerOptions()
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
activityDate: [],
planStatus: '',
region: '全国',
provinceId: '',
cityId: '',
zoneId: '', // 经销商
warzoneId: '', // 战区
employeeId: '', // 归属人
storeName: '', // 门店名称
pageNum: 1,
pageSize: 10,
})
const taskStatusList = ref([
{
label: '执行',
value: 'EXECUTION'
},
{
label: '未执行',
value: 'NOT_EXECUTION'
}
])
// 查询参数-区域查询
const taskStatusList = ref(Object.values(PROMOTION_STATUS))
// 区域查询切换
const provinceList = ref([])
const cityList = ref([])
// 获取省份和城市列表
const getProCity = async () => {
const { data } = await getProCityAPI(queryParams)
// 本次省份里有值,证明 data 是城市数据
if (queryParams.provinceId) {
queryParams.cityId = undefined
queryParams.cityId = ''
cityList.value = data.map(item => ({
label: item.name,
value: item.num
}))
} else {
queryParams.cityId = undefined
// 省份列表数据
queryParams.cityId = ''
cityList.value = []
provinceList.value = data.map(item => ({
label: item.name,
......@@ -496,11 +508,24 @@ const getProCity = async () => {
}
getPlanList()
}
getProCity()
// 切换
const regionChange = (val) => {
if (val === '全国') {
queryParams.provinceId = ''
queryParams.cityId = ''
} else if (val === '省') {
queryParams.cityId = ''
} else if (val === '省-市') {
cityList.value = []
getProCity()
}
getPlanList()
}
// 查询经销商列表
const zoneList = ref([])
const getDealerList = async () => {
const getZoneList = async () => {
const { data } = await getDealerListAPI(queryParams)
zoneList.value = data.map(item => {
return {
......@@ -509,12 +534,12 @@ const getDealerList = async () => {
}
})
}
// 经销商远程搜索
const remoteMethod = (query) => {
// 经销商远程搜索(点击输入框自动触发)
const zoneRemoteSearch = (query) => {
queryParams.dealerName = query
getDealerList()
getZoneList()
}
getDealerList()
// 查询战区列表
const warZoneList = ref([])
const getWarZoneList = async () => {
......@@ -526,12 +551,12 @@ const getWarZoneList = async () => {
}
})
}
getWarZoneList()
// 查询归属人列表
const managerList = ref([])
const getChargeList = async () => {
const belongPerList = ref([])
const getBelongPerList = async () => {
const { data } = await getChargeListAPI()
managerList.value = data.map(item => {
belongPerList.value = data.map(item => {
return {
label: item.name,
value: item.id,
......@@ -541,52 +566,34 @@ const getChargeList = async () => {
}
})
}
getChargeList()
// 区域查询切换
const regionChange = (val) => {
if (val === '全国') {
queryParams.provinceId = undefined
queryParams.cityId = undefined
} else if (val === '省') {
queryParams.cityId = undefined
} else if (val === '省-市') {
cityList.value = []
getProCity()
}
getPlanList()
}
// 表格复选框的数据
const checkedRowList = ref([])
// 全选
// 同时删除多行的按钮禁用状态
const delMultipleBtnDis = ref(true)
// 同时修改多行的归属人禁用状态
const editMultipleBtnDis = ref(true)
// 表格全选复选框点击
const handleSelectionChange = (val) => {
checkedRowList.value = val
multiple.value = !(checkedRowList.value.length > 0)
delMultipleBtnDis.value = !(checkedRowList.value.length > 0)
editMultipleBtnDis.value = !(checkedRowList.value.length > 0)
}
// 任务列表
const tableList = ref([])
const total = ref(0)
const multiple = ref(true)
const columns = ref([
{
label: '归属人',
prop: 'employeeName',
width: 150,
fixed: true
},
// {
// label: '归属人工号',
// prop: 'employeeNo',
// width: 140
// },
{
label: '战区',
prop: 'orgName',
width: 150
width: 120
},
{
label: '店铺名称',
......@@ -596,7 +603,7 @@ const columns = ref([
{
label: '活动日期',
prop: 'date',
width: 180
width: 120
},
{
label: '星期',
......@@ -636,7 +643,7 @@ const columns = ref([
{
label: '省份',
prop: 'province',
width: 130
width: 100
},
{
label: '地址',
......@@ -663,12 +670,6 @@ const columns = ref([
prop: 'incidentals',
width: 100
},
// {
// label: '城市',
// prop: 'city',
// width: 100
// },
{
label: '创建人',
prop: 'createBy',
......@@ -682,36 +683,39 @@ const columns = ref([
{
label: '最后修改时间',
prop: 'modifyTime',
width: 250
width: 180
},
{
label: '活动 ID',
prop: 'id',
width: 90,
// fixed: true
width: 90
}
])
const getPlanList = async () => {
// 后台省市不要 id,自己查个名字给后台
// 后台:省市不要 id,查个名字给后台(但是省市区接口还得用 id,所以 queryParams 上还必须绑定 id)
queryParams.province = provinceList.value.find(item => item.value === queryParams.provinceId)?.label
queryParams.city = cityList.value.find(item => item.value === queryParams.cityId)?.label
// 城市经理查自己,职能角色查所有(需要的是促销系统 id)
if (cityManagerPrivilege.value) {
// 城市经理
await getChargeList()
queryParams.employeeId = managerList.value.find(item => item.employeeNo === store.state.value.user.userInfo.userName)?.value
// 城市经理查自己,职能角色查所有
if (isCityManager.value) {
// 城市经理 (用员工 ID(1,2,3),而不是工号,employeeNo 是工号(000535))
queryParams.employeeId = belongPerList.value.find(item => item.employeeNo === userStore().getEmployeeNo)?.value
// 先从归属人查询当前登录用户的战区 ID
queryParams.warzoneId = managerList.value.find(item => item.employeeNo === store.state.value.user.userInfo.userName)?.deptQcId
queryParams.warzoneId = belongPerList.value.find(item => item.employeeNo === userStore().getEmployeeNo)?.deptQcId
}
// 日期格式化一下
if (queryParams.activityDate?.length > 0) {
queryParams.activityDate = queryParams.activityDate.map(item => parseTime(item, '{y}-{m}-{d}'))
}
const res = await getPlanListAPI(queryParams)
tableList.value = res.data.records
total.value = res.data.totalRecord
}
getPlanList()
// 格式化计划列表单元格内容
const formatter = (row, col, value) => {
if (col.property === 'planStatus') {
return value == 0 ? '未执行' : '执行'
} else if (col.property === 'date') {
return getPromotionActiveStatus(value)?.label
} else if (col.property === 'date') { // 活动日期
return parseTime(value, '{y}-{m}-{d}')
} else if (col.property === 'week') {
return parseTime(row['date'], '周{a}')
......@@ -720,7 +724,7 @@ const formatter = (row, col, value) => {
} else if (col.property === 'clockInTime' || col.property === 'clockOutTime') {
return parseTime(value)
} else if (col.property === 'employeeName') {
// 判断名字小于 4 个字,少于几个就加几个空格
// 判断归属人名字小于 4 个字,少于几个就加几个空格
if (value.length === 2) {
return value + '  ' + '(' + row.employeeNo + ')'
} else if (value.length === 3) {
......@@ -734,10 +738,9 @@ const formatter = (row, col, value) => {
return value
}
}
// 判断计划是否过期
// 判断计划是否过期(上班开始后 1 小时无法编辑和删除)
const checkPlanExpire = (row) => {
const date = new Date()
// const targetDate = new Date(`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours() + 1}:${date.getMinutes()}:${date.getSeconds()}`)
const rowDate = new Date(row.clockInTime)
rowDate.setHours(rowDate.getHours() + 1)
if (rowDate < date || row.planStatus === 1) {
......@@ -747,11 +750,11 @@ const checkPlanExpire = (row) => {
return true
}
}
// 计划是否可选
// 计划是否可选和编辑和删除按钮禁用
const selectableFn = (row) => {
return checkPlanExpire(row)
}
// 计划是否已经过期,不可以操作
// 计划是否已经过期,不可以操作(返回灰色行样式)
const tableRowTimeOutClassName = ({ row }) => {
const isExpire = checkPlanExpire(row)
if (!isExpire) {
......@@ -773,7 +776,7 @@ const editPlanEmpRules = ref({
trigger: 'change'
}]
})
// 点击修改归属人按钮
const handleEditEmp = () => {
editPlanEmpVisible.value = true
nextTick(() => {
......@@ -783,7 +786,6 @@ const handleEditEmp = () => {
}
// 确定批量修改计划人
const handleEditPlanEmp = async () => {
const res = await batchUpdatePlanAPI({
employeeId: editPlanEmpForm.value.employeeId,
operName: store.state.value.user.userInfo.nickName,
......@@ -800,11 +802,11 @@ const uploadFile = async (file) => {
// 拼接当前月数为文件夹名
const date = new Date()
const month = date.getMonth() + 1
const excelUrl = await uploadFileToOSSAPI(`planExcel/${date.getFullYear()}-${month}/${store.state.value.user.userInfo.userName}/${uuidv4()}.xlsx`, file.file)
const targetAPI = store.state.value.user.userInfo.privilegeId === 1 ? addPlanAPI : addPlanByRoleAPI
const excelUrl = await uploadFileToOSSAPI(`planExcel/${date.getFullYear()}-${month}/${userStore().getEmployeeNo}/${uuidv4()}.xlsx`, file.file)
const targetAPI = isCityManager.value ? addPlanAPI : addPlanByRoleAPI
const res = await targetAPI({
"excelUrl": excelUrl,
"employeeNo": store.state.value.user.userInfo.userName
"employeeNo": userStore().getEmployeeNo
})
planTableList.value = res.data.table
confirmExcelUUID.value = res.data.uuid
......@@ -823,12 +825,6 @@ const confirmTableColumns = [
prop: 'errorMsg',
width: 450
},
{
label: '活动 ID',
prop: 'id',
width: 90,
// fixed: true
},
{
label: '归属人',
prop: 'employeeName',
......@@ -840,40 +836,15 @@ const confirmTableColumns = [
prop: 'employeeNo',
width: 140
},
{
label: '经销商 ID',
prop: 'dealerId',
width: 120
},
{
label: '经销商',
prop: 'dealerName',
width: 220
},
{
label: '系统名称',
prop: 'lineName',
width: 100
},
{
label: '店铺编码',
prop: 'storeCode',
width: 160
},
{
label: '店铺名称',
prop: 'storeName',
width: 200
},
{
label: '活动日期',
prop: 'date',
width: 180
},
{
label: '活动状态',
prop: 'planStatus',
width: 100
label: '店铺编码',
prop: 'storeCode',
width: 160
},
{
label: '活动模式',
......@@ -881,14 +852,9 @@ const confirmTableColumns = [
width: 100
},
{
label: '省份',
prop: 'province',
width: 100
},
{
label: '地址',
prop: 'addr',
width: 200
label: '活动日期',
prop: 'date',
width: 180
},
{
label: '上班时间',
......@@ -910,6 +876,42 @@ const confirmTableColumns = [
prop: 'incidentals',
width: 100
},
// {
// label: '活动 ID',
// prop: 'id',
// width: 90,
// // fixed: true
// },
{
label: '经销商 ID',
prop: 'dealerId',
width: 120
},
{
label: '经销商',
prop: 'dealerName',
width: 220
},
{
label: '系统名称',
prop: 'lineName',
width: 100
},
// {
// label: '活动状态',
// prop: 'planStatus',
// width: 100
// },
{
label: '省份',
prop: 'province',
width: 100
},
{
label: '地址',
prop: 'addr',
width: 200
},
{
label: '战区',
prop: 'orgName',
......@@ -934,10 +936,9 @@ const confirmTableColumns = [
label: '最后修改时间',
prop: 'modifyTime',
width: 250
},
}
]
const tableRowClassName = ({ row, rowIndex }) => {
const tableRowClassName = ({ row }) => {
if (row.errorMsg) {
return 'error-row'
} else {
......@@ -963,7 +964,7 @@ const confirmPlanBtn = async () => {
getPlanList()
}
// 新增/编辑计划
// 新增/编辑计划表单弹框
const addOrEditPlanVisible = ref(false)
const addOrEditPlanForm = ref({})
// 重置表单
......@@ -972,7 +973,7 @@ const resetAddOrEditPlanForm = () => {
selecteStoreInfo.value = ''
isInfoError.value = false
}
// 新增/编辑计划-表单验证(所有都是必填项
// 表单验证(所有都是必填项)
const addOrEditPlanFormRules = reactive({
storeCode: [
{
......@@ -1052,8 +1053,8 @@ const disabledDateFn = (time) => {
const handleAdd = () => {
resetAddOrEditPlanForm()
// 只有城市经理情况下,默认填充当前登录人为归属人
// if (cityManagerPrivilege.value) {
// addOrEditPlanForm.value.employeeNo = store.state.value.user.userInfo.userName
// if (isCityManager.value) {
// addOrEditPlanForm.value.employeeNo = userStore().getEmployeeNo
// }
addOrEditPlanVisible.value = true
}
......@@ -1099,22 +1100,21 @@ const disabledSeconds = (h, m, s) => {
return makeRange(0, date.getSeconds() - 1);
}
// 编辑计划
// 开始编辑某行计划
const editFn = (row) => {
addOrEditPlanForm.value = { ...row }
addOrEditPlanVisible.value = true
}
// 保存新增/编辑计划
const handleAddOrEditPlan = async () => {
// 表单校验
await addOrEditPlanRef.value.validate()
addOrEditPlanForm.value.operNo = store.state.value.user.userInfo.userName
addOrEditPlanForm.value.operNo = userStore().getEmployeeNo
addOrEditPlanForm.value.operName = store.state.value.user.userInfo.nickName
addOrEditPlanForm.value.operId = store.state.value.user.userInfo.userId
if (addOrEditPlanForm.value.id) {
// 根据归属人 employeeId 查询它的 id 和名字
const employeeInfo = managerList.value.find(item => item.employeeNo === addOrEditPlanForm.value.employeeNo)
const employeeInfo = belongPerList.value.find(item => item.employeeNo === addOrEditPlanForm.value.employeeNo)
addOrEditPlanForm.value.employeeId = employeeInfo.value
addOrEditPlanForm.value.employeeName = employeeInfo.label
await updatePlanByWebAPI(addOrEditPlanForm.value)
......@@ -1126,7 +1126,6 @@ const handleAddOrEditPlan = async () => {
addOrEditPlanVisible.value = false
getPlanList()
}
// 删除计划
const deletePlane = (row) => {
checkedRowList.value = [row]
......@@ -1141,7 +1140,7 @@ const handleDelete = async () => {
})
await deletePlanAPI({
planIds: checkedRowList.value.map(o => o.id),
employeeNo: store.state.value.user.userInfo.userName
employeeNo: userStore().getEmployeeNo
})
ElMessage.success('删除成功')
getPlanList()
......@@ -1208,10 +1207,10 @@ const uploadChangeFile = async (file) => {
// 拼接当前月数为文件夹名
const date = new Date()
const month = date.getMonth() + 1
const excelUrl = await uploadFileToOSSAPI(`planExcel/${date.getFullYear()}-${month}/${store.state.value.user.userInfo.userName}/${uuidv4()}.xlsx`, file.file)
const excelUrl = await uploadFileToOSSAPI(`planExcel/${date.getFullYear()}-${month}/${userStore().getEmployeeNo}/${uuidv4()}.xlsx`, file.file)
const res = await updatePlanAPI({
"excelUrl": excelUrl,
"employeeNo": store.state.value.user.userInfo.userName
"employeeNo": userStore().getEmployeeNo
})
planTableList.value = res.data.table
confirmExcelUUID.value = res.data.uuid
......@@ -1219,6 +1218,17 @@ const uploadChangeFile = async (file) => {
proxy.$modal.closeLoading();
return true
}
const init = async () => {
await getBelongPerList()
getPlanList() // 任务列表需要当前归属人 id,所以保证上一步网络请求完成
getProCity()
getWarZoneList()
};
init()
</script>
<style scoped
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论