master
Gitea 2 weeks ago
parent 8c5449012d
commit 949568534a
  1. 3
      jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysUser.java
  2. 26
      jeecgboot-vue3/src/views/declarant/user.data.ts
  3. 395
      jeecgboot-vue3/src/views/declarantUnit/declarantUnitList.vue
  4. 23
      jeecgboot-vue3/src/views/system/depart/components/DepartLeftTree.vue
  5. 4
      jeecgboot-vue3/src/views/system/depart/depart.api.ts
  6. 9
      jeecgboot-vue3/src/views/system/depart/depart.data.ts
  7. 9
      jeecgboot-vue3/src/views/system/departUser/depart.user.data.ts
  8. 42
      jeecgboot-vue3/src/views/system/kejijuuser/PasswordModal.vue
  9. 45
      jeecgboot-vue3/src/views/system/kejijuuser/UserAgentModal.vue
  10. 178
      jeecgboot-vue3/src/views/system/kejijuuser/UserDrawer.vue
  11. 81
      jeecgboot-vue3/src/views/system/kejijuuser/UserQuitAgentModal.vue
  12. 110
      jeecgboot-vue3/src/views/system/kejijuuser/UserQuitModal.vue
  13. 166
      jeecgboot-vue3/src/views/system/kejijuuser/UserRecycleBinModal.vue
  14. 301
      jeecgboot-vue3/src/views/system/kejijuuser/index.vue
  15. 254
      jeecgboot-vue3/src/views/system/kejijuuser/user.api.ts
  16. 569
      jeecgboot-vue3/src/views/system/kejijuuser/user.data.ts
  17. 54
      jeecgboot-vue3/src/views/system/kejijuuser/userDetails.vue
  18. 1
      jeecgboot-vue3/types/store.d.ts

@ -222,4 +222,7 @@ public class SysUser implements Serializable {
*/ */
@TableField(exist = false) @TableField(exist = false)
private boolean izBindThird; private boolean izBindThird;
@TableField(exist = false)
private String roleCode;
} }

@ -51,7 +51,7 @@ export const columns: BasicColumn[] = [
// }, // },
{ {
title: '状态', title: '状态',
//dataIndex: 'orgCategory_dictText', // dataIndex: 'orgCategory_dictText',
dataIndex: 'status_dictText', dataIndex: 'status_dictText',
width: 80, width: 80,
}, },
@ -96,7 +96,7 @@ export const searchFormSchema: FormSchema[] = [
label: '名字', label: '名字',
field: 'realname', field: 'realname',
component: 'JInput', component: 'JInput',
//colProps: { span: 6 }, //colProps: { span: 6 },
}, },
// { // {
// label: '', // label: '',
@ -124,7 +124,7 @@ export const searchFormSchema: FormSchema[] = [
placeholder: '请选择状态', placeholder: '请选择状态',
stringToNumber: true, stringToNumber: true,
}, },
//colProps: { span: 6 }, //colProps: { span: 6 },
}, },
]; ];
@ -175,7 +175,7 @@ export const formSchema: FormSchema[] = [
required: true, required: true,
component: 'Input', component: 'Input',
}, },
{ /*{
label: '工号', label: '工号',
field: 'workNo', field: 'workNo',
required: true, required: true,
@ -190,7 +190,7 @@ export const formSchema: FormSchema[] = [
componentProps: { componentProps: {
labelKey: 'name', labelKey: 'name',
}, },
}, },*/
{ {
label: '角色', label: '角色',
field: 'selectedroles', field: 'selectedroles',
@ -234,7 +234,7 @@ export const formSchema: FormSchema[] = [
}; };
}, },
}, },
{ /*{
label: '租户', label: '租户',
field: 'relTenantIds', field: 'relTenantIds',
component: 'ApiSelect', component: 'ApiSelect',
@ -263,8 +263,8 @@ export const formSchema: FormSchema[] = [
}, },
}; };
}, },
}, },*/
{ /*{
label: '负责部门', label: '负责部门',
field: 'departIds', field: 'departIds',
component: 'Select', component: 'Select',
@ -272,7 +272,7 @@ export const formSchema: FormSchema[] = [
mode: 'multiple', mode: 'multiple',
}, },
ifShow: ({ values }) => values.userIdentity == 2, ifShow: ({ values }) => values.userIdentity == 2,
}, },*/
{ {
label: '头像', label: '头像',
field: 'avatar', field: 'avatar',
@ -320,13 +320,13 @@ export const formSchema: FormSchema[] = [
]; ];
}, },
}, },
{ /*{
label: '座机', label: '座机',
field: 'telephone', field: 'telephone',
component: 'Input', component: 'Input',
rules: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' }], rules: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' }],
}, },*/
{ /*{
label: '工作流引擎', label: '工作流引擎',
field: 'activitiSync', field: 'activitiSync',
defaultValue: 1, defaultValue: 1,
@ -336,7 +336,7 @@ export const formSchema: FormSchema[] = [
type: 'radio', type: 'radio',
stringToNumber: true, stringToNumber: true,
}, },
}, },*/
]; ];
export const formPasswordSchema: FormSchema[] = [ export const formPasswordSchema: FormSchema[] = [

@ -22,7 +22,7 @@
<!-- </a-button>--> <!-- </a-button>-->
<!-- </a-dropdown>--> <!-- </a-dropdown>-->
<!-- 高级查询 --> <!-- 高级查询 -->
<!-- <super-query :config="superQueryConfig" @search="handleSuperQuery"/>--> <!-- <super-query :config="superQueryConfig" @search="handleSuperQuery"/>-->
</template> </template>
<!--操作栏--> <!--操作栏-->
<template #action="{ record }"> <template #action="{ record }">
@ -38,212 +38,215 @@
</template> </template>
<script lang="ts" name="departtest-depart1012" setup> <script lang="ts" name="departtest-depart1012" setup>
import {reactive, ref} from 'vue'; import {reactive, ref} from 'vue';
import {BasicTable, TableAction} from '/@/components/Table'; import {BasicTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal'; import {useModal} from '/@/components/Modal';
import {useListPage} from '/@/hooks/system/useListPage' import {useListPage} from '/@/hooks/system/useListPage'
import Depart1012Modal from './components/Depart1012Modal.vue' import Depart1012Modal from './components/Depart1012Modal.vue'
import {columns, searchFormSchema, superQuerySchema} from './depart.user.data'; import {columns, searchFormSchema, superQuerySchema} from './depart.user.data';
import { import {
batchDelete, batchDelete,
deleteOne, deleteOne,
frozenBatch, frozenBatch,
getExportUrl, getExportUrl,
getImportUrl, getImportUrl,
list list
} from './depart.user.api'; } from './depart.user.api';
import {useUserStore} from '/@/store/modules/user'; import {useUserStore} from '/@/store/modules/user';
import {useMessage} from "@/hooks/web/useMessage"; import {useMessage} from "@/hooks/web/useMessage";
const queryParam = reactive<any>({}); const queryParam = reactive<any>({});
const checkedKeys = ref<Array<string | number>>([]); const checkedKeys = ref<Array<string | number>>([]);
const userStore = useUserStore(); const userStore = useUserStore();
const {createMessage, createConfirm} = useMessage(); // console.log("userStore.getUserInfo---",JSON.stringify(userStore.getUserInfo))
// console.log("userStore.getRoleList---",userStore.getRoleList)
//model const {createMessage, createConfirm} = useMessage();
const [registerModal, {openModal}] = useModal();
//table //model
const {prefixCls, tableContext, onExportXls, onImportXls} = useListPage({ const [registerModal, {openModal}] = useModal();
tableProps: { //table
title: '部门', const {prefixCls, tableContext, onExportXls, onImportXls} = useListPage({
api: list, tableProps: {
columns, title: '部门',
canResize: false, api: list,
formConfig: { columns,
//labelWidth: 120, canResize: false,
schemas: searchFormSchema, formConfig: {
autoSubmitOnEnter: true, //labelWidth: 120,
showAdvancedButton: true, schemas: searchFormSchema,
fieldMapToNumber: [], autoSubmitOnEnter: true,
fieldMapToTime: [], showAdvancedButton: true,
}, fieldMapToNumber: [],
actionColumn: { fieldMapToTime: [],
width: 180, },
fixed: 'right' actionColumn: {
width: 180,
fixed: 'right'
},
beforeFetch: (params) => {
return Object.assign(params, queryParam);
},
}, },
beforeFetch: (params) => { exportConfig: {
return Object.assign(params, queryParam); name: "部门",
url: getExportUrl,
params: queryParam,
}, },
}, importConfig: {
exportConfig: { url: getImportUrl,
name: "部门", success: handleSuccess
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
})
const [registerTable, {reload}, {rowSelection, selectedRowKeys}] = tableContext
//
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
reload();
}
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: selectedRowKeys.value}, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, },
// { })
// label: '',
// //auth: 'user:changepwd', const [registerTable, {reload}, {rowSelection, selectedRowKeys}] = tableContext
// onClick: handleChangePassword.bind(null, record.username),
// }, //
{ const superQueryConfig = reactive(superQuerySchema);
label: '驳回',
ifShow: record.status == 1, /**
popConfirm: { * 高级查询事件
title: '确定驳回吗?', */
confirm: handleFrozen.bind(null, record, 0), function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
reload();
}
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: selectedRowKeys.value}, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, },
}, // {
{ // label: '',
label: '通过', // //auth: 'user:changepwd',
ifShow: record.status == 0, // onClick: handleChangePassword.bind(null, record.username),
popConfirm: { // },
title: '确定通过吗?', {
confirm: handleFrozen.bind(null, record, 1), label: '驳回',
ifShow: userStore.getUserInfo.roleCode !='faren_admin' && record.status == 1,
popConfirm: {
title: '确定驳回吗?',
confirm: handleFrozen.bind(null, record, 0),
},
}, },
}, {
{ label: '通过',
label: '删除', ifShow: userStore.getUserInfo.roleCode !='faren_admin' && record.status == 0,
popConfirm: { popConfirm: {
title: '是否确认删除', title: '确定通过吗?',
confirm: handleDelete.bind(null, record), confirm: handleFrozen.bind(null, record, 1),
},
}, },
}, {
// { label: '删除',
// label: '', ifShow: userStore.getUserInfo.roleCode !='faren_admin',
// onClick: handleAgentSettings.bind(null, record.username), popConfirm: {
// }, title: '是否确认删除',
]; confirm: handleDelete.bind(null, record),
} },
/**
* 冻结解冻
*/
async function handleFrozen(record, status) {
if ('admin' == record.username) {
createMessage.warning('管理员账号不允许此操作!');
return;
}
await frozenBatch({ids: record.id, status: status}, reload);
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
}, },
auth: 'departtest:depart1012:delete' // {
// label: '',
// onClick: handleAgentSettings.bind(null, record.username),
// },
];
}
/**
* 冻结解冻
*/
async function handleFrozen(record, status) {
if ('admin' == record.username) {
createMessage.warning('管理员账号不允许此操作!');
return;
} }
] await frozenBatch({ids: record.id, status: status}, reload);
} }
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: 'departtest:depart1012:delete'
}
]
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
:deep(.ant-picker), :deep(.ant-input-number) { :deep(.ant-picker), :deep(.ant-input-number) {
width: 100%; width: 100%;
} }
</style> </style>

