用户删除策略,有营销数据时不许删除用户

用户-岗位1v1加校验
营销数据增加录入日期字段,列表超长会出现格式问题,金额格式化,删掉导入导出,搜索框增加姓名
This commit is contained in:
SGK\17962 2025-09-01 17:36:53 +08:00
parent 0bee6780ea
commit 66ea08e711
13 changed files with 136 additions and 56 deletions

View File

@ -47,8 +47,6 @@ declare module "@elegant-router/types" {
"original": "/original";
"original_batch-account-info": "/original/batch-account-info";
"original_batch-bank-card-info": "/original/batch-bank-card-info";
"original_batch-account-info": "/original/batch-account-info";
"original_batch-bank-card-info": "/original/batch-bank-card-info";
"original_dianfei": "/original/dianfei";
"original_e-m-banking": "/original/e-m-banking";
"original_gjj-payment": "/original/gjj-payment";
@ -218,9 +216,6 @@ declare module "@elegant-router/types" {
| "system_client"
| "system_config"
| "system_dept-transfer"
| "report"
| "original_batch-account-info"
| "original_batch-bank-card-info"
| "system_dept"
| "system_dict"
| "system_menu"
@ -308,7 +303,7 @@ declare module "@elegant-router/types" {
component: `view.${K}`;
}
: never;
/**
* the center level route
*/
@ -331,7 +326,7 @@ declare module "@elegant-router/types" {
children: (CenterLevelRoute<GetChildRouteKey<K>> | LastLevelRoute<GetChildRouteKey<K>>)[];
}
: never;
/**
* the custom first level route
*/

View File

@ -237,7 +237,7 @@ const {
);
}
// magneticCardIdmagneticCardListmagneticCardId
return row.magneticCardId || '';
return '';
}
},
{
@ -293,7 +293,7 @@ const {
);
}
// trafficIdtrafficListtrafficId
return row.trafficId || '';
return '';
}
},
{
@ -484,9 +484,9 @@ function edit(dataId: CommonType.IdType) {
handleEdit('dataId', dataId);
}
function handleImport() {
openImportModal();
}
// function handleImport() {
// openImportModal();
// }
function handleExport() {
download('/mps/market/export', searchParams, `营销数据管理_${new Date().getTime()}.xlsx`);
@ -525,20 +525,20 @@ async function getSubcategoryOptions() {
:loading="loading"
:show-add="hasAuth('mps:market:add')"
:show-delete="hasAuth('mps:market:remove')"
:show-export="hasAuth('mps:market:export')"
:show-export="false"
@add="handleAdd"
@delete="handleBatchDelete"
@export="handleExport"
@refresh="getData"
>
<template #after>
<NButton v-if="hasAuth('mps:market:export')" size="small" ghost @click="handleImport">
<template #icon>
<SvgIcon local-icon="upload-rounded" class="text-icon"/>
</template>
{{ $t('common.import') }}
</NButton>
</template>
<!-- <template #after>-->
<!-- <NButton v-if="hasAuth('mps:market:export')" size="small" ghost @click="handleImport">-->
<!-- <template #icon>-->
<!-- <SvgIcon local-icon="upload-rounded" class="text-icon"/>-->
<!-- </template>-->
<!-- {{ $t('common.import') }}-->
<!-- </NButton>-->
<!-- </template>-->
</TableHeaderOperation>
</template>

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { computed,defineComponent, onMounted, reactive, ref, watch } from 'vue';
import { fetchCreateMarket, fetchUpdateMarket } from '@/service/api/mps/market';
import { fetchGetMuUserSelect } from '@/service/api/system';
import { useAuthStore } from '@/store/modules/auth';
@ -8,10 +8,13 @@ import { useDict } from '@/hooks/business/dict';
import { $t } from '@/locales';
import { useLoading } from '~/packages/hooks';
defineOptions({
name: 'MarketOperateDrawer'
});
interface Props {
/** the type of operation */
operateType: NaiveUI.TableOperateType;
@ -136,6 +139,13 @@ const acquiringIdPatternRule = {
trigger: 'change'
};
//
const onlyAllowCharNumber= (value: string) => !value || /^[a-zA-Z0-9]+$/.test(value);
//
const onlyAllowNumber= (value: string) => !value || /^\d+$/.test(value);
const noSideSpace= (value: string) => !value.startsWith(' ') && !value.endsWith(' ');
// const custTypeRule = computed(() => {
// // ""
// if (model.subcategoryName !== '') {
@ -754,19 +764,19 @@ watch(
<tbody>
<tr v-for="(item, index) in model.magneticCardList" :key="index">
<td>
<NInputNumber
<NInput
v-model:value="item.oldCardNo"
placeholder="请输入老卡号"
:show-button="false"
:controls="false" style="width: 100%"
:allow-input = "onlyAllowNumber"
style="width: 100%"
/>
</td>
<td>
<NInputNumber
<NInput
v-model:value="item.newCardNo"
placeholder="请输入新卡号"
:show-button="false"
:controls="false" style="width: 100%"
:allow-input = "onlyAllowNumber"
style="width: 100%"
/>
</td>
<td>
@ -782,7 +792,7 @@ watch(
</NTable>
</NFormItem>
<NFormItem v-if="isdisplayacquiringName" label="综合收单商户名" path="acquiringName">
<NInput v-model:value="model.acquiringName" placeholder="请输入综合收单商户名" />
<NInput v-model:value="model.acquiringName" :allow-input="noSideSpace" placeholder="请输入综合收单商户名" />
</NFormItem>
<NFormItem v-if="isdisplayacquiringId" label="综合收单商户号" path="acquiringId">
<NInput v-model:value="model.acquiringId" placeholder="请输入综合收单商户号" />
@ -812,16 +822,26 @@ watch(
<tbody>
<tr v-for="(item, index) in model.trafficList || []" :key="index">
<td>
<NInputNumber
<NInput
v-model:value="item.trafficNo"
placeholder="请输入决定书编号"
:show-button="false"
:controls="false"
:allow-input = "onlyAllowCharNumber"
style="width: 100%"
/>
</td>
<td>
<NInputNumber v-model:value="item.trafficAmt" placeholder="请输入处罚金额" :min="0" style="width: 100%" />
<NInputNumber
v-model:value="item.trafficAmt"
placeholder="请输入处罚金额"
:min="0"
:precision="2"
:show-button="false"
style="width: 100%"
>
<template #suffix>
</template>
</NInputNumber>
</td>
<td>
<NButton text type="error" @click="removeTrafficItem(index)">删除</NButton>
@ -836,10 +856,10 @@ watch(
</NTable>
</NFormItem>
<NFormItem v-if="isdisplayworkplace" label="职工所属单位" path="workplace">
<NInput v-model:value="model.workplace" placeholder="请输入职工所属单位" />
<NInput v-model:value="model.workplace" :allow-input="noSideSpace" placeholder="请输入职工所属单位" />
</NFormItem>
<NFormItem v-if="isdisplaysurplusAccountName" label="公积金缴纳账户名称" path="surplusAccountName">
<NInput v-model:value="model.surplusAccountName" placeholder="请输入公积金缴纳账户名称" />
<NInput v-model:value="model.surplusAccountName" :allow-input="noSideSpace" placeholder="请输入公积金缴纳账户名称" />
</NFormItem>
<NFormItem v-if="isdisplayheatingNo" label="户号" path="heatingNo">
<NInput v-model:value="model.heatingNo" placeholder="请输入户号" />

View File

@ -17,6 +17,9 @@ const props = withDefaults(defineProps<Props>(), {
subcategoryIdOptions: () => []
});
const { options: mps_cust_type } = useDict('mps_cust_type');
interface Emits {
(e: 'reset'): void;
(e: 'search'): void;
@ -49,7 +52,7 @@ async function search() {
<NCollapseItem :title="$t('common.search')" name="user-search">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="screen" item-responsive>
<NFormItemGi span="24 s:12 m:8" label="业务类型" path="subcategoryName" class="pr-24px">
<NFormItemGi span="24" label="业务类型" path="subcategoryName" class="pr-24px">
<NSelect
v-model:value="model.subcategoryId"
filterable
@ -83,20 +86,20 @@ async function search() {
<!-- <NFormItemGi span="24 s:12 m:6" label="部门id" path="deptId" class="pr-24px">-->
<!-- <NInput v-model:value="model.deptId" placeholder="请输入部门id" />-->
<!-- </NFormItemGi>-->
<!-- <NFormItemGi span="24 s:12 m:6" label="客户类型1-个人2-对公)" path="custType" class="pr-24px">-->
<!-- <NSelect-->
<!-- v-model:value="model.custType"-->
<!-- placeholder="请选择客户类型1-个人2-对公)"-->
<!-- :options="[]"-->
<!-- clearable-->
<!-- />-->
<!-- </NFormItemGi>-->
<NFormItemGi span="24 s:12 m:6" label="客户类型" path="custType" class="pr-24px">
<NSelect
v-model:value="model.custType"
placeholder="请选择客户类型1-个人2-对公)"
:options="mps_cust_type"
clearable
/>
</NFormItemGi>
<!-- <NFormItemGi span="24 s:12 m:6" label="客户身份证号" path="custId" class="pr-24px">-->
<!-- <NInput v-model:value="model.custId" placeholder="请输入客户身份证号" />-->
<!-- </NFormItemGi>-->
<!-- <NFormItemGi span="24 s:12 m:6" label="客户姓名" path="custName" class="pr-24px">-->
<!-- <NInput v-model:value="model.custName" placeholder="请输入客户姓名" />-->
<!-- </NFormItemGi>-->
<NFormItemGi span="24 s:12 m:6" label="客户姓名" path="custName" class="pr-24px">
<NInput v-model:value="model.custName" placeholder="请输入客户姓名" />
</NFormItemGi>
<!-- <NFormItemGi span="24 s:12 m:6" label="客户账号/卡号" path="custAcctNo" class="pr-24px">-->
<!-- <NInput v-model:value="model.custAcctNo" placeholder="请输入客户账号/卡号" />-->
<!-- </NFormItemGi>-->
@ -127,7 +130,7 @@ async function search() {
<!-- <NFormItemGi span="24 s:12 m:6" label="取暖费户号" path="heatingNo" class="pr-24px">-->
<!-- <NInput v-model:value="model.heatingNo" placeholder="请输入取暖费户号" />-->
<!-- </NFormItemGi>-->
<NFormItemGi span="24 s:12 m:8" label="核对标志" path="checkFlag" class="pr-24px">
<NFormItemGi span="24 s:12 m:6" label="核对标志" path="checkFlag" class="pr-24px">
<NSelect v-model:value="model.checkFlag" :options="mpsCheckStatusOptions" placeholder="请选择核对状态" />
</NFormItemGi>
<!-- <NFormItemGi span="24 s:12 m:6" label="核对时间" path="checkTime" class="pr-24px">-->

View File

@ -2,6 +2,7 @@
<script setup lang="ts">
import { h, ref, watch } from 'vue';
import type { UploadFileInfo } from 'naive-ui';
import dayjs from "dayjs";
import { getToken } from '@/store/modules/auth/shared';
import { useDownload } from '@/hooks/business/download';
import { getServiceBaseURL } from '@/utils/service';
@ -36,7 +37,8 @@
});
const data = ref<Record<string, any>>({
updateSupport: false
updateSupport: false,
importMonth: dayjs().subtract(1, 'month').startOf('month').valueOf()
});
const fileList = ref<UploadFileInfo[]>([]);
@ -98,6 +100,16 @@
message.value = '';
}
} );
function disablePreviousDate(ts: number) {
//
const currentMonthStart = new Date(new Date().getFullYear(), new Date().getMonth(), 1).getTime()
const prevMonthStart = new Date(new Date().getFullYear(), new Date().getMonth() - 1, 1).getTime()
return ts !== currentMonthStart && ts !== prevMonthStart
// const prevMonthStart = dayjs().subtract(1, 'month').startOf('month')
// // 1
// return ts < prevMonthStart.valueOf()
}
</script>
]]]
@ -143,7 +155,15 @@
</NUploadDragger>
</NUpload>
<div class="flex-center">
<NCheckbox v-model="data.updateSupport">{{ $t('common.updateExisting') }}</NCheckbox>
<!-- <NCheckbox v-model="data.updateSupport">{{ $t('common.updateExisting') }}</NCheckbox>-->
<!-- <n-divider vertical />-->
<NDatePicker
v-model:value="data.importMonth"
type="month"
:placeholder="$t('common.selectImportMonth')"
:is-date-disabled="disablePreviousDate"
disabled
/>
</div>
<NAlert v-if="message" :title="$t('common.importResult')" :type="success ? 'success' : 'error'" :bordered="false">
<template #default>
@ -152,7 +172,7 @@
</NAlert>
<template #footer>
<NSpace justify="end" :size="16">
<NButton @click="handleDownloadTemplate">{{ $t('common.downloadTemplate') }}</NButton>
<!-- <NButton @click="handleDownloadTemplate">{{ $t('common.downloadTemplate') }}</NButton>-->
<NButton type="primary" @click="handleSubmit">{{ $t('common.import') }}</NButton>
</NSpace>
</template>

View File

@ -168,7 +168,7 @@ public class BusinessSubcategoryServiceImpl implements IBusinessSubcategoryServi
return baseMapper.selectSubcategoryList(new LambdaQueryWrapper<BusinessSubcategory>()
//.select(SysUser::getUserId, SysUser::getMktNo, SysUser::getNickName)
.select(BusinessSubcategory::getId, BusinessSubcategory::getName)
.ne( BusinessSubcategory::getTypeId, "BIZ006")//BIZ006 新增综合收单商户留存率提升当季不录入
// .ne( BusinessSubcategory::getTypeId, "BIZ006")//BIZ006 新增综合收单商户留存率提升当季不录入
.eq(BusinessSubcategory::getStatus, "0"));
}

View File

@ -180,6 +180,11 @@ public class MpsMarket extends TenantEntity {
*/
private String checkMsg;
/**
* 创建时间
*/
private String entryDate;
/**
* 删除标志0代表存在 1代表删除
*/

View File

@ -3,6 +3,7 @@ package org.dromara.mps.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.idev.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
@ -178,6 +179,7 @@ public class MpsMarketServiceImpl implements IMpsMarketService {
// }
// MpsMarket add = mpsMarketConverter.convert(bo);
MpsMarket add = MapstructUtils.convert(bo, MpsMarket.class);
add.setEntryDate(DateUtils.format(new Date(), "yyyy_MM_dd"));
validEntityBeforeAdd(add);
System.out.println("add:--->"+add);
boolean flag = baseMapper.insert(add) > 0;

View File

@ -1,5 +1,6 @@
package org.dromara.original.controller;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
@ -7,6 +8,9 @@ import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.enums.FormatsType;
import org.dromara.common.core.utils.DateUtils;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.dromara.common.excel.core.ExcelResult;
@ -79,8 +83,11 @@ public class OriginalBatchAccountInfoController extends BaseController {
@Log(title = "批量账户信息查询(对公)", businessType = BusinessType.IMPORT)
@SaCheckPermission("original:batchAccountInfo:import")
@PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
ExcelResult<OriginalBatchAccountInfoImportVo> result = ExcelUtil.importExcel(file.getInputStream(), OriginalBatchAccountInfoImportVo.class, new OriginalBatchAccountInfoImportListener(updateSupport));
public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM") Date importMonth) throws Exception {
String importTime = DateUtils.parseDateToStr(FormatsType.YYYY_MM,importMonth);
originalBatchAccountInfoService.deleteDataByMonth(importTime);
ExcelResult<OriginalBatchAccountInfoImportVo> result = ExcelUtil.importExcel(file.getInputStream(), OriginalBatchAccountInfoImportVo.class, new OriginalBatchAccountInfoImportListener(updateSupport,importTime));
return R.ok(result.getAnalysis());
}

View File

@ -38,6 +38,7 @@ public class OriginalBatchAccountInfoImportListener extends AnalysisEventListene
private final Boolean isUpdateSupport;
private final Long operUserId;
private int countN = 1;
private final String importTime;
// 存储所有解析成功的对象
private final Collection<OriginalBatchAccountInfo> successList = new ArrayList<>();
@ -47,10 +48,11 @@ public class OriginalBatchAccountInfoImportListener extends AnalysisEventListene
//private final Collection<Pair<OriginalBatchAccountInfoImportVo, String>> failureList = new ArrayList<>();
private final Collection<Pair<Integer, String>> failureList = new ArrayList<>();
public OriginalBatchAccountInfoImportListener(Boolean isUpdateSupport) {
public OriginalBatchAccountInfoImportListener(Boolean isUpdateSupport, String importTime) {
this.originalBatchAccountInfoService = SpringUtils.getBean(IOriginalBatchAccountInfoService.class);
this.isUpdateSupport = isUpdateSupport;
this.operUserId = LoginHelper.getUserId();
this.importTime = importTime;
}
@Override
@ -66,7 +68,7 @@ public class OriginalBatchAccountInfoImportListener extends AnalysisEventListene
// 2. 转换为业务对象
OriginalBatchAccountInfo originalBatchAccountInfo = BeanUtil.toBean(originalBatchAccountInfoImportVo, OriginalBatchAccountInfo.class);
originalBatchAccountInfo.setImportTime(importTime);
// 3. 添加到成功列表稍后批量处理
successList.add(originalBatchAccountInfo);

View File

@ -72,4 +72,6 @@ public interface IOriginalBatchAccountInfoService {
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
Boolean deleteDataByMonth(String importTime);
}

View File

@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.original.domain.OriginalTraffic;
import org.springframework.stereotype.Service;
import org.dromara.original.domain.bo.OriginalBatchAccountInfoBo;
import org.dromara.original.domain.vo.OriginalBatchAccountInfoVo;
@ -194,4 +195,9 @@ public class OriginalBatchAccountInfoServiceImpl implements IOriginalBatchAccoun
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public Boolean deleteDataByMonth(String importTime) {
return baseMapper.delete(new LambdaQueryWrapper<OriginalBatchAccountInfo>().eq(OriginalBatchAccountInfo::getImportTime, importTime))>0;
}
}

View File

@ -23,6 +23,8 @@ import org.dromara.common.core.utils.*;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mps.domain.MpsMarket;
import org.dromara.mps.mapper.MpsMarketMapper;
import org.dromara.system.domain.*;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysPostVo;
@ -55,6 +57,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
private final SysPostMapper postMapper;
private final SysUserRoleMapper userRoleMapper;
private final SysUserPostMapper userPostMapper;
private final MpsMarketMapper mpsMarketMapper;
@Override
public TableDataInfo<SysUserVo> selectPageUserList(SysUserBo user, PageQuery pageQuery) {
@ -513,6 +516,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
*/
private void insertUserPost(SysUserBo user, boolean clear) {
Long[] posts = user.getPostIds();
if (posts.length >1) {
throw new ServiceException("用户" + user.getUserName() + "不能添加多个岗位");
}
if (ArrayUtil.isNotEmpty(posts)) {
if (clear) {
// 删除用户与岗位关联
@ -599,6 +605,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteUserById(Long userId) {
SysUserVo user = selectUserById(userId);
//校验是否有营销数据若yxid或jbid等于user.getMktNo()则提示用户有营销数据请先删除营销数据
if (mpsMarketMapper.selectCount(new LambdaQueryWrapper<MpsMarket>().eq(MpsMarket::getYxId, user.getMktNo())) > 0 ||
mpsMarketMapper.selectCount(new LambdaQueryWrapper<MpsMarket>().eq(MpsMarket::getJbId, user.getMktNo())) > 0) {
throw new ServiceException("用户有营销数据,请先删除营销数据");
};
// 删除用户与角色关联
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
// 删除用户与岗位表
@ -623,6 +635,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
for (Long userId : userIds) {
checkUserAllowed(userId);
checkUserDataScope(userId);
SysUserVo user = selectUserById(userId);
//校验是否有营销数据若yxid或jbid等于user.getMktNo()则提示用户有营销数据请先删除营销数据
if (mpsMarketMapper.selectCount(new LambdaQueryWrapper<MpsMarket>().eq(MpsMarket::getYxId, user.getMktNo())) > 0 ||
mpsMarketMapper.selectCount(new LambdaQueryWrapper<MpsMarket>().eq(MpsMarket::getJbId, user.getMktNo())) > 0) {
throw new ServiceException("用户有营销数据,请先删除营销数据");
};
}
List<Long> ids = List.of(userIds);
// 删除用户与角色关联