Browse Source

迁移一期报表

dev-V1.10.2-temp
zhuibobo 4 months ago
parent
commit
0ef2271837
  1. 1
      script/sql/zfjd-refactoring-v1/011-1-重建虚拟单位树.sql
  2. 5
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/EfcodeVirtualUnitUser.java
  3. 5
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/bo/EfcodeVirtualUnitUserBo.java
  4. 31
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/bo/RefUserBo.java
  5. 35
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/bo/RefUserRemarkBo.java
  6. 6
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/vo/EfcodeVirtualUnitUserVo.java
  7. 5
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/vo/UnitUserVo.java
  8. 11
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/mapper/EfcodeVirtualUnitMapper.java
  9. 2
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/mapper/EfcodeVirtualUnitUserMapper.java
  10. 35
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/IEfcodeVirtualUnitService.java
  11. 86
      zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java
  12. 47
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/EfcodeVirtualUnitController.java
  13. 27
      zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/EfcodeVirtualUnitMapper.xml
  14. 49
      zdxt-web-client/zdxt-admin-plus-ui/src/api/efcode/virtualUnit/index.ts
  15. 1
      zdxt-web-client/zdxt-admin-plus-ui/src/api/efcode/virtualUnit/types.ts
  16. 346
      zdxt-web-client/zdxt-admin-plus-ui/src/views/efcode/virtualUnit/unitUserManager.vue
  17. 4
      zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index-dept-separate.vue

1
script/sql/zfjd-refactoring-v1/011-1-重建虚拟单位树.sql

@ -27,6 +27,7 @@ create table efcode_virtual_unit
create table efcode_virtual_unit_user create table efcode_virtual_unit_user
( (
vir_user_id varchar(100) not null comment '主键ID' primary key, vir_user_id varchar(100) not null comment '主键ID' primary key,
vir_unit_id varchar(100) null comment '虚拟单位ID,关联efcode_virtual_unit.vir_id',
sys_user_id varchar(100) null comment '真实用户id,关联sys_user.user_id', sys_user_id varchar(100) null comment '真实用户id,关联sys_user.user_id',
remark varchar(200) null comment '备注', remark varchar(200) null comment '备注',
order_num int default 0 null comment '显示顺序', order_num int default 0 null comment '显示顺序',

5
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/EfcodeVirtualUnitUser.java

@ -27,6 +27,11 @@ public class EfcodeVirtualUnitUser extends BaseEntity {
@TableId(value = "vir_user_id") @TableId(value = "vir_user_id")
private String virUserId; private String virUserId;
/**
* 虚拟单位ID,关联efcode_virtual_unit.vir_id
*/
private String virUnitId;
/** /**
* 真实用户id,关联sys_user.user_id * 真实用户id,关联sys_user.user_id
*/ */

5
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/bo/EfcodeVirtualUnitUserBo.java

@ -26,6 +26,11 @@ public class EfcodeVirtualUnitUserBo extends BaseEntity {
@NotBlank(message = "主键ID不能为空", groups = { EditGroup.class }) @NotBlank(message = "主键ID不能为空", groups = { EditGroup.class })
private String virUserId; private String virUserId;
/**
* 虚拟单位ID,关联efcode_virtual_unit.vir_id
*/
private String virUnitId;
/** /**
* 真实用户id,关联sys_user.user_id * 真实用户id,关联sys_user.user_id
*/ */

31
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/bo/RefUserBo.java

@ -0,0 +1,31 @@
package com.zdxt.enforcementcode.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 虚拟单位引用人员BO
*/
@Data
public class RefUserBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 虚拟单位ID
*/
@NotBlank(message = "虚拟单位ID不能为空")
private String virUnitId;
/**
* 真实用户ID集合
*/
@NotEmpty(message = "请选择人员")
private List<Long> sysUserIds;
}

35
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/bo/RefUserRemarkBo.java

@ -0,0 +1,35 @@
package com.zdxt.enforcementcode.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 虚拟单位引用人员备注BO
*/
@Data
public class RefUserRemarkBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 虚拟单位ID
*/
@NotBlank(message = "虚拟单位ID不能为空")
private String virUnitId;
/**
* 真实用户ID
*/
@NotNull(message = "用户ID不能为空")
private Long sysUserId;
/**
* 备注
*/
private String remark;
}

6
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/vo/EfcodeVirtualUnitUserVo.java

@ -34,6 +34,12 @@ public class EfcodeVirtualUnitUserVo implements Serializable {
@ExcelProperty(value = "主键ID") @ExcelProperty(value = "主键ID")
private String virUserId; private String virUserId;
/**
* 虚拟单位ID,关联efcode_virtual_unit.vir_id
*/
@ExcelProperty(value = "虚拟单位ID,关联efcode_virtual_unit.vir_id")
private String virUnitId;
/** /**
* 真实用户id,关联sys_user.user_id * 真实用户id,关联sys_user.user_id
*/ */

5
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/domain/vo/UnitUserVo.java

@ -58,4 +58,9 @@ public class UnitUserVo implements Serializable {
* 人员来源(10=本系统新增) * 人员来源(10=本系统新增)
*/ */
private Integer userSource; private Integer userSource;
/**
* 引用备注(仅引用人员列表使用,来自efcode_virtual_unit_user.remark)
*/
private String remark;
} }

11
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/mapper/EfcodeVirtualUnitMapper.java

@ -33,6 +33,17 @@ public interface EfcodeVirtualUnitMapper extends BaseMapperPlus<EfcodeVirtualUni
@Param("keyword") String keyword, @Param("keyword") String keyword,
@Param("globalSearch") boolean globalSearch); @Param("globalSearch") boolean globalSearch);
/**
* 查询虚拟单位引用的人员列表(来自 efcode_virtual_unit_user)
*
* @param virUnitId 虚拟单位ID
* @param keyword 搜索关键字
* @return 人员列表
*/
IPage<UnitUserVo> selectReferencedUsers(Page<UnitUserVo> page,
@Param("virUnitId") String virUnitId,
@Param("keyword") String keyword);
/** /**
* 查询指定节点的子孙级虚拟单位(按查询/统计/业务条件过滤) * 查询指定节点的子孙级虚拟单位(按查询/统计/业务条件过滤)
* *

2
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/mapper/EfcodeVirtualUnitUserMapper.java

@ -2,6 +2,7 @@ package com.zdxt.enforcementcode.mapper;
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnitUser; import com.zdxt.enforcementcode.domain.EfcodeVirtualUnitUser;
import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitUserVo; import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitUserVo;
import org.apache.ibatis.annotations.Mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/** /**
@ -10,6 +11,7 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
* @author Lion Li * @author Lion Li
* @date 2026-07-07 * @date 2026-07-07
*/ */
@Mapper
public interface EfcodeVirtualUnitUserMapper extends BaseMapperPlus<EfcodeVirtualUnitUser, EfcodeVirtualUnitUserVo> { public interface EfcodeVirtualUnitUserMapper extends BaseMapperPlus<EfcodeVirtualUnitUser, EfcodeVirtualUnitUserVo> {
} }