@ -3,12 +3,12 @@
<div class="j-table-operator" style="width: 100%"> <div class="j-table-operator" style="width: 100%">
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="onAddDepart">新增</a-button> <a-button type="primary" preIcon="ant-design:plus-outlined" @click="onAddDepart">新增</a-button>
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="onAddChildDepart()">添加下级</a-button> <a-button type="primary" preIcon="ant-design:plus-outlined" @click="onAddChildDepart()">添加下级</a-button>
<a-upload name="file" :showUploadList="false" :customRequest="onImportXls"> <!-- <a-upload name="file" :showUploadList="false" :customRequest="onImportXls">
<a-button type="primary" preIcon="ant-design:import-outlined">导入</a-button> <a-button type="primary" preIcon="ant-design:import-outlined">导入</a-button>
</a-upload> </a-upload>-->
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls">导出</a-button> <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls">导出</a-button>
<!--<a-button type="primary" preIcon="ant-design:sync-outlined">同步企微?</a-button> <!-- <a-button type="primary" preIcon="ant-design:sync-outlined">同步企微?</a-button>
<a-button type="primary" preIcon="ant-design:sync-outlined">同步钉钉?</a-button>--> <a-button type="primary" preIcon="ant-design:sync-outlined">同步钉钉?</a-button>-->
<template v-if="checkedKeys.length > 0"> <template v-if="checkedKeys.length > 0">
<a-dropdown> <a-dropdown>
<template #overlay> <template #overlay>
@ -92,10 +92,11 @@
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { useMethods } from '/@/hooks/system/useMethods'; import { useMethods } from '/@/hooks/system/useMethods';
import { Api, deleteBatchDepart, queryDepartTreeSync } from '../depart.api'; import { Api, deleteBatchDepart, queryDepartTreeSync4ZhuGuanBuMen } from '../depart.api';
import { searchByKeywords } from '/@/views/system/departUser/depart.user.api'; import { searchByKeywords } from '/@/views/system/departUser/depart.user.api';
import DepartFormModal from '/@/views/system/depart/components/DepartFormModal.vue'; import DepartFormModal from '/@/views/system/depart/components/DepartFormModal.vue';
import { Popconfirm } from 'ant-design-vue'; import { Popconfirm } from 'ant-design-vue';
import {useUserStore} from "@/store/modules/user";
const prefixCls = inject('prefixCls'); const prefixCls = inject('prefixCls');
const emit = defineEmits(['select', 'rootTreeData']); const emit = defineEmits(['select', 'rootTreeData']);
@ -124,13 +125,16 @@
// modal // modal
const [registerModal, { openModal }] = useModal(); const [registerModal, { openModal }] = useModal();
const userStore = useUserStore();
// //
async function loadRootTreeData() { async function loadRootTreeData() {
try { try {
loading.value = true; loading.value = true;
treeData.value = []; treeData.value = [];
const result = await queryDepartTreeSync(); const result = await queryDepartTreeSync4ZhuGuanBuMen({
parentOrgCode: userStore.getUserInfo.orgCode,
});
if (Array.isArray(result)) { if (Array.isArray(result)) {
treeData.value = result; treeData.value = result;
} }
@ -158,8 +162,9 @@
// //
async function loadChildrenTreeData(treeNode) { async function loadChildrenTreeData(treeNode) {
try { try {
const result = await queryDepartTreeSync({ const result = await queryDepartTreeSync4ZhuGuanBuMen({
pid: treeNode.dataRef.id, // pid: treeNode.dataRef.id,
parentOrgCode: treeNode.dataRef.orgCode,
}); });
if (result.length == 0) { if (result.length == 0) {
treeNode.dataRef.isLeaf = true; treeNode.dataRef.isLeaf = true;

@ -6,6 +6,7 @@ const { createConfirm } = useMessage();
export enum Api { export enum Api {
queryDepartTreeSync = '/sys/sysDepart/queryDepartTreeSync', queryDepartTreeSync = '/sys/sysDepart/queryDepartTreeSync',
queryDepartTreeSync4ZhuGuanBuMen = '/sys/sysDepart/queryDepartTreeSync4ZhuGuanBuMen',
save = '/sys/sysDepart/add', save = '/sys/sysDepart/add',
edit = '/sys/sysDepart/edit', edit = '/sys/sysDepart/edit',
delete = '/sys/sysDepart/delete', delete = '/sys/sysDepart/delete',
@ -31,6 +32,9 @@ export enum Api {
*/ */
export const queryDepartTreeSync = (params?) => defHttp.get({ url: Api.queryDepartTreeSync, params }); export const queryDepartTreeSync = (params?) => defHttp.get({ url: Api.queryDepartTreeSync, params });
// add by zhc 11.09
export const queryDepartTreeSync4ZhuGuanBuMen = (params?) => defHttp.get({ url: Api.queryDepartTreeSync4ZhuGuanBuMen, params });
/** /**
* 保存或者更新部门角色 * 保存或者更新部门角色
*/ */

@ -81,10 +81,13 @@ export function useBasicFormSchema() {
// //
export const orgCategoryOptions = { export const orgCategoryOptions = {
// //
root: [{ value: '1', label: '市直' }], // root: [{ value: '1', label: '' }],
root: [{ value: '1', label: '管理单位' }],
// //
child: [ child: [
{ value: '2', label: '市直' }, // { value: '2', label: '' },
{ value: '3', label: '县区' }, { value: '2', label: '直属法人单位' },
// { value: '3', label: '' },
{ value: '3', label: '县区法人单位' },
], ],
}; };

@ -163,11 +163,14 @@ export function useBaseInfoForm(treeData: Ref<any[]>) {
label: '机构类型', label: '机构类型',
render(val) { render(val) {
if (val === '1') { if (val === '1') {
return '市直'; // return '';
return '管理单位';
} else if (val === '2') { } else if (val === '2') {
return '市直'; // return '';
return '直属法人单位';
} else if (val === '3') { } else if (val === '3') {
return '县区'; // return '';
return '县区法人单位';
} }
return val; return val;
}, },

@ -0,0 +1,42 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="修改密码" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" name="PassWordModal" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formPasswordSchema } from './user.data';
import { changePassword } from './user.api';
// Emits
const emit = defineEmits(['success', 'register']);
//
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
schemas: formPasswordSchema,
showActionButtonGroup: false,
});
//
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//
await resetFields();
setModalProps({ confirmLoading: false });
//
await setFieldsValue({ ...data });
});
//
async function handleSubmit() {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
//
await changePassword(values);
//
closeModal();
//
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>

@ -0,0 +1,45 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :width="800" title="用户代理" @ok="handleSubmit" destroyOnClose>
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formAgentSchema } from './user.data';
import { getUserAgent, saveOrUpdateAgent } from './user.api';
// Emits
const emit = defineEmits(['success', 'register']);
//
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
schemas: formAgentSchema,
showActionButtonGroup: false,
});
//
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//
await resetFields();
setModalProps({ confirmLoading: false });
//
const res = await getUserAgent({ userName: data.userName });
data = res.result ? res.result : data;
//
await setFieldsValue({ ...data });
});
//
async function handleSubmit() {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
//
await saveOrUpdateAgent(values);
//
closeModal();
//
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>

@ -0,0 +1,178 @@
<template>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
:title="getTitle"
:width="adaptiveWidth"
@ok="handleSubmit"
:showFooter="showFooter"
destroyOnClose
>
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
<script lang="ts" setup>
import { defineComponent, ref, computed, unref, useAttrs } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from './user.data';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { saveOrUpdateUser, getUserRoles, getUserDepartList, getAllRolesListNoByTenant, getAllRolesList } from './user.api';
import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth';
import { getTenantId } from "/@/utils/auth";
// Emits
const emit = defineEmits(['success', 'register']);
const attrs = useAttrs();
const isUpdate = ref(true);
const rowId = ref('');
const departOptions = ref([]);
let isFormDepartUser = false;
//
const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({
labelWidth: 90,
schemas: formSchema,
showActionButtonGroup: false,
});
// TODO [VUEN-527] https://www.teambition.com/task/6239beb894b358003fe93626
const showFooter = ref(true);
//
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
await resetFields();
showFooter.value = data?.showFooter ?? true;
setDrawerProps({ confirmLoading: false, showFooter: showFooter.value });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
rowId.value = data.record.id;
//
if (data.record.relTenantIds && !Array.isArray(data.record.relTenantIds)) {
data.record.relTenantIds = data.record.relTenantIds.split(',');
} else {
//issues/I56C5I
//data.record.relTenantIds = [];
}
////try catch
try {
const userRoles = await getUserRoles({ userid: data.record.id });
if (userRoles && userRoles.length > 0) {
data.record.selectedroles = userRoles;
}
} catch (error) {}
///
const userDepart = await getUserDepartList({ userId: data.record.id });
if (userDepart && userDepart.length > 0) {
data.record.selecteddeparts = userDepart;
let selectDepartKeys = Array.from(userDepart, ({ key }) => key);
data.record.selecteddeparts = selectDepartKeys.join(',');
departOptions.value = userDepart.map((item) => {
return { label: item.title, value: item.key };
});
}
///
data.record.departIds && !Array.isArray(data.record.departIds) && (data.record.departIds = data.record.departIds.split(','));
//update-begin---author:zyf Date:20211210 for------------
//update-begin---author:liusq Date:20231008 for[issues/772]------------
data.record.departIds = (!data.record.departIds || data.record.departIds == '') ? [] : data.record.departIds;
//update-end-----author:liusq Date:20231008 for[issues/772]------------
//update-begin---author:zyf Date:20211210 for------------
}
//()
data.selectedroles && (await setFieldsValue({ selectedroles: data.selectedroles }));
// -update-begin--author:liaozhiyang---date:20240702---forTV360X-1737updateFromPage:"deptUsers"
isFormDepartUser = data?.departDisabled === true ? true : false;
// -update-end--author:liaozhiyang---date:20240702---forTV360X-1737updateFromPage:"deptUsers"
////
updateSchema([
{
field: 'password',
// QQYUN-8324
ifShow: !unref(isUpdate),
},
{
field: 'confirmPassword',
ifShow: !unref(isUpdate),
},
{
field: 'selectedroles',
show: !data.isRole,
},
{
field: 'departIds',
componentProps: { options: departOptions },
},
{
field: 'selecteddeparts',
show: !data?.departDisabled,
},
{
field: 'selectedroles',
show: !data?.departDisabled,
//update-begin---author:wangshuai ---date:20230424 forissues/4844------------
//
componentProps:{
api: data.tenantSaas?getAllRolesList:getAllRolesListNoByTenant
}
//update-end---author:wangshuai ---date:20230424 forissues/4844------------
},
//update-begin---author:wangshuai ---date:20230522 forissues/4935------------
{
field: 'relTenantIds',
componentProps:{
disabled: !!data.tenantSaas,
},
},
//update-end---author:wangshuai ---date:20230522 forissues/4935------------
]);
//update-begin---author:wangshuai ---date:20230522 forissues/4935------------
if(!unref(isUpdate) && data.tenantSaas){
await setFieldsValue({ relTenantIds: getTenantId().toString() })
}
//update-end---author:wangshuai ---date:20230522 forissues/4935------------
//
if (typeof data.record === 'object') {
setFieldsValue({
...data.record,
});
}
//
//update-begin-author:taoyan date:2022-5-24 for: VUEN-1117issue0523
setProps({ disabled: !showFooter.value });
//update-end-author:taoyan date:2022-5-24 for: VUEN-1117issue0523
});
//
const getTitle = computed(() => {
// update-begin--author:liaozhiyang---date:20240306---forQQYUN-8389title
if (!unref(isUpdate)) {
return '新增用户';
} else {
return unref(showFooter) ? '编辑用户' : '用户详情';
}
// update-end--author:liaozhiyang---date:20240306---forQQYUN-8389title
});
const { adaptiveWidth } = useDrawerAdaptiveWidth();
//
async function handleSubmit() {
try {
let values = await validate();
setDrawerProps({ confirmLoading: true });
values.userIdentity === 1 && (values.departIds = '');
let isUpdateVal = unref(isUpdate);
// -update-begin--author:liaozhiyang---date:20240702---forTV360X-1737updateFromPage:"deptUsers"
let params = values;
if (isFormDepartUser) {
params = { ...params, updateFromPage: 'deptUsers' };
}
// -update-end--author:liaozhiyang---date:20240702---forTV360X-1737updateFromPage:"deptUsers"
//
await saveOrUpdateUser(params, isUpdateVal);
//
closeDrawer();
//
emit('success',{isUpdateVal ,values});
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>

@ -0,0 +1,81 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :width="800" title="离职交接" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup name="user-quit-agent-modal">
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formQuitAgentSchema } from './user.data';
import { getUserAgent, userQuitAgent } from './user.api';
import dayjs from 'dayjs';
// Emits
const emit = defineEmits(['success', 'register']);
//
const [registerForm, { resetFields, setFieldsValue, validate, clearValidate, updateSchema }] = useForm({
schemas: formQuitAgentSchema,
showActionButtonGroup: false,
});
//
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//
await resetFields();
setModalProps({ confirmLoading: true });
let userId = data.userId;
//
const res = await getUserAgent({ userName: data.userName });
data = res.result ? res.result : data;
let date = new Date();
if (!data.startTime) {
data.startTime = dayjs(date).format('YYYY-MM-DD HH:mm:ss');
}
if (!data.endTime) {
data.endTime = getYear(date);
}
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
await updateSchema(
[{
field:'agentUserName',
componentProps:{
excludeUserIdList:[userId]
}
}]
)
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
//
await setFieldsValue({ ...data });
setModalProps({ confirmLoading: false });
});
//
async function handleSubmit() {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
//
await userQuitAgent(values);
//
closeModal();
//
emit('success',values.userName);
} finally {
setModalProps({ confirmLoading: false });
}
}
/**
* 获取后30年
*/
function getYear(date) {
//update-begin---author:wangshuai ---date:20221207 for[QQYUN-3285] ------------
//
let y = date.getFullYear() + 30;
let m = dayjs(date).format('MM');
let d = dayjs(date).format('DD');
let hour = dayjs(date).format('HH:mm:ss');
console.log('年月日', y + '-' + m + '-' + d);
return dayjs(y + '-' + m + '-' + d + ' ' + hour).format('YYYY-MM-DD HH:mm:ss');
//update-end---author:wangshuai ---date:20221207 for[QQYUN-3285] --------------
}
</script>

@ -0,0 +1,110 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="离职人员信息" :showOkBtn="false" width="1000px" destroyOnClose>
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleRevert">
<Icon icon="ant-design:redo-outlined"></Icon>
批量取消
</a-menu-item>
</a-menu>
</template>
<a-button
>批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</BasicModal>
</template>
<script lang="ts" setup name="user-quit-modal">
import { ref, toRaw, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { recycleColumns } from './user.data';
import { getQuitList, putCancelQuit, deleteRecycleBin } from './user.api';
import { useMessage } from '/@/hooks/web/useMessage';
import { useListPage } from '/@/hooks/system/useListPage';
import { Modal } from 'ant-design-vue';
import { defHttp } from '/@/utils/http/axios';
const { createConfirm } = useMessage();
// Emits
const emit = defineEmits(['success', 'register']);
const checkedKeys = ref<Array<string | number>>([]);
const [registerModal] = useModalInner(() => {
checkedKeys.value = [];
});
//table
const { prefixCls, tableContext } = useListPage({
tableProps: {
api: getQuitList,
columns: recycleColumns,
rowKey: 'id',
canResize: false,
useSearchForm: false,
actionColumn: {
width: 120,
},
},
});
//table
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
/**
* 取消离职事件
* @param record
*/
async function handleCancelQuit(record) {
await putCancelQuit({ userIds: record.id, usernames: record.username }, reload);
emit('success');
}
/**
* 批量取消离职事件
*/
function batchHandleRevert() {
Modal.confirm({
title: '取消离职',
content: '取消离职交接人也会清空',
okText: '确认',
cancelText: '取消',
onOk: () => {
let rowValue = selectedRows.value;
let rowData: any = [];
for (const value of rowValue) {
rowData.push(value.username);
}
handleCancelQuit({ id: toRaw(unref(selectedRowKeys)).join(','), username: rowData.join(',') });
},
});
}
//
function getTableAction(record) {
return [
{
label: '取消离职',
icon: 'ant-design:redo-outlined',
popConfirm: {
title: '是否取消离职,取消离职交接人也会清空',
confirm: handleCancelQuit.bind(null, record),
},
},
];
}
</script>
<style scoped lang="less">
:deep(.ant-popover-inner-content){
width: 185px !important;
}
</style>

@ -0,0 +1,166 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="用户回收站" :showOkBtn="false" width="1000px" destroyOnClose @fullScreen="handleFullScreen">
<BasicTable @register="registerTable" :rowSelection="rowSelection" :scroll="scroll">
<!--插槽:table标题-->
<template #tableTitle>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
批量删除
</a-menu-item>
<a-menu-item key="1" @click="batchHandleRevert">
<Icon icon="ant-design:redo-outlined"></Icon>
批量还原
</a-menu-item>
</a-menu>
</template>
<a-button
>批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="getTableAction(record)" />
</template>
</template>
</BasicTable>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, toRaw, unref, watch } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { recycleColumns } from './user.data';
import { getRecycleBinList, putRecycleBin, deleteRecycleBin } from './user.api';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
// Emits
const emit = defineEmits(['success', 'register']);
const checkedKeys = ref<Array<string | number>>([]);
const [registerModal] = useModalInner(() => {
checkedKeys.value = [];
});
const scroll = ref({ y: 0 });
//table
const [registerTable, { reload }] = useTable({
api: getRecycleBinList,
columns: recycleColumns,
rowKey: 'id',
striped: true,
useSearchForm: false,
showTableSetting: false,
clickToRowSelect: false,
bordered: true,
showIndexColumn: false,
pagination: true,
tableSetting: { fullScreen: true },
canResize: false,
actionColumn: {
width: 150,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
fixed: undefined,
},
});
// update-begin--author:liaozhiyang---date:20240704---forTV360X-1657
const handleFullScreen = (maximize) => {
setTableHeight(maximize);
};
const setTableHeight = (maximize) => {
const clientHeight = document.documentElement.clientHeight;
scroll.value = {
y: clientHeight - (maximize ? 300 : 500),
};
};
setTableHeight(false);
watch(
checkedKeys,
(newValue, oldValue) => {
if (checkedKeys.value.length && oldValue.length == 0) {
scroll.value = {
y: scroll.value.y - 50,
};
} else if (checkedKeys.value.length == 0 && oldValue.length) {
scroll.value = {
y: scroll.value.y + 50,
};
}
},
{ deep: true }
);
// update-end--author:liaozhiyang---date:20240704---forTV360X-1657
/**
* 选择列配置
*/
const rowSelection = {
type: 'checkbox',
columnWidth: 50,
selectedRowKeys: checkedKeys,
onChange: onSelectChange,
};
/**
* 选择事件
*/
function onSelectChange(selectedRowKeys: (string | number)[]) {
checkedKeys.value = selectedRowKeys;
}
/**
* 还原事件
*/
async function handleRevert(record) {
await putRecycleBin({ userIds: record.id }, reload);
emit('success');
}
/**
* 批量还原事件
*/
function batchHandleRevert() {
handleRevert({ id: toRaw(unref(checkedKeys)).join(',') });
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteRecycleBin({ userIds: record.id }, reload);
}
/**
* 批量删除事件
*/
function batchHandleDelete() {
createConfirm({
iconType: 'warning',
title: '删除',
content: '确定要永久删除吗?删除后将不可恢复!',
onOk: () => handleDelete({ id: toRaw(unref(checkedKeys)).join(',') }),
onCancel() {},
});
}
//
function getTableAction(record) {
return [
{
label: '取回',
icon: 'ant-design:redo-outlined',
popConfirm: {
title: '是否确认还原',
confirm: handleRevert.bind(null, record),
},
},
{
label: '彻底删除',
icon: 'ant-design:scissor-outlined',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
},
},
];
}
</script>

@ -0,0 +1,301 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls" :disabled="isDisabledAuth('system:user:export')"> 导出</a-button>
<!--
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
-->
<a-button type="primary" @click="openModal(true, {})" preIcon="ant-design:hdd-outlined"> 回收站</a-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
<a-menu-item key="2" @click="batchFrozen(2)">
<Icon icon="ant-design:lock-outlined"></Icon>
冻结
</a-menu-item>
<a-menu-item key="3" @click="batchFrozen(1)">
<Icon icon="ant-design:unlock-outlined"></Icon>
解冻
</a-menu-item>
</a-menu>
</template>
<a-button
>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
</BasicTable>
<!--用户抽屉-->
<UserDrawer @register="registerDrawer" @success="handleSuccess" />
<!--修改密码-->
<PasswordModal @register="registerPasswordModal" @success="reload" />
<!--用户代理-->
<UserAgentModal @register="registerAgentModal" @success="reload" />
<!--回收站-->
<UserRecycleBinModal @register="registerModal" @success="reload" />
<!-- 离职受理人弹窗 -->
<UserQuitAgentModal @register="registerQuitAgentModal" @success="reload" />
<!-- 离职人员列弹窗 -->
<UserQuitModal @register="registerQuitModal" @success="reload" />
</div>
</template>
<script lang="ts" name="system-user" setup>
//ts
import { ref, computed, unref } from 'vue';
import { BasicTable, TableAction, ActionItem } from '/@/components/Table';
import UserDrawer from './UserDrawer.vue';
import UserRecycleBinModal from './UserRecycleBinModal.vue';
import PasswordModal from './PasswordModal.vue';
import UserAgentModal from './UserAgentModal.vue';
import JThirdAppButton from '/@/components/jeecg/thirdApp/JThirdAppButton.vue';
import UserQuitAgentModal from './UserQuitAgentModal.vue';
import UserQuitModal from './UserQuitModal.vue';
import { useDrawer } from '/@/components/Drawer';
import { useListPage } from '/@/hooks/system/useListPage';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { columns, searchFormSchema } from './user.data';
import { listNoCareTenant, deleteUser, batchDeleteUser, getImportUrl, getExportUrl, frozenBatch } from './user.api';
import {usePermission} from "/@/hooks/web/usePermission";
const { createMessage, createConfirm } = useMessage();
const { isDisabledAuth } = usePermission();
//drawer
const [registerDrawer, { openDrawer }] = useDrawer();
//model
const [registerModal, { openModal }] = useModal();
//model
const [registerPasswordModal, { openModal: openPasswordModal }] = useModal();
//model
const [registerAgentModal, { openModal: openAgentModal }] = useModal();
//model
const [registerQuitAgentModal, { openModal: openQuitAgentModal }] = useModal();
//model
const [registerQuitModal, { openModal: openQuitModal }] = useModal();
//
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
designScope: 'user-list',
tableProps: {
title: '用户列表',
api: listNoCareTenant,
columns: columns,
size: 'small',
formConfig: {
// labelWidth: 200,
schemas: searchFormSchema,
},
actionColumn: {
width: 120,
},
beforeFetch: (params) => {
return Object.assign({ column: 'createTime', order: 'desc' }, params);
},
},
exportConfig: {
name: '用户列表',
url: getExportUrl,
},
importConfig: {
url: getImportUrl,
},
});
//table
const [registerTable, { reload, updateTableDataRecord }, { rowSelection, selectedRows, selectedRowKeys }] = tableContext;
/**
* 新增事件
*/
function handleCreate() {
openDrawer(true, {
isUpdate: false,
showFooter: true,
tenantSaas: false,
});
}
/**
* 编辑事件
*/
async function handleEdit(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: true,
tenantSaas: false,
});
}
/**
* 详情
*/
async function handleDetail(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: false,
tenantSaas: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
if ('admin' == record.username) {
createMessage.warning('管理员账号不允许此操作!');
return;
}
await deleteUser({ id: record.id }, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
let hasAdmin = unref(selectedRows).filter((item) => item.username == 'admin');
if (unref(hasAdmin).length > 0) {
createMessage.warning('管理员账号不允许此操作!');
return;
}
await batchDeleteUser({ ids: selectedRowKeys.value }, () => {
selectedRowKeys.value = [];
reload();
});
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 打开修改密码弹窗
*/
function handleChangePassword(username) {
openPasswordModal(true, { username });
}
/**
* 打开代理人弹窗
*/
function handleAgentSettings(userName) {
openAgentModal(true, { userName });
}
/**
* 冻结解冻
*/
async function handleFrozen(record, status) {
if ('admin' == record.username) {
createMessage.warning('管理员账号不允许此操作!');
return;
}
await frozenBatch({ ids: record.id, status: status }, reload);
}
/**
* 批量冻结解冻
*/
function batchFrozen(status) {
let hasAdmin = selectedRows.value.filter((item) => item.username == 'admin');
if (unref(hasAdmin).length > 0) {
createMessage.warning('管理员账号不允许此操作!');
return;
}
createConfirm({
iconType: 'warning',
title: '确认操作',
content: '是否' + (status == 1 ? '解冻' : '冻结') + '选中账号?',
onOk: async () => {
await frozenBatch({ ids: unref(selectedRowKeys).join(','), status: status }, reload);
},
});
}
/**
*同步钉钉和微信回调
*/
function onSyncFinally({ isToLocal }) {
//
if (isToLocal) {
reload();
}
}
/**
* 操作栏
*/
function getTableAction(record): ActionItem[] {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
// ifShow: () => hasPermission('system:user:edit'),
},
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record): ActionItem[] {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '密码',
//auth: 'user:changepwd',
onClick: handleChangePassword.bind(null, record.username),
},
{
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
},
},
{
label: '冻结',
ifShow: record.status == 1,
popConfirm: {
title: '确定冻结吗?',
confirm: handleFrozen.bind(null, record, 2),
},
},
{
label: '解冻',
ifShow: record.status == 2,
popConfirm: {
title: '确定解冻吗?',
confirm: handleFrozen.bind(null, record, 1),
},
},
{
label: '代理人',
onClick: handleAgentSettings.bind(null, record.username),
},
];
}
/**
* 离职
* @param userName
*/
function handleQuit(userName) {
//
openQuitAgentModal(true, { userName });
}
</script>
<style scoped></style>

