diff --git a/jeecgboot-vue3/src/views/system/tenant/TenantUserList.vue b/jeecgboot-vue3/src/views/system/tenant/TenantUserList.vue index d95b7658a..39b2f51d2 100644 --- a/jeecgboot-vue3/src/views/system/tenant/TenantUserList.vue +++ b/jeecgboot-vue3/src/views/system/tenant/TenantUserList.vue @@ -4,10 +4,20 @@ - 新增 + 新增 + + 邀请用户加入 + - 离职信息 + 离职人员 当前登录租户: {{loginTenantName}} + + + @@ -16,12 +26,23 @@ - - + + + + + + + 移除:将用户从当前租户中移除 + 删除:仅可删除当天创建的用户,删除后可在系统用户回收站恢复 + 离职:非租户创建者可进行离职操作,离职员工可在离职人员列表查看 + 交接:租户创建者可进行租户交接,交接后员工信息可在离职人员列表查看 + + + @@ -31,14 +52,13 @@ import { BasicTable, TableAction, ActionItem } from '/@/components/Table'; import UserDrawer from '../user/UserDrawer.vue'; import JThirdAppButton from '/@/components/jeecg/thirdApp/JThirdAppButton.vue'; - import UserQuitAgentModal from '../user/UserQuitAgentModal.vue'; import UserQuitModal from '../user/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/user.data'; - import { list , deleteUser, batchDeleteUser, getImportUrl, getExportUrl, frozenBatch , getUserTenantPageList, updateUserTenantStatus } from '../user/user.api'; + import { list , deleteUser, batchDeleteUser, getImportUrl, getExportUrl, frozenBatch, getUserTenantPageList, updateUserTenantStatus } from '../user/user.api'; // import { usePermission } from '/@/hooks/web/usePermission' // const { hasPermission } = usePermission(); import { userTenantColumns, userTenantFormSchema } from '../user/user.data'; @@ -46,9 +66,11 @@ import UserSelectModal from '/@/components/Form/src/jeecg/components/modal/UserSelectModal.vue'; import { getTenantId } from "/@/utils/auth"; import { changeOwenUserTenant } from "/@/views/system/usersetting/UserSetting.api"; - import { getLoginTenantName } from "/@/views/system/tenant/tenant.api"; + import {getLoginTenantName, invitationUserJoin, leaveTenant} from "/@/views/system/tenant/tenant.api"; import TenantUserDrawer from './components/TenantUserDrawer.vue'; - import { tenantSaasMessage } from "@/utils/common/compUtils"; + import { sameDay, tenantSaasMessage } from "@/utils/common/compUtils"; + import TenantPackAllotModal from './components/TenantPackAllotModal.vue' + import TenantInviteUserModal from "@/views/system/tenant/components/TenantInviteUserModal.vue"; const { createMessage, createConfirm } = useMessage(); @@ -58,8 +80,12 @@ const [registerQuitAgentModal, { openModal: openQuitAgentModal }] = useModal(); //离职用户列表model const [registerQuitModal, { openModal: openQuitModal }] = useModal(); + //分配套餐弹窗 + const [registerPackAllotModal, { openModal: openPackAllotModal }] = useModal(); const userStore = useUserStore(); const createBy = userStore.getUserInfo.username; + //弹窗提示显示 + const tipShow = ref(false); // 列表页面公共参数、方法 const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({ @@ -153,22 +179,23 @@ function getDropDownAction(record): ActionItem[] { return [ { - label: '详情', + label: '查看详情', onClick: handleDetail.bind(null, record), }, { - label: '离职', - //update-begin---author:wangshuai---date:2023-10-25---for:【QQYUN-6822】9.离职交接人选的是自己,完成之后数据没了--- - onClick: handleQuit.bind(null,record.username, record.id), - //update-end---author:wangshuai---date:2023-10-25---for:【QQYUN-6822】9.离职交接人选的是自己,完成之后数据没了--- - //update-begin---author:wangshuai ---date:20230130 for:[QQYUN-3974]租户的创建人 不应该有离职按钮------------ - ifShow: () =>{ - return record.status === '1' && record.username!== record.createBy; - } - //update-end---author:wangshuai ---date:20230130 for:[QQYUN-3974]租户的创建人 不应该有离职按钮------------ + label: '移除用户', + onClick: handleLeave.bind(null, record.id), }, { - label: '交接', + label: '删除用户', + popConfirm: { + title: '是否确认删除该用户', + confirm: handleDeleteUser.bind(null, record), + }, + ifShow: () => record.username!== userStore.getUserInfo?.username && sameDay(record.createTime), + }, + { + label: '变更拥有者', onClick: handleHandover.bind(null, record), ifShow: () =>{ return record.username === record.createBy; @@ -191,19 +218,13 @@ return record.status === '3' && record.createBy === createBy; }, }, + { + label: '用户套餐', + onClick: handleAllotPack.bind(null, record), + } ]; } - /** - * 离职 - * @param userName - * @param userId - */ - function handleQuit(userName, userId) { - //打开离职代理人弹窗 - openQuitAgentModal(true, { userName, userId }); - } - /** * 更新用户租户状态 * @param id @@ -228,6 +249,8 @@ const excludeUserIdList = ref([]); //离职代理人model const [registerUserModal, { openModal: openUserModal }] = useModal(); + //邀请用户加入弹窗 + const [registerSelUserModal, { openModal: userOpenModal }] = useModal(); const handOverUserName = ref(''); /** @@ -277,21 +300,59 @@ loginTenantName.value = await getLoginTenantName(); } //update-end---author:wangshuai ---date:20230710 for:【QQYUN-5723】4、显示当前登录租户------------ + /** - * 离职成功之后需要判断一下是否为当前用户,当前用户需要刷新浏览器 - * @param userName + * 分配套餐 + * + * @param record */ - function handleQuitSuccess(userName) { - //判断如果当前离职的是当前登录用户,需要刷新页面,便将租户id设置成null - let username = userStore.getUserInfo.username; - if (username && userName === username) { - userStore.setTenant(null); - window.location.reload(); - }else{ + function handleAllotPack(record) { + openPackAllotModal(true,{ + record + }) + } + + /** + * 删除用户 + */ + function handleDeleteUser(record) { + deleteUser({ id: record.id }, reload); + } + + /** + * 邀请用户加入租户 + */ + function handleInvitation() { + userOpenModal(true, {}); + } + + /** + * 用户选择回调事件 + * @param username + * @param phone + * @param userSelectId + */ + async function handleInviteUserOk(phone, username) { + let tId = getTenantId(); + if (phone) { + await invitationUserJoin({ ids: tId, phone: phone }); + reload(); + } + if (username) { + await invitationUserJoin({ ids: tId, username: username }); reload(); } } + + /** + * 请离 + * @param id + */ + async function handleLeave(id) { + await leaveTenant({ userIds: id, tenantId: getTenantId() }, reload) + } + onMounted(()=>{ tenantSaasMessage('租户用户') @@ -304,4 +365,11 @@ margin: 5px; font-size: 15px; } + .user-tenant-tip{ + margin: 20px; + background-color: #f8f9fb; + color: #99a1a9; + border-radius: 4px; + padding: 12px; + } diff --git a/jeecgboot-vue3/src/views/system/tenant/components/TenantPackAllotModal.vue b/jeecgboot-vue3/src/views/system/tenant/components/TenantPackAllotModal.vue new file mode 100644 index 000000000..01daf7bb2 --- /dev/null +++ b/jeecgboot-vue3/src/views/system/tenant/components/TenantPackAllotModal.vue @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + diff --git a/jeecgboot-vue3/src/views/system/tenant/components/TenantUserRightList.vue b/jeecgboot-vue3/src/views/system/tenant/components/TenantUserRightList.vue new file mode 100644 index 000000000..e61d23ed2 --- /dev/null +++ b/jeecgboot-vue3/src/views/system/tenant/components/TenantUserRightList.vue @@ -0,0 +1,181 @@ + + + + + {{ getName(text) }} + + + + + {{ getName(text) }} + + + + 邀请成员 + 关闭 + + + + + + + + + + + + diff --git a/jeecgboot-vue3/src/views/system/tenant/my/MyTenantDetail.vue b/jeecgboot-vue3/src/views/system/tenant/my/MyTenantDetail.vue new file mode 100644 index 000000000..6aea5817a --- /dev/null +++ b/jeecgboot-vue3/src/views/system/tenant/my/MyTenantDetail.vue @@ -0,0 +1,296 @@ + + + + + + 组织信息 + + + + + + 组织LOGO + + + + + + 组织名称 + {{ formState.name }} + + + 组织门牌号 + + + {{ formState.houseNumber }} + + + + + 组织编号(ID) + + + {{ formState.id }} + + + + + + 所在地 + {{ formState.companyAddress_dictText }} + + + 所在行业 + {{ formState.trade_dictText }} + + + 工作地点 + {{ formState.workPlace }} + + + + + + + + + + diff --git a/jeecgboot-vue3/src/views/system/tenant/my/MyTenantList.vue b/jeecgboot-vue3/src/views/system/tenant/my/MyTenantList.vue index b4b8c1612..1a526f34b 100644 --- a/jeecgboot-vue3/src/views/system/tenant/my/MyTenantList.vue +++ b/jeecgboot-vue3/src/views/system/tenant/my/MyTenantList.vue @@ -10,14 +10,14 @@ :disabled="selectedRowKeys.length === 0" >邀请用户加入 - 套餐 + >--> diff --git a/jeecgboot-vue3/src/views/system/tenant/pack/TenantCurrentPackList.vue b/jeecgboot-vue3/src/views/system/tenant/pack/TenantCurrentPackList.vue new file mode 100644 index 000000000..9965022f7 --- /dev/null +++ b/jeecgboot-vue3/src/views/system/tenant/pack/TenantCurrentPackList.vue @@ -0,0 +1,188 @@ + + + + + + + 当前登录租户: {{ loginTenantName }} + + + + + + + + + + + + + + + + diff --git a/jeecgboot-vue3/src/views/system/tenant/pack/TenantPackList.vue b/jeecgboot-vue3/src/views/system/tenant/pack/TenantPackList.vue index e5095b79c..57c61ac6c 100644 --- a/jeecgboot-vue3/src/views/system/tenant/pack/TenantPackList.vue +++ b/jeecgboot-vue3/src/views/system/tenant/pack/TenantPackList.vue @@ -137,6 +137,12 @@ return; } //update-end---author:wangshuai ---date:20230222 for:系统默认套餐包不允许删除------------ + //update-begin---author:wangshuai---date:2025-09-03---for:默认套餐不允许删除--- + if(record.packCode && record.packCode.indexOf("default") != -1){ + createMessage.warning("默认套餐包不允许删除"); + return; + } + //update-end---author:wangshuai---date:2025-09-03---for:默认套餐不允许删除--- await deleteTenantPack({ ids: record.id }, success); } @@ -151,6 +157,12 @@ createMessage.warning("默认系统套餐包不允许删除"); return; } + //update-begin---author:wangshuai---date:2025-09-03---for:默认套餐不允许删除--- + if(value[i].packCode && value[i].packCode.indexOf("default") != -1){ + createMessage.warning("默认套餐包不允许删除"); + return; + } + //update-end---author:wangshuai---date:2025-09-03---for:默认套餐不允许删除--- } } Modal.confirm({ diff --git a/jeecgboot-vue3/src/views/system/tenant/tenant.api.ts b/jeecgboot-vue3/src/views/system/tenant/tenant.api.ts index fa6a5a09a..f82c14a04 100644 --- a/jeecgboot-vue3/src/views/system/tenant/tenant.api.ts +++ b/jeecgboot-vue3/src/views/system/tenant/tenant.api.ts @@ -29,8 +29,10 @@ enum Api { getTenantPageListByUserId = '/sys/tenant/getTenantPageListByUserId', //新增、编辑用户租户 - saveUser = '/sys/user/add', + saveUser = '/sys/user/addTenantUser', editUser = '/sys/user/editTenantUser', + //根据租户id和用户获取用户的产品包列表和当前用户下的产品包id + listPackByTenantUserId = '/sys/tenant/listPackByTenantUserId', } /** @@ -112,7 +114,7 @@ export const getTenantUserList = (params) => { export const leaveTenant = (params, handleSuccess) => { Modal.confirm({ title: '请离', - content: '是否请离该用户', + content: '是否将此用户请离当前租户', okText: '确认', cancelText: '取消', onOk: () => { @@ -253,3 +255,11 @@ export const saveOrUpdateTenantUser = (params, isUpdate) => { let url = isUpdate ? Api.editUser : Api.saveUser; return defHttp.post({ url: url, params },{ joinParamsToUrl: true }); }; +/** + * 根据租户id和用户获取用户的产品包列表和当前用户下的产品包id + * + * @param params + */ +export const listPackByTenantUserId = (params) => { + return defHttp.get({ url: Api.listPackByTenantUserId, params }); +} diff --git a/jeecgboot-vue3/src/views/system/tenant/tenant.data.ts b/jeecgboot-vue3/src/views/system/tenant/tenant.data.ts index 8c5b06102..199cc26aa 100644 --- a/jeecgboot-vue3/src/views/system/tenant/tenant.data.ts +++ b/jeecgboot-vue3/src/views/system/tenant/tenant.data.ts @@ -147,12 +147,21 @@ export const formSchema: FormSchema[] = [ }, { field: 'companyAddress', label: '公司地址', - component: 'InputTextArea', + component: 'JAreaSelect', componentProps: { placeholder: '请输入公司地址', rows: 4, } }, + { + field: 'workPlace', + label: '工作地点', + component: 'InputTextArea', + componentProps: { + placeholder: '请输入工作地点', + rows: 4, + } + }, /* { field: 'beginDate', label: '开始时间', @@ -257,6 +266,25 @@ export const packColumns: BasicColumn[] = [ title: '套餐包名称', dataIndex: 'packName', width: 100, + customRender: ( { record, text }) => { + if(record.packCode && record.packCode.indexOf('default') != -1) { + return text + '(默认产品包)'; + } else { + return text; + } + } + }, + { + title: '是否自动分配用户', + dataIndex: 'izSysn', + width: 100, + customRender: ( { text }) => { + if(text === '1') { + return '是'; + } else { + return '否'; + } + } }, { title: '状态', @@ -277,6 +305,39 @@ export const packColumns: BasicColumn[] = [ }, ]; +//套餐包列表 +export const tenantPackColumns: BasicColumn[] = [ + { + title: '套餐包名称', + dataIndex: 'packName', + width: 100, + customRender: ( { record, text }) => { + if(record.packCode && record.packCode.indexOf('default') != -1) { + return text + '(默认产品包)'; + } else { + return text; + } + } + }, + { + title: '是否自动分配用户', + dataIndex: 'izSysn', + width: 100, + customRender: ( { text }) => { + if(text === '1') { + return '是'; + } else { + return '否'; + } + } + }, + { + title: '备注说明', + dataIndex: 'remarks', + width: 150, + }, +]; + //套餐包列表 export const defalutPackColumns: BasicColumn[] = [ { @@ -337,9 +398,11 @@ export const packMenuFormSchema: FormSchema[] = [ componentProps: { dict: 'sys_permission,name,id', pidField: 'parent_id', + hasChildField:'is_leaf', multiple: true, treeCheckAble:true, treeCheckStrictly: true, + converIsLeafVal: 0, getPopupContainer: () => document.body, }, }, @@ -348,6 +411,19 @@ export const packMenuFormSchema: FormSchema[] = [ label: '备注说明', component: 'InputTextArea', }, + { + field: 'izSysn', + label: '自动分配用户', + component: 'Switch', + componentProps: { + checkedValue: "1", + checkedChildren: '是', + unCheckedValue: "0", + unCheckedChildren: '否', + }, + defaultValue: "1", + helpMessage: "默认会自动分配给用户,个性高级套餐,需要租户管理员手工分配人员(拥有更灵活性权限控制)" + }, { field: 'status', label: '开启状态', @@ -366,6 +442,18 @@ export const packMenuFormSchema: FormSchema[] = [ component: 'Input', show: false }, + { + field: 'packCode', + label: '产品包编码', + component: 'Input', + show: false + }, + { + field: 'packType', + label: '产品包类型', + component: 'Input', + show: false + }, ]; //回收站列表 @@ -479,7 +567,7 @@ export const tenantUserSchema: FormSchema[] = [ }, }, { field: 'selecteddeparts', label: '部门', component: 'JSelectDept', componentProps: { checkStrictly: true } }, - { + /* { field: 'post', label: '职位', component: 'JSelectPosition', @@ -489,9 +577,33 @@ export const tenantUserSchema: FormSchema[] = [ label: '工号', component: 'Input', dynamicRules: ({ model, schema }) => { - return [{ required: true, message: '请输入工号' }, { ...rules.duplicateCheckRule('sys_user', 'work_no', model, schema, false)[0] }]; + return [{ required: false, message: '请输入工号' }, { ...rules.duplicateCheckRule('sys_user', 'work_no', model, schema, false)[0] }]; }, - }, + },*/ { field: 'relTenantIds', label: '租户', component: 'Input',show:false }, { field: 'selectedroles', label: '角色', component: 'Input',show:false }, ]; + +// 分配用户套餐 +export const packUserAllotSchemas: FormSchema[] = [ + { + field: 'userId', + label: '用户id', + component: 'Input', + show: false + }, + { + field: 'realname', + label: '用户姓名', + component: 'Input', + componentProps:{ + readonly : true + }, + }, + { + field: 'packId', + label: '套餐', + component: 'Select', + slot: 'packId' + } +]; \ No newline at end of file