35
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/IEfcodeVirtualUnitService.java

@ -105,6 +105,41 @@ public interface IEfcodeVirtualUnitService {
*/ */
TableDataInfo<UnitUserVo> queryUsersBySysDeptId(String sysDeptId, String keyword, boolean globalSearch, PageQuery pageQuery); TableDataInfo<UnitUserVo> queryUsersBySysDeptId(String sysDeptId, String keyword, boolean globalSearch, PageQuery pageQuery);
/**
* 分页查询虚拟单位引用的人员列表
*
* @param virUnitId 虚拟单位ID
* @param keyword 搜索关键字(可选)
* @param pageQuery 分页参数
* @return 人员分页列表
*/
TableDataInfo<UnitUserVo> queryReferencedUsers(String virUnitId, String keyword, PageQuery pageQuery);
/**
* 新增虚拟单位引用人员(批量,已存在的自动跳过)
*
* @param virUnitId 虚拟单位ID
* @param sysUserIds 真实用户ID集合
*/
void addReferencedUsers(String virUnitId, List<Long> sysUserIds);
/**
* 移除虚拟单位引用人员
*
* @param virUnitId 虚拟单位ID
* @param sysUserIds 真实用户ID集合
*/
void deleteReferencedUsers(String virUnitId, List<Long> sysUserIds);
/**
* 修改虚拟单位引用人员的备注
*
* @param virUnitId 虚拟单位ID
* @param sysUserId 真实用户ID
* @param remark 备注
*/
void updateReferencedUserRemark(String virUnitId, Long sysUserId, String remark);
/** /**
* 是否存在子节点 * 是否存在子节点
* *

86
zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java

@ -23,7 +23,9 @@ import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo;
import com.zdxt.enforcementcode.domain.vo.UnitUserVo; import com.zdxt.enforcementcode.domain.vo.UnitUserVo;
import com.zdxt.enforcementcode.domain.vo.VirtualUnitDeptTreeVo; import com.zdxt.enforcementcode.domain.vo.VirtualUnitDeptTreeVo;
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit; import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit;
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnitUser;
import com.zdxt.enforcementcode.mapper.EfcodeVirtualUnitMapper; import com.zdxt.enforcementcode.mapper.EfcodeVirtualUnitMapper;
import com.zdxt.enforcementcode.mapper.EfcodeVirtualUnitUserMapper;
import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService; import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService;
import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysDept;
import org.dromara.system.domain.SysUser; import org.dromara.system.domain.SysUser;
@ -48,6 +50,7 @@ import java.util.stream.Collectors;
public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService { public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService {
private final EfcodeVirtualUnitMapper baseMapper; private final EfcodeVirtualUnitMapper baseMapper;
private final EfcodeVirtualUnitUserMapper virtualUnitUserMapper;
private final SysDeptMapper sysDeptMapper; private final SysDeptMapper sysDeptMapper;
private final SrzDeptMapper srzDeptMapper; private final SrzDeptMapper srzDeptMapper;
private final SysUserMapper sysUserMapper; private final SysUserMapper sysUserMapper;
@ -264,6 +267,89 @@ public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService {
return TableDataInfo.build(page); return TableDataInfo.build(page);
} }
/**
* 分页查询虚拟单位引用的人员列表
* SQL实现参见 EfcodeVirtualUnitMapper.xml#selectReferencedUsers
*/
@Override
public TableDataInfo<UnitUserVo> queryReferencedUsers(String virUnitId, String keyword, PageQuery pageQuery) {
if (StringUtils.isBlank(virUnitId)) {
return TableDataInfo.build(new Page<>());
}
IPage<UnitUserVo> page = baseMapper.selectReferencedUsers(pageQuery.build(), virUnitId, keyword);
return TableDataInfo.build(page);
}
/**
* 新增虚拟单位引用人员(批量,已存在的自动跳过)
*/
@Override
public void addReferencedUsers(String virUnitId, List<Long> sysUserIds) {
if (StringUtils.isBlank(virUnitId)) {
throw new ServiceException("虚拟单位ID不能为空");
}
if (sysUserIds == null || sysUserIds.isEmpty()) {
throw new ServiceException("请选择要引用的人员");
}
// 查询该单位已引用的用户,过滤重复
List<EfcodeVirtualUnitUser> existList = virtualUnitUserMapper.selectList(
Wrappers.<EfcodeVirtualUnitUser>lambdaQuery()
.eq(EfcodeVirtualUnitUser::getVirUnitId, virUnitId)
);
Set<String> existUserIds = existList.stream()
.map(EfcodeVirtualUnitUser::getSysUserId)
.collect(Collectors.toSet());
for (Long sysUserId : sysUserIds) {
if (sysUserId == null || existUserIds.contains(String.valueOf(sysUserId))) {
continue;
}
EfcodeVirtualUnitUser entity = new EfcodeVirtualUnitUser();
entity.setVirUserId(UUID.randomUUID().toString().replace("-", ""));
entity.setVirUnitId(virUnitId);
entity.setSysUserId(String.valueOf(sysUserId));
entity.setOrderNum(0L);
virtualUnitUserMapper.insert(entity);
}
}
/**
* 移除虚拟单位引用人员
*/
@Override
public void deleteReferencedUsers(String virUnitId, List<Long> sysUserIds) {
if (StringUtils.isBlank(virUnitId)) {
throw new ServiceException("虚拟单位ID不能为空");
}
if (sysUserIds == null || sysUserIds.isEmpty()) {
throw new ServiceException("请选择要移除的人员");
}
List<String> ids = sysUserIds.stream()
.filter(Objects::nonNull)
.map(String::valueOf)
.collect(Collectors.toList());
virtualUnitUserMapper.delete(
Wrappers.<EfcodeVirtualUnitUser>lambdaQuery()
.eq(EfcodeVirtualUnitUser::getVirUnitId, virUnitId)
.in(EfcodeVirtualUnitUser::getSysUserId, ids)
);
}
/**
* 修改虚拟单位引用人员的备注
*/
@Override
public void updateReferencedUserRemark(String virUnitId, Long sysUserId, String remark) {
if (StringUtils.isBlank(virUnitId) || sysUserId == null) {
throw new ServiceException("参数不能为空");
}
virtualUnitUserMapper.update(null,
Wrappers.<EfcodeVirtualUnitUser>lambdaUpdate()
.set(EfcodeVirtualUnitUser::getRemark, remark)
.eq(EfcodeVirtualUnitUser::getVirUnitId, virUnitId)
.eq(EfcodeVirtualUnitUser::getSysUserId, String.valueOf(sysUserId))
);
}
/** /**
* 是否存在子节点 * 是否存在子节点
*/ */

47
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/EfcodeVirtualUnitController.java

@ -22,6 +22,8 @@ import com.zdxt.enforcementcode.domain.vo.UnitUserVo;
import com.zdxt.enforcementcode.domain.vo.VirtualUnitDeptTreeVo; import com.zdxt.enforcementcode.domain.vo.VirtualUnitDeptTreeVo;
import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo; import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo;
import com.zdxt.enforcementcode.domain.bo.UnitUserBo; import com.zdxt.enforcementcode.domain.bo.UnitUserBo;
import com.zdxt.enforcementcode.domain.bo.RefUserBo;
import com.zdxt.enforcementcode.domain.bo.RefUserRemarkBo;
import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService; import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
@ -96,6 +98,51 @@ public class EfcodeVirtualUnitController extends BaseController {
return efcodeVirtualUnitService.queryUsersBySysDeptId(sysDeptId, keyword, globalSearch, pageQuery); return efcodeVirtualUnitService.queryUsersBySysDeptId(sysDeptId, keyword, globalSearch, pageQuery);
} }
/**
* 分页查询虚拟单位引用的人员列表
*
* @param virUnitId 虚拟单位ID
* @param keyword 搜索关键字
*/
@GetMapping("/refUsers")
public TableDataInfo<UnitUserVo> queryReferencedUsers(
@RequestParam String virUnitId,
@RequestParam(required = false) String keyword,
PageQuery pageQuery) {
return efcodeVirtualUnitService.queryReferencedUsers(virUnitId, keyword, pageQuery);
}
/**
* 新增虚拟单位引用人员
*/
@Log(title = "引用人员", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/refUser")
public R<Void> addReferencedUsers(@Validated @RequestBody RefUserBo bo) {
efcodeVirtualUnitService.addReferencedUsers(bo.getVirUnitId(), bo.getSysUserIds());
return R.ok();
}
/**
* 移除虚拟单位引用人员
*/
@Log(title = "引用人员", businessType = BusinessType.DELETE)
@DeleteMapping("/refUser")
public R<Void> deleteReferencedUsers(@Validated @RequestBody RefUserBo bo) {
efcodeVirtualUnitService.deleteReferencedUsers(bo.getVirUnitId(), bo.getSysUserIds());
return R.ok();
}
/**
* 修改虚拟单位引用人员备注
*/
@Log(title = "引用人员", businessType = BusinessType.UPDATE)
@PutMapping("/refUser/remark")
public R<Void> updateReferencedUserRemark(@Validated @RequestBody RefUserRemarkBo bo) {
efcodeVirtualUnitService.updateReferencedUserRemark(bo.getVirUnitId(), bo.getSysUserId(), bo.getRemark());
return R.ok();
}
/** /**
* 导出虚拟单位树列表 * 导出虚拟单位树列表
*/ */

27
zdxt-modules/zdxt-enforcement-code/src/main/resources/mapper/enforcementcode/EfcodeVirtualUnitMapper.xml

@ -40,6 +40,33 @@
</if> </if>
ORDER BY u.dept_id ASC, u.user_id ASC ORDER BY u.dept_id ASC, u.user_id ASC
</select> </select>
<!-- 查询虚拟单位引用的人员列表(来自 efcode_virtual_unit_user) -->
<select id="selectReferencedUsers" resultType="com.zdxt.enforcementcode.domain.vo.UnitUserVo">
SELECT
u.user_id AS userId,
u.dept_id AS deptId,
u.user_name AS userName,
u.login_name AS loginName,
u.fullname AS fullname,
u.mobileNumber AS mobileNumber,
u.user_source AS userSource,
vu.remark AS remark,
REPLACE(COALESCE(d.zzDisplayPath, ''), '深圳市/', '') AS zzDisplayPath,
0 AS isSubDeptUser
FROM efcode_virtual_unit_user vu
INNER JOIN sys_user u ON vu.sys_user_id = u.user_id AND u.del_flag = '0'
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
WHERE vu.vir_unit_id = #{virUnitId}
<if test="keyword != null and keyword != ''">
AND (
u.fullname LIKE CONCAT('%', #{keyword}, '%')
OR u.login_name LIKE CONCAT('%', #{keyword}, '%')
OR u.user_name LIKE CONCAT('%', #{keyword}, '%')
)
</if>
ORDER BY vu.order_num ASC, u.user_id ASC
</select>
<!-- 查询指定节点的子孙级(按查询/统计/业务条件过滤) --> <!-- 查询指定节点的子孙级(按查询/统计/业务条件过滤) -->
<select id="selectDescendants" resultType="com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo"> <select id="selectDescendants" resultType="com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo">
SELECT vir_id, sys_dept_id SELECT vir_id, sys_dept_id

49
zdxt-web-client/zdxt-admin-plus-ui/src/api/efcode/virtualUnit/index.ts

@ -127,3 +127,52 @@ export const deleteUnitUser = (userIds: (number | string)[]) => {
method: 'delete' method: 'delete'
}); });
}; };
/**
* 查询虚拟单位引用的人员列表(分页)
*/
export const getReferencedUsers = (params: {
virUnitId: string;
keyword?: string;
pageNum?: number;
pageSize?: number;
}) => {
return request({
url: '/enforcementcode/virtualUnit/refUsers',
method: 'get',
params
});
};
/**
* 新增虚拟单位引用人员
*/
export const addReferencedUsers = (data: { virUnitId: string; sysUserIds: (number | string)[] }) => {
return request({
url: '/enforcementcode/virtualUnit/refUser',
method: 'post',
data
});
};
/**
* 移除虚拟单位引用人员
*/
export const deleteReferencedUsers = (data: { virUnitId: string; sysUserIds: (number | string)[] }) => {
return request({
url: '/enforcementcode/virtualUnit/refUser',
method: 'delete',
data
});
};
/**
* 修改虚拟单位引用人员备注
*/
export const updateReferencedUserRemark = (data: { virUnitId: string; sysUserId: number | string; remark?: string }) => {
return request({
url: '/enforcementcode/virtualUnit/refUser/remark',
method: 'put',
data
});
};