@ -0,0 +1,254 @@
import { defHttp } from '/@/utils/http/axios';
import { Modal } from 'ant-design-vue';
import { isObject } from '/@/utils/is';
enum Api {
listNoCareTenant = '/sys/user/listAll',
// add by zhc 11.08
listByRollCode = '/sys/user/listByRollCode',
list = '/sys/user/list',
save = '/sys/user/add',
edit = '/sys/user/edit',
agentSave = '/sys/sysUserAgent/add',
agentEdit = '/sys/sysUserAgent/edit',
getUserRole = '/sys/user/queryUserRole',
duplicateCheck = '/sys/duplicate/check',
deleteUser = '/sys/user/delete',
deleteBatch = '/sys/user/deleteBatch',
importExcel = '/sys/user/importExcel',
exportXls = '/sys/user/exportXls',
recycleBinList = '/sys/user/recycleBin',
putRecycleBin = '/sys/user/putRecycleBin',
deleteRecycleBin = '/sys/user/deleteRecycleBin',
allRolesList = '/sys/role/queryall',
allRolesListNoByTenant = '/sys/role/queryallNoByTenant',
allTenantList = '/sys/tenant/queryList',
allPostList = '/sys/position/list',
userDepartList = '/sys/user/userDepartList',
changePassword = '/sys/user/changePassword',
frozenBatch = '/sys/user/frozenBatch',
getUserAgent = '/sys/sysUserAgent/queryByUserName',
userQuitAgent = '/sys/user/userQuitAgent',
getQuitList = '/sys/user/getQuitList',
putCancelQuit = '/sys/user/putCancelQuit',
updateUserTenantStatus='/sys/tenant/updateUserTenantStatus',
getUserTenantPageList='/sys/tenant/getUserTenantPageList',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口(查询用户通过租户隔离)
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* 列表接口(查询全部用户不通过租户隔离)
* @param params
*/
export const listNoCareTenant = (params) => defHttp.get({ url: Api.listByRollCode, params });
/**
* 用户角色接口
* @param params
*/
export const getUserRoles = (params) => defHttp.get({ url: Api.getUserRole, params }, { errorMessageMode: 'none' });
/**
* 删除用户
*/
export const deleteUser = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteUser, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
* 批量删除用户
* @param params
*/
export const batchDeleteUser = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
* 保存或者更新用户
* @param params
*/
export const saveOrUpdateUser = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
/**
* 唯一校验
* @param params
*/
export const duplicateCheck = (params) => defHttp.get({ url: Api.duplicateCheck, params }, { isTransformResponse: false });
/**
* 20231215
* liaozhiyang
* 唯一校验 延迟防抖
* @param params
*/
const timer = {};
export const duplicateCheckDelay = (params) => {
return new Promise((resove, rejected) => {
// -update-begin--author:liaozhiyang---date:20240619---forTV360X-1380使duplicateCheckDelayvalidatepromise
let key;
if (isObject(params)) {
key = `${params.tableName}_${params.fieldName}`;
} else {
key = params;
}
clearTimeout(timer[key]);
// -update-end--author:liaozhiyang---date:20240619---forTV360X-1380使duplicateCheckDelayvalidatepromise
timer[key] = setTimeout(() => {
defHttp
.get({ url: Api.duplicateCheck, params }, { isTransformResponse: false })
.then((res: any) => {
resove(res as any);
})
.catch((error) => {
rejected(error);
});
delete timer[key];
}, 500);
});
};
/**
* 获取全部角色租户隔离
* @param params
*/
export const getAllRolesList = (params) => defHttp.get({ url: Api.allRolesList, params });
/**
* 获取全部角色不租户隔离
* @param params
*/
export const getAllRolesListNoByTenant = (params) => defHttp.get({ url: Api.allRolesListNoByTenant, params });
/**
* 获取全部租户
*/
export const getAllTenantList = (params) => defHttp.get({ url: Api.allTenantList, params });
/**
* 获取指定用户负责部门
*/
export const getUserDepartList = (params) => defHttp.get({ url: Api.userDepartList, params }, { successMessageMode: 'none' });
/**
* 获取全部职务
*/
export const getAllPostList = (params) => {
return new Promise((resolve) => {
defHttp.get({ url: Api.allPostList, params }).then((res) => {
resolve(res.records);
});
});
};
/**
* 回收站列表
* @param params
*/
export const getRecycleBinList = (params) => defHttp.get({ url: Api.recycleBinList, params });
/**
* 回收站还原
* @param params
*/
export const putRecycleBin = (params, handleSuccess) => {
return defHttp.put({ url: Api.putRecycleBin, params }).then(() => {
handleSuccess();
});
};
/**
* 回收站删除
* @param params
*/
export const deleteRecycleBin = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteRecycleBin, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
* 修改密码
* @param params
*/
export const changePassword = (params) => {
return defHttp.put({ url: Api.changePassword, params });
};
/**
* 冻结解冻
* @param params
*/
export const frozenBatch = (params, handleSuccess) => {
return defHttp.put({ url: Api.frozenBatch, params }).then(() => {
handleSuccess();
});
};
/**
* 获取用户代理
* @param params
*/
export const getUserAgent = (params) => defHttp.get({ url: Api.getUserAgent, params }, { isTransformResponse: false });
/**
* 保存或者更新用户代理
* @param params
*/
export const saveOrUpdateAgent = (params) => {
let url = params.id ? Api.agentEdit : Api.agentSave;
return defHttp.post({ url: url, params });
};
/**
* 用户离职(新增代理人和用户状态变更操作)
* @param params
*/
export const userQuitAgent = (params) => {
return defHttp.put({ url: Api.userQuitAgent, params });
};
/**
* 用户离职列表
* @param params
*/
export const getQuitList = (params) => {
return defHttp.get({ url: Api.getQuitList, params });
};
/**
* 取消离职
* @param params
*/
export const putCancelQuit = (params, handleSuccess) => {
return defHttp.put({ url: Api.putCancelQuit, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
* 待审批获取列表数据
*/
export const getUserTenantPageList = (params) => {
return defHttp.get({ url: Api.getUserTenantPageList, params });
};
/**
* 更新租户状态
* @param params
*/
export const updateUserTenantStatus = (params) => {
return defHttp.put({ url: Api.updateUserTenantStatus, params }, { joinParamsToUrl: true, isTransformResponse: false });
};

@ -0,0 +1,569 @@
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { getAllRolesListNoByTenant, getAllTenantList } from './user.api';
import { rules } from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
export const columns: BasicColumn[] = [
{
title: '用户账号',
dataIndex: 'username',
width: 120,
},
{
title: '用户姓名',
dataIndex: 'realname',
width: 100,
},
{
title: '头像',
dataIndex: 'avatar',
width: 120,
customRender: render.renderAvatar,
},
{
title: '性别',
dataIndex: 'sex',
width: 80,
sorter: true,
customRender: ({ text }) => {
return render.renderDict(text, 'sex');
},
},
/*{
title: '生日',
dataIndex: 'birthday',
width: 100,
},*/
{
title: '手机号',
dataIndex: 'phone',
width: 100,
},
{
title: '部门',
width: 150,
dataIndex: 'orgCodeTxt',
},
/*{
title: '负责部门',
width: 150,
dataIndex: 'departIds_dictText',
},*/
{
title: '状态',
dataIndex: 'status_dictText',
width: 80,
},
];
export const recycleColumns: BasicColumn[] = [
{
title: '用户账号',
dataIndex: 'username',
width: 100,
},
{
title: '用户姓名',
dataIndex: 'realname',
width: 100,
},
{
title: '头像',
dataIndex: 'avatar',
width: 80,
customRender: render.renderAvatar,
},
{
title: '性别',
dataIndex: 'sex',
width: 80,
sorter: true,
customRender: ({ text }) => {
return render.renderDict(text, 'sex');
},
},
];
export const searchFormSchema: FormSchema[] = [
{
label: '账号',
field: 'username',
component: 'JInput',
//colProps: { span: 6 },
},
{
label: '名字',
field: 'realname',
component: 'JInput',
//colProps: { span: 6 },
},
{
label: '性别',
field: 'sex',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'sex',
placeholder: '请选择性别',
stringToNumber: true,
},
//colProps: { span: 6 },
},
{
label: '手机号码',
field: 'phone',
component: 'Input',
//colProps: { span: 6 },
},
{
label: '用户状态',
field: 'status',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'user_status',
placeholder: '请选择状态',
stringToNumber: true,
},
//colProps: { span: 6 },
},
];
export const formSchema: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
{
label: '用户账号',
field: 'username',
component: 'Input',
required: true,
dynamicDisabled: ({ values }) => {
return !!values.id;
},
dynamicRules: ({ model, schema }) => rules.duplicateCheckRule('sys_user', 'username', model, schema, true),
},
{
label: '登录密码',
field: 'password',
component: 'StrengthMeter',
componentProps:{
autocomplete: 'new-password',
},
rules: [
{
required: true,
message: '请输入登录密码',
},
{
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
message: '密码由8位数字、大小写字母和特殊符号组成!',
},
],
},
{
label: '确认密码',
field: 'confirmPassword',
component: 'InputPassword',
dynamicRules: ({ values }) => rules.confirmPassword(values, true),
},
{
label: '用户姓名',
field: 'realname',
required: true,
component: 'Input',
},
/*{
label: '工号',
field: 'workNo',
required: true,
component: 'Input',
dynamicRules: ({ model, schema }) => rules.duplicateCheckRule('sys_user', 'work_no', model, schema, true),
},
{
label: '职务',
field: 'post',
required: false,
component: 'JSelectPosition',
componentProps: {
labelKey: 'name',
},
},*/
{
label: '角色',
field: 'selectedroles',
component: 'ApiSelect',
componentProps: {
mode: 'multiple',
api: getAllRolesListNoByTenant,
labelField: 'roleName',
valueField: 'id',
immediate: false,
},
},
{
label: '所属部门',
field: 'selecteddeparts',
component: 'JSelectDept',
componentProps: ({ formActionType, formModel }) => {
return {
sync: false,
checkStrictly: true,
defaultExpandLevel: 2,
onSelect: (options, values) => {
const { updateSchema } = formActionType;
//
updateSchema([
{
field: 'departIds',
componentProps: { options },
},
]);
//update-begin---author:wangshuai---date:2024-05-11---for:issues/1222---
if(!values){
formModel.departIds = [];
return;
}
//update-end---author:wangshuai---date:2024-05-11---for:issues/1222---
//
formModel.departIds && (formModel.departIds = formModel.departIds.filter((item) => values.value.indexOf(item) > -1));
},
};
},
},
/*{
label: '租户',
field: 'relTenantIds',
component: 'ApiSelect',
componentProps: {
mode: 'multiple',
api: getAllTenantList,
numberToString: true,
labelField: 'name',
valueField: 'id',
immediate: false,
},
},
{
label: '身份',
field: 'userIdentity',
component: 'RadioGroup',
defaultValue: 1,
componentProps: ({ formModel }) => {
return {
options: [
{ label: '普通用户', value: 1, key: '1' },
{ label: '上级', value: 2, key: '2' },
],
onChange: () => {
formModel.userIdentity == 1 && (formModel.departIds = []);
},
};
},
},*/
{
label: '负责部门',
field: 'departIds',
component: 'Select',
componentProps: {
mode: 'multiple',
},
ifShow: ({ values }) => values.userIdentity == 2,
},
{
label: '头像',
field: 'avatar',
component: 'JImageUpload',
componentProps: {
fileMax: 1,
},
},
{
label: '生日',
field: 'birthday',
component: 'DatePicker',
},
{
label: '性别',
field: 'sex',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'sex',
placeholder: '请选择性别',
stringToNumber: true,
},
},
{
label: '邮箱',
field: 'email',
component: 'Input',
required: true,
dynamicRules: ({ model, schema }) => {
return [
{ ...rules.duplicateCheckRule('sys_user', 'email', model, schema, true)[0], trigger: 'blur' },
{ ...rules.rule('email', false)[0], trigger: 'blur' },
];
},
},
{
label: '手机号码',
field: 'phone',
component: 'Input',
required: true,
dynamicRules: ({ model, schema }) => {
return [
{ ...rules.duplicateCheckRule('sys_user', 'phone', model, schema, true)[0], trigger: 'blur' },
{ pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误', trigger: 'blur' },
];
},
},
/* {
label: '座机',
field: 'telephone',
component: 'Input',
rules: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' }],
},
{
label: '工作流引擎',
field: 'activitiSync',
defaultValue: 1,
component: 'JDictSelectTag',
componentProps: {
dictCode: 'activiti_sync',
type: 'radio',
stringToNumber: true,
},
},*/
];
export const formPasswordSchema: FormSchema[] = [
{
label: '用户账号',
field: 'username',
component: 'Input',
componentProps: { readOnly: true },
},
{
label: '登录密码',
field: 'password',
component: 'StrengthMeter',
componentProps: {
placeholder: '请输入登录密码',
},
rules: [
{
required: true,
message: '请输入登录密码',
},
{
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
message: '密码由8位数字、大小写字母和特殊符号组成!',
},
],
},
{
label: '确认密码',
field: 'confirmPassword',
component: 'InputPassword',
dynamicRules: ({ values }) => rules.confirmPassword(values, true),
},
];
export const formAgentSchema: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
{
field: 'userName',
label: '用户名',
component: 'Input',
componentProps: {
readOnly: true,
allowClear: false,
},
},
{
field: 'agentUserName',
label: '代理人用户名',
required: true,
component: 'JSelectUser',
componentProps: {
rowKey: 'username',
labelKey: 'realname',
maxSelectCount: 10,
},
},
{
field: 'startTime',
label: '代理开始时间',
component: 'DatePicker',
required: true,
componentProps: {
showTime: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss',
placeholder: '请选择代理开始时间',
getPopupContainer: () => document.body,
},
},
{
field: 'endTime',
label: '代理结束时间',
component: 'DatePicker',
required: true,
componentProps: {
showTime: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss',
placeholder: '请选择代理结束时间',
getPopupContainer: () => document.body,
},
},
{
field: 'status',
label: '状态',
component: 'JDictSelectTag',
defaultValue: '1',
componentProps: {
dictCode: 'valid_status',
type: 'radioButton',
},
},
];
export const formQuitAgentSchema: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
{
field: 'userName',
label: '用户名',
component: 'Input',
componentProps: {
readOnly: true,
allowClear: false,
},
},
{
field: 'agentUserName',
label: '交接人员',
//required: true,
component: 'JSelectUser',
componentProps: {
rowKey: 'username',
labelKey: 'realname',
maxSelectCount: 1,
},
},
{
field: 'startTime',
label: '交接开始时间',
component: 'DatePicker',
//required: true,
componentProps: {
showTime: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss',
placeholder: '请选择交接开始时间',
getPopupContainer: () => document.body,
},
},
{
field: 'endTime',
label: '交接结束时间',
component: 'DatePicker',
//required: true,
componentProps: {
showTime: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss',
placeholder: '请选择交接结束时间',
getPopupContainer: () => document.body,
},
},
{
field: 'status',
label: '状态',
component: 'JDictSelectTag',
defaultValue: '1',
componentProps: {
dictCode: 'valid_status',
type: 'radioButton',
},
},
];
//
export const userTenantColumns: BasicColumn[] = [
{
title: '用户账号',
dataIndex: 'username',
width: 120,
},
{
title: '用户姓名',
dataIndex: 'realname',
width: 100,
},
{
title: '头像',
dataIndex: 'avatar',
width: 120,
customRender: render.renderAvatar,
},
{
title: '手机号',
dataIndex: 'phone',
width: 100,
},
{
title: '部门',
width: 150,
dataIndex: 'orgCodeTxt',
},
{
title: '状态',
dataIndex: 'status',
width: 80,
customRender: ({ text }) => {
if (text === '1') {
return '正常';
} else if (text === '3') {
return '审批中';
} else {
return '已拒绝';
}
},
},
];
//
export const userTenantFormSchema: FormSchema[] = [
{
label: '账号',
field: 'username',
component: 'Input',
colProps: { span: 6 },
},
{
label: '名字',
field: 'realname',
component: 'Input',
colProps: { span: 6 },
},
{
label: '性别',
field: 'sex',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'sex',
placeholder: '请选择性别',
stringToNumber: true,
},
colProps: { span: 6 },
},
];

