提交 a1ed177c authored 作者: lidongxu's avatar lidongxu

feat(mobile/promotion/plan): 促销移动端:批量删除计划功能

同上
上级 53641a5e
...@@ -19,8 +19,8 @@ const { x, y } = useWindowScroll({ ...@@ -19,8 +19,8 @@ const { x, y } = useWindowScroll({
lang="scss"> lang="scss">
.back-to-top { .back-to-top {
position: fixed; position: fixed;
bottom: 30px; bottom: 50px;
right: 10px; right: 24px;
z-index: 999; z-index: 999;
width: 46px; width: 46px;
height: 46px; height: 46px;
......
// 长按手势指令
import { ref } from 'vue';
const longPressDuration = ref(500); // 长按时间阈值,单位毫秒
let start = null; // 记录触摸开始时间
let cancel = null;
export default {
beforeMount(el, binding) {
let pressTimer = null;
start = (e) => {
if (pressTimer === null) {
pressTimer = setTimeout(() => {
binding.value();
}, longPressDuration.value);
}
};
cancel = (e) => {
if (pressTimer !== null) {
clearTimeout(pressTimer);
pressTimer = null;
}
};
el.addEventListener('touchstart', start);
el.addEventListener('touchend', cancel);
el.addEventListener('touchcancel', cancel);
},
unmounted(el) {
el.removeEventListener('touchstart', start);
el.removeEventListener('touchend', cancel);
el.removeEventListener('touchcancel', cancel);
}
};
\ No newline at end of file
...@@ -5,6 +5,9 @@ import PickerSearch from './components/PickerSearch' ...@@ -5,6 +5,9 @@ import PickerSearch from './components/PickerSearch'
// 选择日期 // 选择日期
import PickerCalendar from './components/PickerCalendar' import PickerCalendar from './components/PickerCalendar'
// 指令
import longPress from './directive/touch'
// 只有在移动端引入 // 只有在移动端引入
if (isMobile()) { if (isMobile()) {
(function () { (function () {
...@@ -25,4 +28,5 @@ if (isMobile()) { ...@@ -25,4 +28,5 @@ if (isMobile()) {
export default function (app) { export default function (app) {
app.component('PickerSearch', PickerSearch); app.component('PickerSearch', PickerSearch);
app.component('PickerCalendar', PickerCalendar); app.component('PickerCalendar', PickerCalendar);
app.directive('longPress', longPress)
} }
<template>
<div class="mobile-container">
<div v-for="(module, moduleIndex) in modules"
:key="moduleIndex"
class="function-module">
<p class="function-module-title">{{ module.title }}</p>
<div class="function-icons">
<div v-for="(icon, iconIndex) in module.icons"
:key="iconIndex"
class="function-icon"
@click="handleIconClick(icon)">
<div class="function-icon-wrap"
:style="{ backgroundColor: icon.iconColor }">
<van-icon :name="icon.iconName" />
</div>
<p>{{ icon.name }}</p>
</div>
</div>
</div>
</div>
</template>
<script setup>
const router = useRouter();
const modules = [
{
title: '促销管理',
icons: [
{ name: '促销计划', iconName: 'shop-o', iconColor: '#5aaeec', to: '/m/promotion_plan' },
{ name: '稽核', iconName: 'manager-o', iconColor: '#feb73b', to: '/m/promotion_plan' },
]
}
]
const handleIconClick = (icon) => {
router.push(icon.to)
};
</script>
<style scoped
lang="scss">
.mobile-container {
background-color: #f3f3f3;
min-height: 100%;
font-size: 14px;
padding: 20px;
p {
margin: 0;
}
.function-module {
background-color: #fff;
/* 设置白色背景 */
border-radius: 8px;
/* 设置圆角 */
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
/* 添加阴影 */
padding: 16px;
/* 添加内边距 */
margin-bottom: 16px;
/* 设置模块间的间距 */
.function-module-title {
font-size: 16px;
/* 设置标题字体大小 */
font-weight: bold;
/* 设置标题字体加粗 */
margin-bottom: 16px;
/* 设置标题与内容的间距 */
}
.function-icons {
display: flex;
flex-wrap: wrap;
gap: 16px;
/* 设置图标间的间距 */
.function-icon {
width: 80px;
text-align: center;
.function-icon-wrap {
width: 60px;
height: 60px;
margin: 0 auto 10px;
background-color: aqua;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
.van-icon {
color: white;
font-size: 35px;
}
}
}
}
}
}
</style>
\ No newline at end of file
...@@ -363,6 +363,10 @@ const onChange = (ind) => { ...@@ -363,6 +363,10 @@ const onChange = (ind) => {
height: 135px; height: 135px;
} }
p {
display: block;
}
} }
&::-webkit-scrollbar-track { &::-webkit-scrollbar-track {
......
...@@ -162,8 +162,12 @@ ...@@ -162,8 +162,12 @@
import { getPlanStoreListAPI, getChargeListAPI, addPlanByWebAPI, getPlanDetailAPI, updatePlanByWebAPI } from '@/api' import { getPlanStoreListAPI, getChargeListAPI, addPlanByWebAPI, getPlanDetailAPI, updatePlanByWebAPI } from '@/api'
import userStore from '@/store/modules/user' import userStore from '@/store/modules/user'
import { parseTime } from '@/utils' import { parseTime } from '@/utils'
const myForm = ref({}) const myForm = ref({})
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const employeeNo = computed(() => userStore().employeeNo)
const employeeName = computed(() => userStore().employeeName)
const employeeInfo = computed(() => userStore().employeeInfo)
const isCityManager = ref(userStore().promotionIdentity) const isCityManager = ref(userStore().promotionIdentity)
const form = reactive({}) const form = reactive({})
const router = useRouter(); const router = useRouter();
...@@ -208,10 +212,10 @@ const validatorIncidentals = (value, obj) => { ...@@ -208,10 +212,10 @@ const validatorIncidentals = (value, obj) => {
} }
} }
const onSubmit = async () => { const onSubmit = async () => {
const data = userStore().employeeInfo for (let key in employeeInfo.value) {
for (const key in data) { form[key] = employeeInfo.value[key]
form[key] = data[key]
} }
if (planId) { if (planId) {
const res = await updatePlanByWebAPI(form) const res = await updatePlanByWebAPI(form)
proxy.$modal.msgSuccess(res.msg) proxy.$modal.msgSuccess(res.msg)
...@@ -219,6 +223,7 @@ const onSubmit = async () => { ...@@ -219,6 +223,7 @@ const onSubmit = async () => {
const res = await addPlanByWebAPI(form) const res = await addPlanByWebAPI(form)
proxy.$modal.msgSuccess(res.msg) proxy.$modal.msgSuccess(res.msg)
} }
clickBack() clickBack()
} }
...@@ -278,7 +283,8 @@ const getBelongList = async () => { ...@@ -278,7 +283,8 @@ const getBelongList = async () => {
const res = await getChargeListAPI() const res = await getChargeListAPI()
allBelongList.value = res.data.map(item => ({ allBelongList.value = res.data.map(item => ({
text: item.name, text: item.name,
value: item.employeeNo value: item.employeeNo,
id: item.id
})) }))
columns.value = allBelongList.value columns.value = allBelongList.value
// 判断如果是城市经理,则设置默认归属人为自己 // 判断如果是城市经理,则设置默认归属人为自己
...@@ -370,6 +376,7 @@ const confirm = (value) => { ...@@ -370,6 +376,7 @@ const confirm = (value) => {
const { selectedOptions } = value const { selectedOptions } = value
form.employeeName = selectedOptions[0]?.text form.employeeName = selectedOptions[0]?.text
form.employeeNo = selectedOptions[0]?.value form.employeeNo = selectedOptions[0]?.value
form.employeeId = selectedOptions[0]?.id
} }
showPicker.value = false showPicker.value = false
} }
......
<template> <template>
<div class="mobile-container"> <div class="mobile-container">
<van-nav-bar right-text="搜索" <van-nav-bar right-text="搜索"
left-text="新增计划" left-arrow
@click-left="$router.push('/m/promotion_plan_editing')" @click-left="$router.back()"
@click-right="showSearch = true" @click-right="showSearch = true"
placeholder placeholder
fixed /> fixed />
...@@ -18,9 +18,13 @@ ...@@ -18,9 +18,13 @@
@load="onLoad"> @load="onLoad">
<van-cell-group inset> <van-cell-group inset>
<van-swipe-cell v-for="item in planList" <van-swipe-cell v-for="item in planList"
:key="item.id"> :key="item.id"
v-long-press="onLongPress">
<van-checkbox v-show="showSelect"
v-model="item.checked"
shape="square" />
<van-cell :title="item.storeName" <van-cell :title="item.storeName"
:to="`/m/promotion_plan_detail/${item.id}`"> @click="clickDetail(item)">
<template #label> <template #label>
<p class="employee">{{ item.employeeName }}</p> <p class="employee">{{ item.employeeName }}</p>
<p :class="{ 'plan-go': item.planStatus === 1 }"> <p :class="{ 'plan-go': item.planStatus === 1 }">
...@@ -32,7 +36,8 @@ ...@@ -32,7 +36,8 @@
<p>{{ parseTime(item.date, '{y}-{m}-{d} (周{a})') }}</p> <p>{{ parseTime(item.date, '{y}-{m}-{d} (周{a})') }}</p>
</template> </template>
</van-cell> </van-cell>
<template #right> <template #right
v-if="!showSelect">
<van-button square <van-button square
type="success" type="success"
text="编辑" text="编辑"
...@@ -46,13 +51,24 @@ ...@@ -46,13 +51,24 @@
</van-cell-group> </van-cell-group>
</van-list> </van-list>
</van-pull-refresh> </van-pull-refresh>
<!-- 搜索组件 --> <!-- 搜索组件 -->
<PlanSearch v-model:show="showSearch" <PlanSearch v-model:show="showSearch"
v-model:query="query" v-model:query="query"
:planColumns="planColumns" :planColumns="planColumns"
:allEmpolyeeList="allEmpolyeeList" :allEmpolyeeList="allEmpolyeeList"
@query="querySearch" /> @query="querySearch" />
<!-- 新增组件(浮动气泡) -->
<van-floating-bubble icon="plus"
@click="$router.push('/m/promotion_plan_editing')" />
<!-- 底部-长按操作栏 -->
<van-action-bar v-show="showSelect">
<span @click="showSelect = false">取消</span>
<van-action-bar-button type="warning"
text="修改归属人" />
<van-action-bar-button type="danger"
text="删除"
@click="clickDelSome" />
</van-action-bar>
</div> </div>
</template> </template>
...@@ -150,15 +166,19 @@ const onRefresh = () => { ...@@ -150,15 +166,19 @@ const onRefresh = () => {
}, 300) }, 300)
} }
const clickDetail = (row) => {
if (showSelect.value) return // 当前处于长按状态,点击详情不做任何操作
router.push(`/m/promotion_plan_detail/${row.id}`)
}
// 搜索表单 // 搜索表单
const querySearch = () => { const querySearch = () => {
query.pageNum = 1 onRefresh()
planList.value = []
getPlanList()
} }
// 编辑计划 // 编辑计划
const editPlan = (row) => { const editPlan = (row) => {
console.log(123)
if (!checkPlanExpire(row)) { if (!checkPlanExpire(row)) {
return proxy.$modal.msgWarning('无法编辑,已执行或之前计划') return proxy.$modal.msgWarning('无法编辑,已执行或之前计划')
} }
...@@ -176,9 +196,8 @@ const deletePlan = (row) => { ...@@ -176,9 +196,8 @@ const deletePlan = (row) => {
employeeNo: employeeNo.value employeeNo: employeeNo.value
}) })
proxy.$modal.msgSuccess('删除成功') proxy.$modal.msgSuccess('删除成功')
// 找到 row 在数组里第几条删除 // 重新获取列表
const index = planList.value.findIndex(item => item.id === row.id) onRefresh()
planList.value.splice(index, 1)
}) })
} }
...@@ -187,6 +206,40 @@ const init = async () => { ...@@ -187,6 +206,40 @@ const init = async () => {
getPlanList() getPlanList()
} }
init() init()
onActivated(() => {
querySearch()
})
// 长按出现全选功能
const showSelect = ref(false)
const onLongPress = () => {
showSelect.value = true
}
// 删除全选的计划
const clickDelSome = () => {
const ids = planList.value.filter(item => item.checked).map(item => item.id)
if (ids.length === 0) {
return proxy.$modal.msgWarning('请选择要删除的计划')
}
proxy.$modal.confirm(`确认删除${ids.length}条计划吗?`).then(async () => {
// 循环判断计划是否含有以前和执行中的
for (let i = 0; i < ids.length; i++) {
const item = planList.value.find(o => o.id === ids[i])
if (!checkPlanExpire(item)) {
return proxy.$modal.msgWarning('无法删除,已执行或之前计划')
}
}
await deletePlanAPI({
planIds: ids,
employeeNo: employeeNo.value
})
proxy.$modal.msgSuccess('删除成功')
showSelect.value = false
onRefresh()
})
}
</script> </script>
<style scoped <style scoped
...@@ -201,33 +254,60 @@ init() ...@@ -201,33 +254,60 @@ init()
.van-cell-group { .van-cell-group {
background: #f5f5f5; background: #f5f5f5;
.van-cell { .van-swipe-cell {
margin-top: 10px; /* 阻止长按选文字效果 */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
.van-cell__label { /* Standard syntax */
font-size: 14px !important; ::v-deep(.van-swipe-cell__wrapper) {
} display: flex;
margin-top: 10px;
.employee { .van-checkbox {
margin-bottom: 5px !important; padding-right: 10px;
} }
.plan-go { .van-cell {
color: #39bb74;
}
p { .van-cell__label {
margin: 0; font-size: 14px !important;
} }
}
.employee {
margin-bottom: 5px !important;
}
.van-swipe-cell__right { .plan-go {
display: flex; color: #39bb74;
}
button { p {
height: 100%; margin: 0;
}
}
.van-swipe-cell__right {
display: flex;
button {
height: 100%;
}
}
} }
} }
}
}
/* 底部菜单 */
.van-action-bar {
span {
font-size: 14px;
padding: 0 10px;
} }
} }
} }
......
...@@ -95,10 +95,16 @@ export const constantMobileRoutes = [ ...@@ -95,10 +95,16 @@ export const constantMobileRoutes = [
}, },
{ {
path: '/m', path: '/m',
redirect: '/m/promotion_plan', redirect: '/m/menu',
component: () => import('@/mobile/index'), component: () => import('@/mobile/index'),
hidden: true, hidden: true,
children: [ children: [
// 菜单页
{
path: 'menu',
component: () => import('@/mobile/views/menu'),
name:'m_menu',
},
// 促销计划 // 促销计划
{ {
path: 'promotion_plan', // 列表 path: 'promotion_plan', // 列表
......
...@@ -98,7 +98,7 @@ export default defineStore( ...@@ -98,7 +98,7 @@ export default defineStore(
promotionIdentity(state) { promotionIdentity(state) {
return getPromotionRole(state.userInfo.privilegeId) === CITY_MANAGER return getPromotionRole(state.userInfo.privilegeId) === CITY_MANAGER
}, },
// 获取员工工号,姓名,id // 操作人员工工号,姓名,id
employeeInfo(state) { employeeInfo(state) {
return { return {
operNo: state.userInfo.userName, operNo: state.userInfo.userName,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论