1
zdxt-web-client/zdxt-admin-plus-ui/src/api/efcode/virtualUnit/types.ts

@ -58,5 +58,6 @@ export interface UnitUserVo {
zzDisplayPath: string; zzDisplayPath: string;
isSubDeptUser: boolean; isSubDeptUser: boolean;
userSource: number; userSource: number;
remark?: string;
[key: string]: any; [key: string]: any;
} }

346
zdxt-web-client/zdxt-admin-plus-ui/src/views/efcode/virtualUnit/unitUserManager.vue

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted, watch, reactive, nextTick } from 'vue'; import { ref, computed, onMounted, watch, reactive, nextTick } from 'vue';
import { Search } from '@element-plus/icons-vue'; import { Search, Edit } from '@element-plus/icons-vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { getBusinessTreeList, getUnitUsers, addUnitUser, updateUnitUser, deleteUnitUser } from '@/api/efcode/virtualUnit'; import { getBusinessTreeList, getUnitUsers, addUnitUser, updateUnitUser, deleteUnitUser, getReferencedUsers, addReferencedUsers, deleteReferencedUsers, updateReferencedUserRemark } from '@/api/efcode/virtualUnit';
import { getAuthRole, updateAuthRole, resetUserPwd } from '@/api/system/user'; import { getAuthRole, updateAuthRole, resetUserPwd } from '@/api/system/user';
import type { VirtualUnitVo, UnitUserVo } from '@/api/efcode/virtualUnit/types'; import type { VirtualUnitVo, UnitUserVo } from '@/api/efcode/virtualUnit/types';
import type { RoleVO } from '@/api/system/role/types'; import type { RoleVO } from '@/api/system/role/types';
@ -224,6 +224,191 @@ onMounted(() => {
loadTree(); loadTree();
}); });
/** ============ 右侧Tab切换 ============ */
const activeTab = ref('staff');
/** ============ 引用人员列表(Tab2) ============ */
const refUserList = ref<UnitUserVo[]>([]);
const refUserLoading = ref(false);
const refUserSearchKeyword = ref('');
const refUserTotal = ref(0);
const refUserPageNum = ref(1);
const refUserPageSize = ref(16);
/** 加载引用人员列表 */
const loadRefUsers = async () => {
if (!selectedNode.value?.virId) {
refUserList.value = [];
refUserTotal.value = 0;
return;
}
refUserLoading.value = true;
try {
const res = await getReferencedUsers({
virUnitId: selectedNode.value.virId,
keyword: refUserSearchKeyword.value.trim() || undefined,
pageNum: refUserPageNum.value,
pageSize: refUserPageSize.value
});
refUserList.value = res.rows;
refUserTotal.value = res.total;
} finally {
refUserLoading.value = false;
}
};
/** 引用人员搜索 */
const handleRefSearch = () => {
refUserPageNum.value = 1;
loadRefUsers();
};
const handleRefPageChange = (page: number) => {
refUserPageNum.value = page;
loadRefUsers();
};
const handleRefSizeChange = (size: number) => {
refUserPageSize.value = size;
refUserPageNum.value = 1;
loadRefUsers();
};
/** 移除引用人员 */
const handleRemoveRef = async (row: UnitUserVo) => {
try {
await ElMessageBox.confirm(`确认移除引用人员“${row.fullname}”吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
await deleteReferencedUsers({ virUnitId: selectedNode.value!.virId, sysUserIds: [row.userId] });
ElMessage.success('移除成功');
loadRefUsers();
} catch {
// cancelled
}
};
/** Tab切换或选中节点变化时加载引用人员 */
watch(activeTab, () => {
if (activeTab.value === 'ref') {
refUserPageNum.value = 1;
loadRefUsers();
}
});
watch(selectedNode, () => {
if (activeTab.value === 'ref') {
refUserPageNum.value = 1;
loadRefUsers();
}
});
/** ============ 引用人员备注行内编辑 ============ */
/** 当前正在编辑备注的行userId */
const editingRemarkId = ref<number | null>(null);
/** 编辑中的备注内容 */
const editingRemarkValue = ref('');
/** 进入备注编辑态 */
const startEditRemark = (row: UnitUserVo) => {
editingRemarkId.value = row.userId;
editingRemarkValue.value = row.remark || '';
};
/** 取消备注编辑 */
const cancelEditRemark = () => {
editingRemarkId.value = null;
editingRemarkValue.value = '';
};
/** 保存备注 */
const saveRemark = async (row: UnitUserVo) => {
const value = editingRemarkValue.value.trim();
try {
await updateReferencedUserRemark({
virUnitId: selectedNode.value!.virId,
sysUserId: row.userId,
remark: value
});
row.remark = value;
ElMessage.success('备注保存成功');
cancelEditRemark();
} catch {
// 服务端报错由全局拦截器处理
}
};
/** ============ 人员选择对话框(引用) ============ */
const selectDialogVisible = ref(false);
const selectLoading = ref(false);
const selectUserList = ref<UnitUserVo[]>([]);
const selectTableRef = ref<InstanceType<typeof import('element-plus')['ElTable']>>();
const selectKeyword = ref('');
const selectTotal = ref(0);
const selectPageNum = ref(1);
const selectPageSize = ref(10);
/** 打开人员选择对话框 */
const openSelectDialog = () => {
if (!selectedNode.value?.virId) {
ElMessage.warning('请先选择左侧的执法单位');
return;
}
selectKeyword.value = '';
selectPageNum.value = 1;
selectDialogVisible.value = true;
loadSelectUsers();
};
/** 加载可选人员(全局搜索) */
const loadSelectUsers = async () => {
selectLoading.value = true;
try {
const res = await getUnitUsers({
globalSearch: true,
keyword: selectKeyword.value.trim() || undefined,
pageNum: selectPageNum.value,
pageSize: selectPageSize.value
});
selectUserList.value = res.rows;
selectTotal.value = res.total;
} finally {
selectLoading.value = false;
}
};
const handleSelectSearch = () => {
selectPageNum.value = 1;
loadSelectUsers();
};
const handleSelectPageChange = (page: number) => {
selectPageNum.value = page;
loadSelectUsers();
};
const handleSelectSizeChange = (size: number) => {
selectPageSize.value = size;
selectPageNum.value = 1;
loadSelectUsers();
};
/** 确认引用所选人员 */
const submitSelect = async () => {
const rows: UnitUserVo[] = selectTableRef.value?.getSelectionRows() || [];
const ids = rows.map((r) => r.userId);
if (!ids.length) {
ElMessage.warning('请至少选择一名人员');
return;
}
await addReferencedUsers({ virUnitId: selectedNode.value!.virId, sysUserIds: ids });
ElMessage.success('引用成功');
selectDialogVisible.value = false;
loadRefUsers();
};
/** ============ 人员新增/编辑对话框 ============ */ /** ============ 人员新增/编辑对话框 ============ */
const userFormRef = ref(); const userFormRef = ref();
const dialogVisible = ref(false); const dialogVisible = ref(false);
@ -492,14 +677,15 @@ const submitResetPwd = async () => {
<!-- 右侧:人员列表 --> <!-- 右侧:人员列表 -->
<div class="right-panel"> <div class="right-panel">
<el-card shadow="hover"> <el-card shadow="hover">
<template #header> <el-tabs v-model="activeTab" class="user-tabs">
<!-- Tab1:执法人员 -->
<el-tab-pane label="执法人员" name="staff">
<div class="right-header"> <div class="right-header">
<span class="panel-title"> <span class="panel-title">
执法人员 <el-tag v-if="selectedNode && !globalSearch" type="info" size="small">
<el-tag v-if="selectedNode && !globalSearch" type="info" size="small" style="margin-left: 8px;">
{{ selectedNode.virName }} {{ selectedNode.virName }}
</el-tag> </el-tag>
<el-tag v-if="globalSearch" type="warning" size="small" style="margin-left: 8px;"> <el-tag v-if="globalSearch" type="warning" size="small">
全局搜索 全局搜索
</el-tag> </el-tag>
</span> </span>
@ -517,13 +703,12 @@ const submitResetPwd = async () => {
<el-button type="primary" plain style="margin-left: 8px;" @click="handleAddUser">新增</el-button> <el-button type="primary" plain style="margin-left: 8px;" @click="handleAddUser">新增</el-button>
</div> </div>
</div> </div>
</template>
<el-table <el-table
:data="userList" :data="userList"
border border
v-loading="userLoading" v-loading="userLoading"
:row-class-name="userRowClassName" :row-class-name="userRowClassName"
max-height="calc(100vh - 240px)" max-height="calc(100vh - 280px)"
> >
<el-table-column type="index" label="#" width="50" align="center" :index="(i: number) => (userPageNum - 1) * userPageSize + i + 1" /> <el-table-column type="index" label="#" width="50" align="center" :index="(i: number) => (userPageNum - 1) * userPageSize + i + 1" />
<el-table-column prop="fullname" label="姓名" min-width="100" show-overflow-tooltip /> <el-table-column prop="fullname" label="姓名" min-width="100" show-overflow-tooltip />
@ -549,9 +734,126 @@ const submitResetPwd = async () => {
@current-change="handlePageChange" @current-change="handlePageChange"
@size-change="handleSizeChange" @size-change="handleSizeChange"
/> />
</el-tab-pane>
<!-- Tab2:引用人员 -->
<el-tab-pane label="引用人员" name="ref">
<div class="right-header">
<span class="panel-title">
<el-tag v-if="selectedNode" type="info" size="small">
{{ selectedNode.virName }}
</el-tag>
</span>
<div class="search-bar">
<el-input
v-model="refUserSearchKeyword"
placeholder="姓名/账号"
:prefix-icon="Search"
clearable
style="width: 200px;"
@keyup.enter="handleRefSearch"
/>
<el-button type="primary" style="margin-left: 8px;" @click="handleRefSearch">查询</el-button>
<el-button type="primary" plain style="margin-left: 8px;" @click="openSelectDialog">引用人员</el-button>
</div>
</div>
<el-table
:data="refUserList"
border
v-loading="refUserLoading"
max-height="calc(100vh - 280px)"
>
<el-table-column type="index" label="#" width="50" align="center" :index="(i: number) => (refUserPageNum - 1) * refUserPageSize + i + 1" />
<el-table-column prop="fullname" label="姓名" min-width="100" show-overflow-tooltip />
<el-table-column prop="loginName" label="账号" min-width="120" show-overflow-tooltip />
<el-table-column prop="zzDisplayPath" label="所属部门" min-width="280" show-overflow-tooltip />
<el-table-column label="备注" min-width="220">
<template #default="{ row }">
<div v-if="editingRemarkId === row.userId" class="remark-edit">
<el-input
v-model="editingRemarkValue"
size="small"
placeholder="请输入备注"
maxlength="200"
@keyup.enter="saveRemark(row)"
/>
<el-button type="primary" link size="small" @click="saveRemark(row)">保存</el-button>
<el-button type="info" link size="small" @click="cancelEditRemark">取消</el-button>
</div>
<div v-else class="remark-view" @click="startEditRemark(row)">
<span :class="{ 'remark-placeholder': !row.remark }">{{ row.remark || '点击添加备注' }}</span>
<el-icon class="remark-edit-icon"><Edit /></el-icon>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center" fixed="right">
<template #default="{ row }">
<el-button type="danger" link size="small" @click="handleRemoveRef(row)">移除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
v-if="refUserTotal > 0"
style="margin-top: 12px; justify-content: flex-end;"
:current-page="refUserPageNum"
:page-size="refUserPageSize"
:page-sizes="[10, 20, 50]"
:total="refUserTotal"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handleRefPageChange"
@size-change="handleRefSizeChange"
/>
</el-tab-pane>
</el-tabs>
</el-card> </el-card>
</div> </div>
<!-- 人员选择对话框(引用) -->
<el-dialog v-model="selectDialogVisible" title="选择引用人员" width="860px" append-to-body>
<div style="margin-bottom: 12px; display: flex; align-items: center; justify-content: space-between;">
<span style="color: #909399; font-size: 13px;">支持全局搜索,可跨页勾选多人</span>
<div>
<el-input
v-model="selectKeyword"
placeholder="姓名/账号"
:prefix-icon="Search"
clearable
style="width: 220px;"
@keyup.enter="handleSelectSearch"
/>
<el-button type="primary" style="margin-left: 8px;" @click="handleSelectSearch">查询</el-button>
</div>
</div>
<el-table
ref="selectTableRef"
v-loading="selectLoading"
:data="selectUserList"
border
row-key="userId"
max-height="420px"
>
<el-table-column type="selection" width="55" reserve-selection />
<el-table-column prop="fullname" label="姓名" min-width="100" show-overflow-tooltip />
<el-table-column prop="loginName" label="账号" min-width="120" show-overflow-tooltip />
<el-table-column prop="zzDisplayPath" label="所属部门" min-width="300" show-overflow-tooltip />
</el-table>
<el-pagination
v-if="selectTotal > 0"
style="margin-top: 12px; justify-content: flex-end;"
:current-page="selectPageNum"
:page-size="selectPageSize"
:page-sizes="[10, 20, 50]"
:total="selectTotal"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handleSelectPageChange"
@size-change="handleSelectSizeChange"
/>
<template #footer>
<el-button @click="selectDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submitSelect">确 定</el-button>
</template>
</el-dialog>
<!-- 分配角色对话框 --> <!-- 分配角色对话框 -->
<el-dialog v-model="roleDialogVisible" title="分配角色" width="860px" append-to-body @close="roleSearchKeyword = ''"> <el-dialog v-model="roleDialogVisible" title="分配角色" width="860px" append-to-body @close="roleSearchKeyword = ''">
<div style="margin-bottom: 12px; display: flex; align-items: center; justify-content: space-between;"> <div style="margin-bottom: 12px; display: flex; align-items: center; justify-content: space-between;">
@ -698,4 +1000,32 @@ const submitResetPwd = async () => {
color: #f56c6c; color: #f56c6c;
font-weight: bold; font-weight: bold;
} }
.remark-edit {
display: flex;
align-items: center;
gap: 4px;
}
.remark-view {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
min-height: 24px;
.remark-edit-icon {
opacity: 0;
color: var(--el-color-primary);
transition: opacity 0.2s;
}
&:hover .remark-edit-icon {
opacity: 1;
}
}
.remark-placeholder {
color: #c0c4cc;
}
</style> </style>

4
zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index-dept-separate.vue

@ -41,7 +41,7 @@
</el-form-item> </el-form-item>
<el-form-item label="创建时间" style="width: 308px"> <el-form-item label="创建时间" style="width: 308px">
<el-date-picker <el-date-picker
v-model="dateRange as any" v-model="dateRange"
value-format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
type="daterange" type="daterange"
range-separator="-" range-separator="-"
@ -283,7 +283,7 @@ const ids = ref<Array<string | number>>([]);
const single = ref(true); const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0); const total = ref(0);
const dateRange = ref<[DateModelType, DateModelType]>(['', '']); const dateRange = ref<any>(['', '']);
const menuOptions = ref<MenuTreeOption[]>([]); const menuOptions = ref<MenuTreeOption[]>([]);
const menuExpand = ref(false); const menuExpand = ref(false);
const menuNodeAll = ref(false); const menuNodeAll = ref(false);

Loading…
Cancel
Save