This commit is contained in:
oneao committed 2025-12-19 17:31:43 +08:00
1 parent 1fea531918
commit 898d209594
11 files changed
+295 -78

No files matched your search

@@ -5,13 +5,14 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeleteCompanyUserDTO {
@NotNull(message = "公司成员不能为空")
private Long id;
private List<Long> ids;
@NotNull(message = "公司不能为空")
private Long companyId;
@@ -18,7 +18,6 @@ public class UpdateCompanyUserDTO {
@NotBlank(message = "邮箱不能为空")
private String email;
@NotBlank(message = "密码不能为空")
private String password;
private String position;
@@ -12,6 +12,7 @@ import cn.link56.company.model.dto.UpdateCompanyUserDTO;
import cn.link56.company.model.po.CompanyUserPO;
import cn.link56.company.model.vo.QueryCompanyUserVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
@@ -205,46 +206,69 @@ public class CompanyUserService extends ServiceImpl<CompanyUserMapper, CompanyUs
public void updateCompanyUser(UpdateCompanyUserDTO companyUserDTO) {
Long id = companyUserDTO.getId();
Long companyId = companyUserDTO.getCompanyId();
String email = companyUserDTO.getEmail();
String phone = companyUserDTO.getPhone();
String password = companyUserDTO.getPassword();
boolean hasPermission = hasPermission(companyId, UserContext.getUserId());
if (!hasPermission){
if (!hasPermission) {
throw new BusinessException("您没有权限访问该公司的信息,操作被拒绝");
}
CompanyUserPO companyUserPO = companyUserMapper.selectById(id);
if (ObjectUtils.isEmpty(companyUserPO)){
String oldPassword = companyUserPO.getPassword();
if (ObjectUtils.isEmpty(companyUserPO)) {
throw new BusinessException("更新失败,该用户不存在");
}
// 检查邮箱
if (!StringUtils.equals(email, companyUserPO.getEmail())
&& isEmailExists(email)) {
// 检查邮箱是否发生变化
boolean isEmailChanged = !StringUtils.equals(email, companyUserPO.getEmail());
if (isEmailChanged && isEmailExists(email)) {
throw new BusinessException("邮箱已被注册");
}
// 检查手机号
if (!StringUtils.equals(phone, companyUserPO.getPhone())
&& isPhoneExists(phone)) {
// 检查手机号是否发生变化
if (!StringUtils.equals(phone, companyUserPO.getPhone()) && isPhoneExists(phone)) {
throw new BusinessException("手机号已被注册");
}
BeanUtils.copyProperties(companyUserDTO,companyUserPO);
if (StringUtils.isNotBlank(password)) {
companyUserPO.setPassword(password);
}
BeanUtils.copyProperties(companyUserDTO, companyUserPO);
if(StringUtils.isNotBlank(password)){
companyUserPO.setPassword(password);
}else{
companyUserPO.setPassword(oldPassword);
}
// 更新用户信息
companyUserMapper.updateById(companyUserPO);
}
public void deleteCompanyUser(DeleteCompanyUserDTO deleteCompanyUserDTO) {
Long id = deleteCompanyUserDTO.getId();
List<Long> ids = deleteCompanyUserDTO.getIds();
Long companyId = deleteCompanyUserDTO.getCompanyId();
// 检查用户是否有权限删除该公司用户
boolean hasPermission = hasPermission(companyId, UserContext.getUserId());
if (!hasPermission){
if (!hasPermission) {
throw new BusinessException("您没有权限访问该公司的信息,操作被拒绝");
}
companyUserMapper.deleteById(id);
LambdaUpdateWrapper<CompanyUserPO> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(CompanyUserPO::getId, ids)
.eq(CompanyUserPO::getCompanyId, companyId)
.ne(CompanyUserPO::getRole, 0);
// 执行删除操作
companyUserMapper.delete(updateWrapper);
}
}
@@ -1,9 +1,15 @@
import type { AddCompanyUserParams, CompanyUser, QueryCompanyUserParams } from '@/types/company/user'
import type { AddCompanyUserParams, CompanyUser, DeleteCompanyUserParams, QueryCompanyUserParams, UpdateCompanyUserParams } from '@/types/company/user'
import { httpGet, httpPostJson } from '@/request/utils'
export function queryCompanyUserApi(params: QueryCompanyUserParams) {
return httpPostJson<BasePageResult<CompanyUser>>('/company/user/query', params)
}
export function addCompanyUserApi(params: AddCompanyUserParams) {
return httpPostJson<BasePageResult<void>>('/company/user/add', params)
return httpPostJson<void>('/company/user/add', params)
}
export function updateCompanyUserApi(params: UpdateCompanyUserParams) {
return httpPostJson<void>('/company/user/update', params)
}
export function deleteCompanyUserApi(params: DeleteCompanyUserParams) {
return httpPostJson<void>('/company/user/delete', params)
}
@@ -34,6 +34,18 @@ const router = createRouter({
path: '/settings/info/user',
component: () => import('@/views/settings/info/user/index.vue'),
},
{
path: '/settings/forum/home',
component: () => import('@/views/settings/forum/home.vue'),
},
{
path: '/settings/forum/editor',
component: () => import('@/views/settings/forum/editor.vue'),
},
{
path: '/settings/forum/post',
component: () => import('@/views/settings/forum/post.vue'),
},
],
},
],
@@ -35,3 +35,20 @@ export interface AddCompanyUserParams {
phone: string
canuse: string
}
export interface UpdateCompanyUserParams {
id: number
companyId: number
email: string
password: string
name: string
position: string
phone: string
canuse: string
}
export interface DeleteCompanyUserParams {
companyId: number
ids: number[]
}
@@ -0,0 +1,10 @@
<script lang="ts" setup>
</script>
<template>
<div class="" />
</template>
<style lang="scss" scoped>
//
</style>
@@ -0,0 +1,10 @@
<script lang="ts" setup>
</script>
<template>
<div class="" />
</template>
<style lang="scss" scoped>
//
</style>
@@ -0,0 +1,10 @@
<script lang="ts" setup>
</script>
<template>
<div class="" />
</template>
<style lang="scss" scoped>
//
</style>
@@ -6,7 +6,7 @@ import { ElMessage } from 'element-plus'
import { computed, ref, watch } from 'vue'
import EmailCodeInput from '@/components/EmailCodeInput.vue'
import { authCodeVerifyApi } from '@/request/api/auth/code'
import { addCompanyUserApi } from '@/request/api/company/user'
import { addCompanyUserApi, updateCompanyUserApi } from '@/request/api/company/user'
import { useUserStore } from '@/store/user'
import { AuthCodeChannel, AuthCodePurpose } from '@/types/auth/code'
import { validatePhone } from '@/utils/validate'
@@ -18,6 +18,8 @@ const props = defineProps({
},
})
const emits = defineEmits(['customClose', 'dataChange'])
const userStore = useUserStore()
const roleOptions = [
{
@@ -91,8 +93,7 @@ const formRules = {
password: [
{
validator: (rule: any, value: any, callback: any) => {
// 更新时允许不填
if (isUpdate.value && !value) {
if (isUpdate.value && (value === undefined || value === null || value === '')) {
callback()
return
}
@@ -136,57 +137,65 @@ async function handleSubmit(formEl: FormInstance | undefined) {
if (!formEl)
return
await formEl.validate((valid) => {
if (valid) {
if (isEmailChanged.value) {
submitLoading.value = true
// 表单验证
const valid = await formEl.validate()
if (!valid) {
console.log('===验证失败===')
return
}
authCodeVerifyApi({
channel: AuthCodeChannel.EMAIL,
purpose: isUpdate.value ? AuthCodePurpose.UPDATE_EMAIL : AuthCodePurpose.REGISTER,
target: form.value.email,
code: form.value.emailCode,
}).then((res) => {
if (res.isSuccess) {
addCompanyUserApi({
companyId: userStore.userInfo.company.id,
email: form.value.email,
password: form.value.password,
name: form.value.name,
position: form.value.position,
phone: form.value.phone,
canuse: form.value.canuse,
}).then((res) => {
if (res.isSuccess) {
ElMessage.success('保存成功')
}
else {
ElMessage.error(res.message || '新增失败,请稍后再试')
}
}).catch((err) => {
console.log(err)
ElMessage.error('新增失败,请稍后再试')
}).finally(() => {
submitLoading.value = false
})
}
else {
submitLoading.value = false
submitLoading.value = true
ElMessage.error(res.message || '验证码无效或已过期,请重新获取')
}
}).catch((err) => {
submitLoading.value = false
try {
// 验证邮箱是否变化
if (isEmailChanged.value) {
const res = await authCodeVerifyApi({
channel: AuthCodeChannel.EMAIL,
purpose: isUpdate.value ? AuthCodePurpose.UPDATE_EMAIL : AuthCodePurpose.REGISTER,
target: form.value.email,
code: form.value.emailCode,
})
console.log(err)
ElMessage.error('邮箱验证码校验失败,请稍后再试')
})
if (!res.isSuccess) {
throw new Error(res.message || '验证码无效或已过期,请重新获取')
}
}
else {
console.log('===验证失败===')
// 提交用户数据
const userApi = isUpdate.value ? updateCompanyUserApi : addCompanyUserApi
const response = await userApi({
id: form.value.id,
companyId: userStore.userInfo.company.id,
email: form.value.email,
password: form.value.password,
name: form.value.name,
position: form.value.position,
phone: form.value.phone,
canuse: form.value.canuse,
})
if (response.isSuccess) {
ElMessage.success(isUpdate.value ? '更新成功' : '保存成功')
emits('customClose')
emits('dataChange')
}
})
else {
ElMessage.error(response.message || (isUpdate.value ? '更新失败,请稍后再试' : '新增失败,请稍后再试'))
}
}
catch (err) {
console.log(err)
if (err instanceof Error) {
ElMessage.error(err.message || '操作失败,请稍后再试')
}
else {
ElMessage.error('操作失败,请稍后再试')
}
}
finally {
submitLoading.value = false
}
}
</script>
@@ -256,9 +265,14 @@ async function handleSubmit(formEl: FormInstance | undefined) {
<el-switch v-model="form.canuse" active-value="1" inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
<div style="flex: auto">
<el-button>
<el-button
@click="() => {
emits('customClose')
}"
>
取消
</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit(formRef)">
@@ -1,15 +1,19 @@
<script lang="ts" setup>
import type { CompanyUser, QueryCompanyUserParams } from '@/types/company/user'
import { Delete, Plus, Refresh, Search } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { onMounted, reactive, ref } from 'vue'
import { queryCompanyUserApi } from '@/request/api/company/user'
import { deleteCompanyUserApi, queryCompanyUserApi } from '@/request/api/company/user'
import { useUserStore } from '@/store/user'
import EditDrawer from './components/EditDrawer.vue'
const userStore = useUserStore()
const activeCollapseNames = ref(['1'])
const loading = reactive({
table: true,
})
const page = reactive<Pagination>({
current: 1,
pageSize: 10,
@@ -43,6 +47,7 @@ const canuseOptions = [
},
]
const tableData = ref<CompanyUser[]>([])
const selectedRows = ref<CompanyUser[]>([])
const showEdit = ref(false)
const editUser = ref<CompanyUser | null>(null)
@@ -51,7 +56,12 @@ onMounted(() => {
getCompanyUser()
})
function selectable(row: CompanyUser) {
return row.role !== 0
}
function getCompanyUser() {
loading.table = true
queryCompanyUserApi({
...queryForm,
currentPage: page.current,
@@ -67,13 +77,92 @@ function getCompanyUser() {
}).catch((err) => {
console.log(err)
ElMessage.error('查询失败,请稍后再试')
}).finally(() => {
loading.table = false
})
}
function resetQueryForm() {
queryForm.currentPage = page.current
queryForm.pageSize = page.pageSize
queryForm.name = ''
queryForm.phone = ''
queryForm.position = ''
queryForm.email = ''
queryForm.canuse = ''
}
function resetPage() {
page.current = 1
page.pageSize = 10
page.total = 0
}
function handleQuery() {
resetPage()
getCompanyUser()
}
function handleShowEditDrawer(user: CompanyUser | null) {
editUser.value = user
showEdit.value = true
}
function handleCloseEditDrawer() {
showEdit.value = false
editUser.value = null
}
function handleSelectionChange(val: CompanyUser[]) {
selectedRows.value = val
}
function handleDelteRows(val?: CompanyUser) {
if (!val && selectedRows.value.length === 0) {
ElMessage.warning('请选择需要删除的数据')
return
}
const rowsToDelete = val ? [val] : selectedRows.value
const deleteIds: number[] = rowsToDelete.map(row => row.id)
const namesToDelete: string[] = rowsToDelete.map(row => row.name)
const tipMessage = `您确定要删除以下用户: ${namesToDelete.join(', ')}`
ElMessageBox.confirm(
tipMessage,
'删除提示',
{
confirmButtonText: '确认删除',
cancelButtonText: '取消',
type: 'warning',
},
).then(() => {
deleteCompanyUserApi({
companyId: userStore.userInfo.company.id,
ids: deleteIds,
}).then((res) => {
if (res.isSuccess) {
resetPage()
resetQueryForm()
getCompanyUser()
ElMessage.success('删除成功')
}
else {
ElMessage.error(res.message || '删除失败,请稍后再试')
}
}).catch((err) => {
console.log(err)
ElMessage.error('删除失败,请稍后再试')
})
})
}
</script>
<template>
@@ -116,10 +205,17 @@ function handleShowEditDrawer(user: CompanyUser | null) {
</el-col>
<el-col :span="18">
<el-form-item>
<el-button :icon="Refresh">
<el-button
:icon="Refresh"
@click="resetQueryForm()"
>
重置
</el-button>
<el-button type="primary" :icon="Search">
<el-button
type="primary"
:icon="Search"
@click="handleQuery"
>
查询
</el-button>
</el-form-item>
@@ -134,17 +230,28 @@ function handleShowEditDrawer(user: CompanyUser | null) {
<el-button type="primary" plain :icon="Plus" @click="handleShowEditDrawer(null)">
新增
</el-button>
<el-button type="danger" plain :icon="Delete">
<el-button type="danger" plain :icon="Delete" @click="handleDelteRows()">
批量删除
</el-button>
<el-button :icon="Refresh">
<el-button :icon="Refresh" @click="getCompanyUser()">
刷新
</el-button>
</div>
</div>
<div class="table-body-wrapper">
<el-table :data="tableData" border stripe>
<el-table-column type="selection" width="55" align="center" />
<el-table
v-loading="loading.table"
border
stripe
:data="tableData"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:selectable="selectable"
/>
<el-table-column prop="name" label="名称" align="center">
<template #default="scope">
<template v-if="scope.row.role === 1">
@@ -163,20 +270,21 @@ function handleShowEditDrawer(user: CompanyUser | null) {
<el-table-column prop="phone" label="电话" align="center" />
<el-table-column prop="canuse" label="启用" width="100" align="center">
<template #default="scope">
<el-tag :type="scope.row.canuse === '1' ? 'primary' : 'warning'">
启用
<el-tag :type="scope.row.canuse === '1' ? 'primary' : 'danger'">
{{ scope.row.canuse === '1' ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button size="small">
<el-button size="small" @click="handleShowEditDrawer(scope.row)">
修改
</el-button>
<el-button
v-if="scope.row.role !== 0"
size="small"
type="danger"
@click="handleDelteRows(scope.row)"
>
删除
</el-button>
@@ -198,7 +306,13 @@ function handleShowEditDrawer(user: CompanyUser | null) {
</div>
</div>
<EditDrawer v-model="showEdit" :user="editUser" />
<EditDrawer
v-model="showEdit"
:user="editUser"
@data-change="getCompanyUser()"
@custom-close="handleCloseEditDrawer()"
@close="handleCloseEditDrawer()"
/>
</div>
</template>