@ -0,0 +1,54 @@
<template>
<Description @register="register" class="mt-4" />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Description, DescItem, useDescription } from '/@/components/Description/index';
const mockData = {
username: 'test',
nickName: 'VB',
age: '123',
phone: '15695909xxx',
email: '190848757@qq.com',
addr: '厦门市思明区',
sex: '男',
certy: '3504256199xxxxxxxxx',
tag: 'orange',
};
const schema: DescItem[] = [
{
field: 'username',
label: '用户名',
},
{
field: 'nickName',
label: '昵称',
render: (curVal, data) => {
return `${data.username}-${curVal}`;
},
},
{
field: 'phone',
label: '联系电话',
},
{
field: 'email',
label: '邮箱',
},
{
field: 'addr',
label: '地址',
},
];
export default defineComponent({
components: { Description },
setup() {
const [register] = useDescription({
title: 'useDescription',
data: mockData,
schema: schema,
});
return { mockData, schema, register };
},
});
</script>

@ -40,6 +40,7 @@ export interface UserInfo {
homePath?: string; homePath?: string;
tenantid?: string | number; tenantid?: string | number;
roles: RoleInfo[]; roles: RoleInfo[];
roleCode: string;
orgCode?: string; orgCode?: string;
} }

Loading…
Cancel
Save