前端和后端源码,合并到一个git仓库中,方便用户下载,避免前后端不匹配的问题

This commit is contained in:
JEECG
2024-06-23 10:39:52 +08:00
parent bb918b742e
commit 0325e34dcb
1439 changed files with 171106 additions and 0 deletions

View File

@ -0,0 +1,307 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
<JThirdAppButton biz-type="user" :selected-row-keys="selectedRowKeys" syncToApp syncToLocal @sync-finally="onSyncFinally" />
<a-button type="primary" @click="openQuitModal(true, {})" preIcon="ant-design:user-delete-outlined">离职信息</a-button>
<div style="margin-left: 10px;margin-top: 5px"> 当前登录租户: <span class="tenant-name">{{loginTenantName}}</span> </div>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
</BasicTable>
<!--用户抽屉-->
<TenantUserDrawer @register="registerDrawer" @success="handleSuccess" />
<!-- 离职受理人弹窗 -->
<UserQuitAgentModal @register="registerQuitAgentModal" @success="handleQuitSuccess" />
<!-- 离职人员列弹窗 -->
<UserQuitModal @register="registerQuitModal" @success="reload" />
<!-- 变更拥有者弹窗 -->
<UserSelectModal @register="registerUserModal" :excludeUserIdList="excludeUserIdList" :maxSelectCount="1" @getSelectResult="selectResult" />
</div>
</template>
<script lang="ts" name="tenant-system-user" setup>
//ts语法
import { onMounted, ref, unref } from 'vue';
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 { usePermission } from '/@/hooks/web/usePermission'
// const { hasPermission } = usePermission();
import { userTenantColumns, userTenantFormSchema } from '../user/user.data';
import { useUserStore } from '/@/store/modules/user';
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 TenantUserDrawer from './components/TenantUserDrawer.vue';
import { tenantSaasMessage } from "@/utils/common/compUtils";
const { createMessage, createConfirm } = useMessage();
//注册drawer
const [registerDrawer, { openDrawer }] = useDrawer();
//离职代理人model
const [registerQuitAgentModal, { openModal: openQuitAgentModal }] = useModal();
//离职用户列表model
const [registerQuitModal, { openModal: openQuitModal }] = useModal();
const userStore = useUserStore();
const createBy = userStore.getUserInfo.username;
// 列表页面公共参数、方法
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
designScope: 'user-list',
tableProps: {
title: '租户用户列表',
api: getUserTenantPageList,
columns: userTenantColumns,
size: 'small',
formConfig: {
schemas: userTenantFormSchema,
},
actionColumn: {
width: 120,
},
beforeFetch: (params) => {
params['userTenantStatus'] = '1,3,4';
return Object.assign({ column: 'createTime', order: 'desc' }, params);
},
},
});
//注册table数据
const [registerTable, { reload, updateTableDataRecord }, { rowSelection, selectedRows, selectedRowKeys }] = tableContext;
/**
* 新增事件
*/
function handleCreate() {
openDrawer(true, {
isUpdate: false,
showFooter: true,
tenantSaas: true,
});
}
/**
* 编辑事件
*/
async function handleEdit(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: true,
tenantSaas: true,
});
}
/**
* 详情
*/
async function handleDetail(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: false,
tenantSaas: true,
});
}
/**
* 成功回调
*/
function handleSuccess() {
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: '离职',
//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: handleHandover.bind(null, record),
ifShow: () =>{
return record.username === record.createBy;
}
},
{
label: '同意',
onClick: updateStatus.bind(null, record.id, '1'),
ifShow: () => {
return (record.status === '3' || record.status === '4') && record.createBy === createBy;
},
},
{
label: '拒绝',
popConfirm: {
title: '是否确认拒绝',
confirm: updateStatus.bind(null, record.id, '4'),
},
ifShow: () => {
return record.status === '3' && record.createBy === createBy;
},
},
];
}
/**
* 离职
* @param userName
* @param userId
*/
function handleQuit(userName, userId) {
//打开离职代理人弹窗
openQuitAgentModal(true, { userName, userId });
}
/**
* 更新用户租户状态
* @param id
* @param status
*/
function updateStatus(id, status) {
updateUserTenantStatus({ userId: id, status: status })
.then((res) => {
if (res.success) {
handleSuccess();
}
})
.catch((e) => {
createMessage.warning(e.message);
});
}
//============================================ 租户离职交接 ============================================
//租户id
const tenantId = ref<string>('');
//排除自己的编号集合
const excludeUserIdList = ref<any>([]);
//离职代理人model
const [registerUserModal, { openModal: openUserModal }] = useModal();
const handOverUserName = ref<string>('');
/**
* 人员交接
*/
function handleHandover(record) {
tenantId.value = getTenantId();
excludeUserIdList.value = [record.id];
//记录一下当前需要交接的用户名
handOverUserName.value = record.createBy;
openUserModal(true)
}
/**
* 用户选择回调
* @param options
* @param values
*/
function selectResult(options,values) {
console.log(values)
if(values && values.length>0){
let userId = values[0];
changeOwenUserTenant({ userId:userId, tenantId:unref(tenantId) }).then((res) =>{
if(res.success){
createMessage.success("交接成功");
let username = userStore.getUserInfo?.username;
if(username == handOverUserName.value){
userStore.logout(true);
}else{
reload();
}
} else {
createMessage.warning(res.message);
}
})
}
}
//============================================ 租户离职交接 ============================================
//update-begin---author:wangshuai ---date:20230710 for【QQYUN-5723】4、显示当前登录租户------------
const loginTenantName = ref<string>('');
getTenantName();
async function getTenantName(){
loginTenantName.value = await getLoginTenantName();
}
//update-end---author:wangshuai ---date:20230710 for【QQYUN-5723】4、显示当前登录租户------------
/**
* 离职成功之后需要判断一下是否为当前用户,当前用户需要刷新浏览器
* @param userName
*/
function handleQuitSuccess(userName) {
//判断如果当前离职的是当前登录用户需要刷新页面便将租户id设置成null
let username = userStore.getUserInfo.username;
if (username && userName === username) {
userStore.setTenant(null);
window.location.reload();
}else{
reload();
}
}
onMounted(()=>{
tenantSaasMessage('租户用户')
})
</script>
<style scoped>
.tenant-name{
text-decoration:underline;
margin: 5px;
font-size: 15px;
}
</style>

View File

@ -0,0 +1,64 @@
<!--邀请用户加入租户弹窗-->
<template>
<BasicModal @register="registerModal" :width="500" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts">
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'TenantInviteUserModal',
components: {
BasicModal,
BasicForm,
},
setup(props, { emit }) {
const title = ref<string>('邀请成员');
const [registerForm, { resetFields, validate }] = useForm({
schemas: [
{
label: '手机号',
field: 'phone',
component: 'Input',
dynamicRules: () => {
return [
{ required: true, message: '请填写手机号' },
{ pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误' },
];
},
},
],
showActionButtonGroup: false,
labelCol: { span: 24 },
wrapperCol: { span: 24 },
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({ minHeight: 100 });
});
/**
* 提交返回给租户list页面
*/
async function handleSubmit() {
let values = await validate();
emit('inviteOk',values.phone);
closeModal();
}
return {
title,
registerModal,
registerForm,
handleSubmit,
};
},
});
</script>
<style scoped></style>

View File

@ -0,0 +1,57 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit" width="700px">
<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 { formSchema } from '../tenant.data';
import { saveOrUpdateTenant, getTenantById } from '../tenant.api';
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema }] = useForm({
// labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
// 编辑模式下禁用id字段
updateSchema({ field: 'id', dynamicDisabled: true });
//获取详情
data.record = await getTenantById({ id: data.record.id });
//表单赋值
await setFieldsValue({
...data.record,
});
} else {
updateSchema({ field: 'id', dynamicDisabled: false });
}
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增租户' : '编辑租户'));
//表单提交事件
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({ confirmLoading: true });
//提交表单
await saveOrUpdateTenant(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>

View File

@ -0,0 +1,147 @@
<!--回收站-->
<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="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 #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</BasicModal>
</template>
<script lang="ts" setup name="tenant-recycle-bin-modal">
import { BasicTable, TableAction } from '/@/components/Table';
import { recycleBinPageList, deleteLogicDeleted, revertTenantLogic } from '../tenant.api';
import { recycleColumns, searchRecycleFormSchema } from '../tenant.data';
import { useListPage } from '/@/hooks/system/useListPage';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { Modal } from 'ant-design-vue';
import { toRaw, unref } from 'vue';
const { createMessage: $message } = useMessage();
const [registerModal] = useModalInner(() => {});
// 列表页面公共参数、方法
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
api: recycleBinPageList,
columns: recycleColumns,
size: 'small',
formConfig: {
schemas: searchRecycleFormSchema,
},
actionColumn: {
width: 120,
},
ellipsis: true,
},
});
const emit = defineEmits(['success', 'register']);
//注册table数据
const [registerTable, { reload, updateTableDataRecord }, { rowSelection, selectedRows, selectedRowKeys }] = tableContext;
//获取操作栏事件
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),
},
},
];
}
/**
* 还原
* @param record
*/
function handleRevert(record) {
revertTenantLogic({ ids: record.id }, handleSuccess);
emit('success');
}
/**
* 成功刷新表格
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 彻底删除
* @param record
*/
async function handleDelete(record) {
await deleteLogicDeleted({ ids: record.id }, handleSuccess);
}
/**
* 批量彻底删除
*/
function batchHandleDelete() {
Modal.confirm({
title: '彻底删除',
content: '是否确认彻底删除',
okText: '确认',
cancelText: '取消',
onOk: () => {
deleteLogicDeleted({ ids: toRaw(unref(selectedRowKeys)).join(',') }, handleSuccess);
},
});
}
/**
* 批量还原
*/
function batchHandleRevert() {
Modal.confirm({
title: '还原',
content: '是否确认还原',
okText: '确认',
cancelText: '取消',
onOk: () => {
revertTenantLogic({ ids: toRaw(unref(selectedRowKeys)).join(',') }, handleSuccess);
emit('success');
},
});
}
</script>
<style lang="less" scoped>
:deep(.ant-popover-inner-content) {
width: 185px !important;
}
</style>

View File

@ -0,0 +1,100 @@
<template>
<BasicDrawer @register="registerDrawer" :title="title" :width="580" destroyOnClose @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
<script lang="ts">
import { defineComponent, ref, unref, computed } from 'vue';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { BasicForm, useForm } from '/@/components/Form';
import { getUserDepartList } from '../../user/user.api';
import { tenantUserSchema } from '../tenant.data';
import { saveOrUpdateTenantUser } from '../tenant.api';
export default defineComponent({
name: 'TenantUserDrawer',
components: {
BasicDrawer,
BasicForm,
},
emits: ['success', 'register'],
setup(_p, { emit }) {
const status = ref<string>('');
const isUpdate = ref(false);
const title = computed(() => {
return isUpdate.value ? '编辑人员' : '添加人员';
});
//表单
const [registerForm, { setFieldsValue, resetFields, validate, setProps, clearValidate }] = useForm({
schemas: tenantUserSchema,
showActionButtonGroup: false,
labelCol: { span: 24 },
wrapperCol: { span: 24 },
});
const showFooter = ref<boolean>(true);
// modal
const [registerDrawer, { closeDrawer, setDrawerProps }] = useDrawerInner(async (data) => {
isUpdate.value = data.isUpdate;
await resetFields();
showFooter.value = data?.showFooter ?? true;
setDrawerProps({ showFooter: showFooter.value });
if (unref(isUpdate)) {
const userDepart = await getUserDepartList({ userId: data.record.id });
let departData: any = '';
if (userDepart && userDepart.length > 0) {
departData = userDepart.map((item) => item.value);
}
let formData = {
...data.record,
selecteddeparts: departData,
selectedroles: data.record.selectedroles,
};
status.value = data.status;
await setFieldsValue(formData);
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter });
if(!data?.showFooter){
await clearValidate();
}
});
const confirmLoading = ref<boolean>(false);
//提交事件
async function handleSubmit() {
const data: any = await validate();
if (!data.username) {
data.username = data.phone;
}
data.password = '123456';
confirmLoading.value = true;
await saveOrUpdateTenantUser(data, isUpdate.value);
confirmLoading.value = false;
emit('success');
handleClose();
}
/**
* 取消
*/
function handleClose() {
closeDrawer();
}
return {
isUpdate,
title,
registerForm,
registerDrawer,
handleSubmit,
handleClose,
status,
confirmLoading,
};
},
});
</script>

View File

@ -0,0 +1,103 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit" width="800px">
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<template #tableTitle>
<a-button v-if="selectedRowKeys.length>0" preIcon="ant-design:delete-outlined" type="primary" @click="handleLeaveBatch" style="margin-right: 5px">批量请离</a-button>
</template>
<template #action="{ record }">
<TableAction :actions="getActions(record)" />
</template>
</BasicTable>
</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 { userColumns, userSearchFormSchema } from "../tenant.data";
import { getTenantUserList, leaveTenant } from "../tenant.api";
import { useListPage } from "/@/hooks/system/useListPage";
import { BasicTable, TableAction } from '/@/components/Table';
const tenantId = ref<number>(0);
// 列表页面公共参数、方法
const { prefixCls, tableContext } = useListPage({
designScope: 'tenant-template',
tableProps: {
api: getTenantUserList,
columns: userColumns,
immediate:false,
formConfig: {
schemas: userSearchFormSchema,
//update-begin---author:wangshuai ---date:20230704 for【QQYUN-5698】样式问题------------
labelWidth: 40,
//update-end---author:wangshuai ---date:20230704 for【QQYUN-5698】样式问题------------
actionColOptions: {
xs: 24,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
},
beforeFetch: (params) => {
return Object.assign(params, { userTenantId: unref(tenantId) });
},
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
// Emits声明
const emit = defineEmits(['register', 'success']);
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
tenantId.value = data.id;
success();
});
//设置标题
const title = '成员';
//表单提交事件
async function handleSubmit(v) {
closeModal();
}
function getActions(record) {
return [
{
label: '移除',
onClick: handleLeave.bind(null, record.id),
},
]
}
/**
* 成功
*/
function success() {
(selectedRowKeys.value = []) && reload();
}
/**
* 请离
* @param id
*/
async function handleLeave(id) {
await leaveTenant({userIds:id,tenantId:unref(tenantId)},success)
}
/**
* 批量请离
*/
async function handleLeaveBatch(){
await leaveTenant({userIds:selectedRowKeys.value.join(","),tenantId:unref(tenantId)},success)
}
</script>
<style scoped>
/*update-begin---author:wangshuai ---date:20220705 for查询组件input有后缀隐藏掉------------*/
:deep(.ant-input-suffix){
display: none;
}
/*update-begin---author:wangshuai ---date:20220705 for查询组件input有后缀隐藏掉------------*/
</style>

View File

@ -0,0 +1,159 @@
<!--套餐中使用的用户选择框-->
<template>
<div>
<BasicModal
v-bind="$attrs"
@register="register"
:title="modalTitle"
width="900px"
wrapClassName="j-user-select-modal"
@ok="handleOk"
destroyOnClose
>
<BasicTable ref="tableRef" @register="registerTable" :rowSelection="rowSelection">
<template #tableTitle></template>
</BasicTable>
</BasicModal>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { getTenantUserList } from '../tenant.api';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { useListPage } from '/@/hooks/system/useListPage';
import { userColumns, userSearchFormSchema } from '../tenant.data';
export default defineComponent({
name: 'TenantUserSelectModal',
components: {
//此处需要异步加载BasicTable
BasicModal,
BasicTable: createAsyncComponent(() => import('/@/components/Table/src/BasicTable.vue'), {
loading: true,
}),
},
props: {
//选择框标题
modalTitle: {
type: String,
default: '选择用户',
},
//查询参数
tenantId: {
type: Number,
default: 0,
},
//排除用户id的集合
excludeUserIdList: {
type: Array,
default: [],
},
},
emits: ['register', 'on-select'],
setup(props, { emit, refs }) {
const tableScroll = ref<any>({ x: false });
const tableRef = ref();
//注册弹框
const [register, { closeModal }] = useModalInner(() => {
if (window.innerWidth < 900) {
tableScroll.value = { x: 900 };
} else {
tableScroll.value = { x: false };
}
setTimeout(() => {
if (tableRef.value) {
tableRef.value.setSelectedRowKeys([]);
}
}, 800);
});
//定义表格列
const columns = [
{
title: '账号',
dataIndex: 'username',
width: 40,
align: 'left',
},
{
title: '姓名',
dataIndex: 'realname',
width: 40,
},
{
title: '性别',
dataIndex: 'sex_dictText',
width: 20,
},
{
title: '手机号码',
dataIndex: 'phone',
width: 30,
},
{
title: '邮箱',
dataIndex: 'email',
width: 40,
},
{
title: '状态',
dataIndex: 'status_dictText',
width: 20,
},
];
// 列表页面公共参数、方法
const { prefixCls, tableContext } = useListPage({
designScope: 'tenant-template',
tableProps: {
api: getTenantUserList,
columns: userColumns,
scroll: { y: 390 },
rowKey: 'id',
showActionColumn: false,
formConfig: {
schemas: userSearchFormSchema,
labelWidth: 60,
actionColOptions: {
xs: 24,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
},
beforeFetch: (params) => {
return Object.assign(params, { userTenantId: props.tenantId });
},
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 确定选择
*/
function handleOk() {
//返回选中事件
emit('on-select', rowSelection.selectedRows, rowSelection.selectedRowKeys);
}
return {
handleOk,
register,
columns,
rowSelection,
tableScroll,
tableRef,
registerTable,
};
},
});
</script>
<style scoped>
:deep(.ant-input-suffix) {
display: none;
}
</style>

View File

@ -0,0 +1,207 @@
<template>
<div>
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<template #tableTitle>
<a-button preIcon="ant-design:plus-outlined" type="primary" @click="handleAdd" style="margin-right: 5px">新增</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>
</template>
<a-button
>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
<a-button
preIcon="ant-design:user-add-outlined"
type="primary"
@click="handleInvitation"
style="margin-right: 5px"
:disabled="selectedRowKeys.length === 0"
>邀请用户加入</a-button
>
<a-button
preIcon="ant-design:plus-outlined"
type="primary"
@click="handlePack"
style="margin-right: 5px"
:disabled="selectedRowKeys.length === 0"
>套餐</a-button
>
<a-button type="primary" @click="recycleBinClick" preIcon="ant-design:hdd-outlined">回收站</a-button>
</template>
<template #action="{ record }">
<TableAction :actions="getActions(record)" />
</template>
</BasicTable>
<TenantModal @register="registerModal" @success="reload" />
<TenantInviteUserModal @register="registerSelUserModal" @inviteOk="handleInviteUserOk"/>
<TenantUserModal @register="registerTenUserModal" />
<!-- 产品包 -->
<TenantPackList @register="registerPackModal" />
<!-- 租户回收站 -->
<TenantRecycleBinModal @register="registerRecycleBinModal" @success="reload" />
</div>
</template>
<script lang="ts" name="system-tenant" setup>
import { ref, unref } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { getTenantList, deleteTenant, batchDeleteTenant, invitationUserJoin } from './tenant.api';
import { columns, searchFormSchema } from './tenant.data';
import TenantModal from './components/TenantModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useListPage } from '/@/hooks/system/useListPage';
import TenantInviteUserModal from './components/TenantInviteUserModal.vue';
import TenantUserModal from './components/TenantUserList.vue';
import TenantPackList from './pack/TenantPackList.vue';
import TenantRecycleBinModal from './components/TenantRecycleBinModal.vue';
const { createMessage } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerSelUserModal, { openModal: userOpenModal }] = useModal();
const [registerTenUserModal, { openModal: tenUserOpenModal }] = useModal();
const [registerPackModal, { openModal: packModal }] = useModal();
const [registerRecycleBinModal, { openModal: recycleBinModal }] = useModal();
// 列表页面公共参数、方法
const { prefixCls, tableContext } = useListPage({
designScope: 'tenant-template',
tableProps: {
title: '租户列表',
api: getTenantList,
columns: columns,
formConfig: {
schemas: searchFormSchema,
fieldMapToTime: [['fieldTime', ['beginDate', 'endDate'], 'YYYY-MM-DD HH:mm:ss']],
},
actionColumn:{
width: 150,
fixed:'right'
}
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
/**
* 操作列定义
* @param record
*/
function getActions(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
popConfirm: {
title: '是否确认删除',
placement: 'left',
confirm: handleDelete.bind(null, record),
},
},
{
label: '用户',
onClick: handleSeeUser.bind(null, record.id),
},
];
}
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
});
}
/**
* 编辑事件
*/
function handleEdit(record) {
openModal(true, {
record,
isUpdate: true,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteTenant({ id: record.id }, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDeleteTenant({ ids: selectedRowKeys.value }, handleSuccess);
}
/**
* 邀请用户加入租户
*/
function handleInvitation() {
userOpenModal(true, {});
}
/**
* 用户选择回调事件
* @param options
* @param value
*/
async function handleInviteUserOk(value) {
//update-begin---author:wangshuai ---date:20230314 for【QQYUN-4605】后台的邀请谁加入租户没办法选不是租户下的用户------------
if (value) {
await invitationUserJoin({ ids: selectedRowKeys.value.join(','), phone: value });
}
//update-end---author:wangshuai ---date:20230314 for【QQYUN-4605】后台的邀请谁加入租户没办法选不是租户下的用户------------
}
/**
* 查看用户
* @param id
*/
function handleSeeUser(id) {
tenUserOpenModal(true, {
id: id,
});
}
/**
* 新增产品包
*/
function handlePack() {
if (unref(selectedRowKeys).length > 1) {
createMessage.warn('请选择一个');
return;
}
packModal(true, {
tenantId: unref(selectedRowKeys.value.join(',')),
//我的租户显示新增和编辑产品包
showPackAddAndEdit: true
});
}
/**
* 回收站
*/
function recycleBinClick() {
recycleBinModal(true, {});
}
/**
* 删除成功之后回调事件
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
</script>

View File

@ -0,0 +1,146 @@
<template>
<div>
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<template #tableTitle>
<a-button
preIcon="ant-design:user-add-outlined"
type="primary"
@click="handleInvitation"
style="margin-right: 5px"
:disabled="selectedRowKeys.length === 0"
>邀请用户加入</a-button
>
<a-button
preIcon="ant-design:plus-outlined"
type="primary"
@click="handlePack"
style="margin-right: 5px"
:disabled="selectedRowKeys.length === 0"
>套餐</a-button
>
</template>
<template #action="{ record }">
<TableAction :actions="getActions(record)" />
</template>
</BasicTable>
<TenantInviteUserModal @register="registerSelUserModal" @inviteOk="handleInviteUserOk" />
<TenantUserModal @register="registerTenUserModal" />
<!-- 产品包 -->
<TenantPackList @register="registerPackModal" />
</div>
</template>
<script lang="ts" name="tenant-my-tenant-list" setup>
import { onMounted, ref, unref } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { invitationUserJoin, getTenantPageListByUserId } from '../tenant.api';
import { columns, searchFormSchema } from '../tenant.data';
import TenantModal from '../components/TenantModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useListPage } from '/@/hooks/system/useListPage';
import TenantInviteUserModal from '../components/TenantInviteUserModal.vue';
import TenantUserModal from '../components/TenantUserList.vue';
import TenantPackList from '../pack/TenantPackList.vue';
import { getTenantId } from '/@/utils/auth';
import { useUserStore } from '/@/store/modules/user';
import { tenantSaasMessage } from "@/utils/common/compUtils";
const { createMessage } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerSelUserModal, { openModal: userOpenModal }] = useModal();
const [registerTenUserModal, { openModal: tenUserOpenModal }] = useModal();
const [registerPackModal, { openModal: packModal }] = useModal();
const userStore = useUserStore();
// 列表页面公共参数、方法
const { prefixCls, tableContext } = useListPage({
designScope: 'tenant-template',
tableProps: {
title: '租户列表',
api: getTenantPageListByUserId,
columns: columns,
formConfig: {
schemas: searchFormSchema,
},
actionColumn: {
width: 150,
fixed: 'right',
},
rowSelection:{
type: "radio"
},
beforeFetch: (params) => {
return Object.assign(params, { userTenantStatus: '1,3,4' });
},
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
/**
* 操作列定义
* @param record
*/
function getActions(record) {
return [
{
label: '用户',
onClick: handleSeeUser.bind(null, record.id),
},
];
}
/**
* 邀请用户加入租户
*/
function handleInvitation() {
userOpenModal(true, {});
}
/**
* 用户选择回调事件
* @param options
* @param value
*/
async function handleInviteUserOk(value) {
if (value) {
await invitationUserJoin({ ids: selectedRowKeys.value.join(','), phone: value });
}
}
/**
* 查看用户
* @param id
*/
async function handleSeeUser(id) {
tenUserOpenModal(true, {
id: id,
});
}
/**
* 新增产品包
*/
async function handlePack() {
if (unref(selectedRowKeys).length > 1) {
createMessage.warn('请选择一个');
return;
}
packModal(true, {
tenantId: unref(selectedRowKeys.value.join(',')),
//我的租户不显示新增和编辑产品包
showPackAddAndEdit: false
});
}
/**
* 删除成功之后回调事件
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
onMounted(()=>{
//提示信息
tenantSaasMessage('我的租户')
})
</script>

View File

@ -0,0 +1,140 @@
<template>
<div>
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<template #tableTitle>
<a-button preIcon="ant-design:user-add-outlined" type="primary" @click="handleAdd">新增</a-button>
<a-button
v-if="selectedRowKeys.length > 0"
preIcon="ant-design:delete-outlined"
type="primary"
@click="handlePackBatch"
style="margin-right: 5px"
>批量删除
</a-button>
</template>
<template #action="{ record }">
<TableAction :actions="getActions(record)" />
</template>
</BasicTable>
<!-- 产品包 -->
<TenantPackMenuModal @register="registerPackMenuModal" @success="handleSuccess"/>
</div>
</template>
<script lang="ts" name="tenant-default-pack" setup>
import { ref, unref } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { deleteTenantPack, packList } from '../tenant.api';
import { packColumns, packFormSchema } from '../tenant.data';
import TenantPackMenuModal from './TenantPackMenuModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useListPage } from '/@/hooks/system/useListPage';
import { useUserStore } from '/@/store/modules/user';
import {Modal} from "ant-design-vue";
const { createMessage } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerPackMenuModal, { openModal: packModal }] = useModal();
const userStore = useUserStore();
// 列表页面公共参数、方法
const { prefixCls, tableContext } = useListPage({
designScope: 'tenant-template',
tableProps: {
api: packList,
columns: packColumns,
formConfig: {
schemas: packFormSchema,
},
beforeFetch: (params) => {
return Object.assign(params, { packType: 'default' });
},
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
/**
* 操作列定义
* @param record
*/
function getActions(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
popConfirm: {
title: '是否确认删除租户产品包',
confirm: handleDelete.bind(null, record.id),
},
},
];
}
/**
* 编辑产品包
*/
function handleAdd() {
packModal(true, {
isUpdate: false,
packType:'default',
showFooter: true
});
}
/**
* 删除默认产品包
*/
async function handleDelete(id) {
await deleteTenantPack({ ids: id }, handleSuccess);
}
/**
* 编辑
*/
function handleEdit(record) {
packModal(true, {
isUpdate: true,
record: record,
packType:'default',
showFooter: true
});
}
/**
* 新增产品包
*/
async function handlePack() {
if (unref(selectedRowKeys).length > 1) {
createMessage.warn('请选择一个');
return;
}
packModal(true, {
tenantId: unref(selectedRowKeys.value.join(',')),
});
}
/**
* 删除成功之后回调事件
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 批量删除产品包
*/
async function handlePackBatch() {
Modal.confirm({
title: '删除租户产品包',
content: '是否删除租户产品包',
okText: '确认',
cancelText: '取消',
onOk: async () => {
await deleteTenantPack({ ids: selectedRowKeys.value.join(',')}, handleSuccess);
}
})
}
</script>

View File

@ -0,0 +1,216 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit" width="800px" :showCancelBtn="false" :showOkBtn="false">
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<template #tableTitle>
<a-button preIcon="ant-design:plus-outlined" type="primary" @click="handleAdd" style="margin-right: 5px" v-if="showPackAddAndEdit">新增 </a-button>
<a-button
v-if="selectedRowKeys.length > 0"
preIcon="ant-design:delete-outlined"
type="primary"
@click="handlePackBatch"
style="margin-right: 5px"
>批量删除
</a-button>
</template>
<template #action="{ record }">
<TableAction :actions="getActions(record)" :dropDownActions="getDropDownAction(record)" />
</template>
</BasicTable>
</BasicModal>
<TenantPackMenuModal @register="registerPackMenu" @success="success" />
<TenantPackUserModal @register="registerPackUser" @success="success" />
</template>
<script lang="ts" setup name="tenant-pack-modal">
import { reactive, ref, unref } from 'vue';
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
import { packColumns, userColumns, packFormSchema } from '../tenant.data';
import { getTenantUserList, leaveTenant, packList, deleteTenantPack } from '../tenant.api';
import { useListPage } from '/@/hooks/system/useListPage';
import { BasicTable, TableAction } from '/@/components/Table';
import TenantPackMenuModal from './TenantPackMenuModal.vue';
import {Modal} from "ant-design-vue";
import TenantPackUserModal from './TenantPackUserModal.vue';
import {useMessage} from "/@/hooks/web/useMessage";
const [registerPackMenu, { openModal }] = useModal();
const [registerPackUser, { openModal: packUserOpenModal }] = useModal();
const tenantId = ref<number>(0);
// 列表页面公共参数、方法
const { prefixCls, tableContext } = useListPage({
designScope: 'tenant-template',
tableProps: {
api: packList,
columns: packColumns,
immediate: false,
formConfig: {
schemas: packFormSchema,
labelCol: {
xxl: 8,
},
actionColOptions: {
xs: 24,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
},
beforeFetch: (params) => {
return Object.assign(params, { tenantId: unref(tenantId), packType:'custom' });
},
},
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
// Emits声明
const emit = defineEmits(['register', 'success']);
//是否显示新增和编辑产品包
const showPackAddAndEdit = ref<boolean>(false);
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
tenantId.value = data.tenantId;
showPackAddAndEdit.value = data.showPackAddAndEdit;
success();
});
//设置标题
const title = '租户产品包列表';
//表单提交事件
async function handleSubmit(v) {
closeModal();
}
function getActions(record) {
return [
{
label: '用户',
onClick: seeTenantPackUser.bind(null, record),
},
{
label: '编辑',
onClick: handleEdit.bind(null, record),
ifShow: ()=>{ return showPackAddAndEdit.value }
},
];
}
/**
* 成功
*/
function success() {
(selectedRowKeys.value = []) && reload();
}
/**
* 编辑
* @param record
*/
async function handleEdit(record) {
openModal(true, {
isUpdate: true,
record: record,
tenantId: unref(tenantId),
packType:'custom',
showFooter: true
});
}
//默认系统产品包不允许删除,包含(超级管理员、组织账户管理员、组织应用管理员)
const packCode = reactive<any>(['superAdmin','accountAdmin','appAdmin']);
const { createMessage } = useMessage();
/**
* 删除产品包
* @param 删除
*/
async function handleDelete(record) {
//update-begin---author:wangshuai ---date:20230222 for系统默认产品包不允许删除------------
if(packCode.indexOf(record.packCode) != -1){
createMessage.warning("默认系统产品包不允许删除");
return;
}
//update-end---author:wangshuai ---date:20230222 for系统默认产品包不允许删除------------
await deleteTenantPack({ ids: record.id }, success);
}
/**
* 批量删除产品包
*/
async function handlePackBatch() {
let value = selectedRows.value;
if(value && value.length>0){
for (let i = 0; i < value.length; i++) {
if(packCode.indexOf(value[i].packCode) != -1){
createMessage.warning("默认系统产品包不允许删除");
return;
}
}
}
Modal.confirm({
title: '删除租户产品包',
content: '是否删除租户产品包',
okText: '确认',
cancelText: '取消',
onOk: async () => {
await deleteTenantPack({ ids: selectedRowKeys.value.join(',')}, success);
}
})
}
/**
*
* 新增表单
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
tenantId: unref(tenantId),
packType:'custom',
showFooter: true
});
}
/**
* 产品包下面的用户
* @param record
*/
function seeTenantPackUser(record) {
packUserOpenModal(true,{
record:record
})
}
/**
* 更多
* @param record
*/
function getDropDownAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '删除',
popConfirm: {
title: '是否确认删除租户产品包',
confirm: handleDelete.bind(null, record),
},
},
]
}
/**
* 详情
* @param record
*/
function handleDetail(record) {
openModal(true, {
isUpdate: true,
record: record,
tenantId: unref(tenantId),
packType:'custom',
showFooter: false
});
}
</script>

View File

@ -0,0 +1,67 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit" width="800px" destroyOnClose>
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts" setup name="tenant-pack-menu-modal">
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form';
import { packMenuFormSchema } from '../tenant.data';
import { addPackPermission, editPackPermission } from '../tenant.api';
const isUpdate = ref<boolean>(false);
// Emits声明
const emit = defineEmits(['register', 'success']);
//表单配置
const [registerForm, { resetFields, setFieldsValue, validate, setProps }] = useForm({
schemas: packMenuFormSchema,
showActionButtonGroup: false,
});
//租户
const tenantId = ref<number>();
//产品包类型
const packType = ref<number>();
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
await resetFields();
isUpdate.value = !!data?.isUpdate;
if(data.tenantId){
tenantId.value = data.tenantId;
}
packType.value = data.packType;
if (unref(isUpdate)) {
//表单赋值
console.log(data.record)
await setFieldsValue({ ...data.record });
}
//update-begin---author:wangshuai ---date:20230705 for【QQYUN-5685】2 产品包增加一个查看:添加底部有没有按钮及表单禁用------------
setModalProps({ confirmLoading: false, showCancelBtn:!!data?.showFooter, showOkBtn:!!data?.showFooter });
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter })
//update-end---author:wangshuai ---date:20230705 for【QQYUN-5685】2 产品包增加一个查看:添加底部有没有按钮及表单禁用------------
});
//设置标题
const title = computed(() => (unref(isUpdate) ? '编辑租户产品包' : '新增租户产品包'));
//表单提交事件
async function handleSubmit(v) {
const values = await validate();
setModalProps({ confirmLoading: true });
values.packType = unref(packType);
if(values.packType === 'custom'){
values.tenantId = unref(tenantId);
}else{
values.tenantId = 0;
}
if (!unref(isUpdate)) {
await addPackPermission(values);
} else {
await editPackPermission(values);
}
emit('success');
setModalProps({ confirmLoading: false });
closeModal();
}
</script>

View File

@ -0,0 +1,170 @@
<template>
<BasicModal @register="registerModal" destroyOnClose :title="title" :width="1000" :footer="null">
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<template #departNames="{ text, record }">
<template v-if="text && text.length > 0">
{{ getName(text) }}
</template>
</template>
<template #positionNames="{ text, record }">
<template v-if="text && text.length > 0">
{{ getName(text) }}
</template>
</template>
<template #tableTitle>
<a-button preIcon="ant-design:usergroup-add-outlined" type="primary" @click="addUser">邀请成员</a-button>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
<tenant-user-select-modal :multi="true" @register="registerUserModal" @on-select="onSelected" :tenantId="getTenantId"></tenant-user-select-modal>
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, reactive, ref } from 'vue';
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
import { BasicTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { tenantPackUserColumns } from '../tenant.data';
import { queryTenantPackUserList, deleteTenantPackUser, addTenantPackUser } from '../tenant.api';
import TenantUserSelectModal from '../components/TenantUserSelectModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useUserStore } from '/@/store/modules/user';
export default defineComponent({
name: 'TenantPackUserModal',
components: { BasicModal, BasicTable, TableAction, TenantUserSelectModal },
setup() {
//获取租户id
const getTenantId = computed(()=>{
return tenantPackData.tenantId;
})
//产品包信息
const tenantPackData = reactive<any>({});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
setModalProps({ confirmLoading: false, showCancelBtn: true, showOkBtn: false });
Object.assign(tenantPackData, data.record);
await reload();
});
const { createMessage } = useMessage();
//设置标题
const title = ref<string>('用户');
//注册table数据
const { tableContext } = useListPage({
tableProps: {
api: queryTenantPackUserList,
immediate: false,
columns: tenantPackUserColumns,
canResize: false,
useSearchForm: false,
beforeFetch: (params) => {
params.tenantId = tenantPackData.tenantId;
params.packId = tenantPackData.id;
params.status = 1;
return params;
},
actionColumn: {
width: 120,
fixed: 'right',
},
},
});
const [registerUserModal, { openModal: openUserModal, closeModal: closeUserModal }] = useModal();
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 获取部门/职务名称
* @param value
*/
function getName(value) {
return value.join(',');
}
/**
* 表格操作列
* @param record
*/
function getTableAction(record) {
return [
{
label: '移除',
popConfirm: {
title: '是否确认移除',
confirm: handleDelete.bind(null, record),
}
},
];
}
/**
* 删除
*/
async function handleDelete(record) {
let params = {
packId: record.packId,
packName: record.packName,
tenantId: tenantPackData.tenantId,
userId: record.id,
realname: record.realname,
};
await deleteTenantPackUser(params);
await reload();
}
/**
* 添加用户弹窗
*/
function addUser() {
openUserModal(true, {
list: [],
});
}
/**
* 邀请人回调事件
* @param arr
*/
async function onSelected(arr) {
if (arr && arr.length > 0) {
let names: any[] = [];
let ids: any[] = [];
for (let u of arr) {
names.push(u.realname);
ids.push(u.id);
}
console.log(tenantPackData);
let params = {
packId: tenantPackData.id,
packName: tenantPackData.packName,
tenantId: tenantPackData.tenantId,
userId: ids.join(','),
realname: names.join(','),
};
await addTenantPackUser(params);
await reload();
}
closeUserModal();
}
return {
title,
registerModal,
registerTable,
rowSelection,
getName,
getTableAction,
registerUserModal,
addUser,
onSelected,
getTenantId,
};
},
});
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,243 @@
import { defHttp } from '/@/utils/http/axios';
import { Modal } from 'ant-design-vue';
import { getTenantId } from "/@/utils/auth";
enum Api {
list = '/sys/tenant/list',
save = '/sys/tenant/add',
edit = '/sys/tenant/edit',
get = '/sys/tenant/queryById',
delete = '/sys/tenant/delete',
deleteBatch = '/sys/tenant/deleteBatch',
getCurrentUserTenants = '/sys/tenant/getCurrentUserTenant',
invitationUserJoin = '/sys/tenant/invitationUserJoin',
getTenantUserList = '/sys/tenant/getTenantUserList',
leaveTenant = '/sys/tenant/leaveTenant',
packList = '/sys/tenant/packList',
addPackPermission = '/sys/tenant/addPackPermission',
editPackPermission = '/sys/tenant/editPackPermission',
deleteTenantPack = '/sys/tenant/deleteTenantPack',
recycleBinPageList = '/sys/tenant/recycleBinPageList',
deleteLogicDeleted = '/sys/tenant/deleteLogicDeleted',
revertTenantLogic = '/sys/tenant/revertTenantLogic',
//用户产品包关系api
queryTenantPackUserList = '/sys/tenant/queryTenantPackUserList',
deleteTenantPackUser = '/sys/tenant/deleteTenantPackUser',
addTenantPackUser = '/sys/tenant/addTenantPackUser',
//获取用户租户列表
getTenantPageListByUserId = '/sys/tenant/getTenantPageListByUserId',
//新增、编辑用户租户
saveUser = '/sys/user/add',
editUser = '/sys/user/editTenantUser',
}
/**
* 查询租户列表
* @param params
*/
export const getTenantList = (params) => {
return defHttp.get({ url: Api.list, params });
};
/**
* 保存或者更新租户
* @param params
*/
export const saveOrUpdateTenant = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
/**
* 查询租户详情
* @param params
*/
export const getTenantById = (params) => {
return defHttp.get({ url: Api.get, params });
};
/**
* 删除租户
* @param params
*/
export const deleteTenant = (params, handleSuccess) => {
return defHttp.delete({ url: Api.delete, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
* 批量删除租户
* @param params
*/
export const batchDeleteTenant = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
* 获取登录用户部门信息
*/
export const getUserTenants = (params?) => defHttp.get({ url: Api.getCurrentUserTenants, params });
/**
* 邀请用户加入租户
* @param params
*/
export const invitationUserJoin = (params) => defHttp.put({ url: Api.invitationUserJoin, params }, { joinParamsToUrl: true });
/**
* 通过租户id获取数据
* @param params
*/
export const getTenantUserList = (params) => {
return defHttp.get({ url: Api.getTenantUserList, params });
};
/**
* 用户离开租户
* @param params
*/
export const leaveTenant = (params, handleSuccess) => {
Modal.confirm({
title: '请离',
content: '是否请离该用户',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.put({ url: Api.leaveTenant, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
* 获取产品包列表
* @param params
*/
export const packList = (params) => {
return defHttp.get({ url: Api.packList, params });
};
/**
* 添加菜单
* @param params
*/
export const addPackPermission = (params) => {
return defHttp.post({ url: Api.addPackPermission, params });
};
/**
* 添加菜单
* @param params
*/
export const editPackPermission = (params) => {
return defHttp.put({ url: Api.editPackPermission, params });
};
/**
* 删除菜单
* @param params
*/
export const deleteTenantPack = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteTenantPack, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
* 获取租户回收站的列表
* @param params
*/
export const recycleBinPageList = (params) => {
return defHttp.get({ url: Api.recycleBinPageList, params });
};
/**
* 租户彻底删除
* @param params
*/
export const deleteLogicDeleted = (params,handleSuccess) => {
return defHttp.delete({ url: Api.deleteLogicDeleted, params },{ joinParamsToUrl: true }).then(() => {
handleSuccess();
}).catch(()=>{
handleSuccess();
});
};
/**
* 租户还原
* @param params
*/
export const revertTenantLogic = (params,handleSuccess) => {
return defHttp.put({ url: Api.revertTenantLogic, params },{ joinParamsToUrl: true }).then(() => {
handleSuccess();
})
};
/**
* 获取租户产品包下面的用户
* @param params
*/
export const queryTenantPackUserList = (params) => {
return defHttp.get({ url: Api.queryTenantPackUserList, params });
};
/**
* 移除用户和产品包的关系数据
* @param params
*/
export const deleteTenantPackUser = (params)=>{
return defHttp.put({ url: Api.deleteTenantPackUser, params });
}
/**
* 添加用户和产品包的关系数据
* @param params
*/
export const addTenantPackUser = (params)=>{
return defHttp.post({ url: Api.addTenantPackUser, params });
}
/**
* 查询用户租户列表
* @param params
*/
export const getTenantPageListByUserId = (params) => {
return defHttp.get({ url: Api.getTenantPageListByUserId, params });
};
/**
* 获取当前登录租户名称
*/
export async function getLoginTenantName() {
let tenantId = getTenantId();
if(tenantId){
let result = await getTenantById({ id:tenantId });
if(result){
return result.name;
}
}
return "空";
}
/**
* 保存或者更新用户
* @param params
*/
export const saveOrUpdateTenantUser = (params, isUpdate) => {
let url = isUpdate ? Api.editUser : Api.saveUser;
return defHttp.post({ url: url, params },{ joinParamsToUrl: true });
};

View File

@ -0,0 +1,461 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
import { getAutoScrollContainer } from '/@/utils/common/compUtils';
import { render } from "/@/utils/common/renderUtils";
import { rules } from "/@/utils/helper/validator";
export const columns: BasicColumn[] = [
{
title: '租户名称',
dataIndex: 'name',
width: 200,
align: 'left',
},
{
title: '租户编号(ID)',
dataIndex: 'id',
width: 180,
},{
title: '组织LOGO',
dataIndex: 'companyLogo',
width: 100,
customRender: ({ text }) => {
if(!text){
return text;
}
return render.renderImage({text});
},
},
{
dataIndex: 'trade_dictText',
title: '所属行业',
width: 150
},
{
dataIndex: 'companySize_dictText',
title: '公司规模',
width: 100
},
{
dataIndex: 'houseNumber',
title: '门牌号',
width: 100,
},
{
dataIndex: 'position_dictText',
title: '职级',
width: 150
},
{
dataIndex: 'department_dictText',
title: '部门',
width: 150
},
{
dataIndex: 'createBy_dictText',
title: '创建者(拥有者)',
width: 150
},
/* {
title: '开始时间',
dataIndex: 'beginDate',
sorter: true,
width: 180,
},
{
title: '结束时间',
dataIndex: 'endDate',
sorter: true,
width: 180,
},*/
{
title: '状态',
dataIndex: 'status_dictText',
width: 100,
},
];
export const searchFormSchema: FormSchema[] = [
{
field: 'name',
label: '租户名称',
component: 'Input',
colProps: { span: 8 },
},
{
field: 'status',
label: '状态',
component: 'Select',
componentProps: {
options: [
{ label: '正常', value: 1 },
{ label: '冻结', value: 0 },
],
},
colProps: { span: 8 },
},
// {
// field: 'fieldTime',
// component: 'RangePicker',
// label: '时间字段',
// componentProps: {
// valueType: 'Date',
// },
// colProps: {
// span: 8,
// },
// },
];
export const formSchema: FormSchema[] = [
{
field: 'name',
label: '租户名称',
component: 'Input',
required: true,
},
{
field: 'id',
label: '租户编号(ID)',
component: 'InputNumber',
required: true,
ifShow: ({ values }) => {
return values.id!=null;
},
},
{
field: 'companyLogo',
label: '组织LOGO',
component: 'JImageUpload',
componentProps:{
text:'logo'
}
},
{
field: 'trade',
label: '所属行业',
component: 'JDictSelectTag',
componentProps: {
dictCode:'trade',
}
}, {
field: 'companySize',
label: '公司规模',
component: 'JDictSelectTag',
componentProps: {
dictCode:'company_size',
}
}, {
field: 'companyAddress',
label: '公司地址',
component: 'InputTextArea',
componentProps: {
placeholder: '请输入公司地址',
rows: 4,
}
},
/* {
field: 'beginDate',
label: '开始时间',
component: 'DatePicker',
componentProps: {
showTime: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss',
getPopupContainer: getAutoScrollContainer,
},
},
{
field: 'endDate',
label: '结束时间',
component: 'DatePicker',
componentProps: {
showTime: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss',
getPopupContainer: getAutoScrollContainer,
},
},*/
{
field: 'houseNumber',
label: '门牌号',
component: 'Input',
dynamicDisabled: true,
ifShow: ({ values }) => {
return values.id!=null;
},
},
{
field: 'position',
label: '职级',
component: 'JDictSelectTag',
componentProps:{
dictCode: 'company_rank'
}
},
{
field: 'department',
label: '部门',
component: 'JDictSelectTag',
componentProps:{
dictCode:'company_department'
}
},
{
field: 'status',
label: '状态',
component: 'RadioButtonGroup',
defaultValue: 1,
componentProps: {
options: [
{ label: '正常', value: 1 },
{ label: '冻结', value: 0 },
],
},
},
];
//定义用户表格列
export const userColumns: BasicColumn[] =[
{
title: '用户账号',
dataIndex: 'username',
width: 100,
align: 'left',
},
{
title: '用户姓名',
dataIndex: 'realname',
width: 100,
},
{
title: '性别',
dataIndex: 'sex_dictText',
width: 100,
},
{
title: '手机号码',
dataIndex: 'phone',
width: 100,
},
];
//邀请用户搜索表单
export const userSearchFormSchema: FormSchema[] = [
{
field: 'username',
label: '账号',
component: 'Input',
},
{
field: 'realname',
label: '姓名',
component: 'Input',
},
];
//产品包列表
export const packColumns: BasicColumn[] = [
{
title: '产品包名称',
dataIndex: 'packName',
width: 100,
},
{
title: '状态',
dataIndex: 'status',
width: 100,
customRender: ({ text }) => {
if (text === '1') {
return '开启';
} else {
return '关闭';
}
},
},
{
title: '备注',
dataIndex: 'remarks',
width: 150,
},
];
//产品包搜索表单
export const packFormSchema: FormSchema[] = [
{
field: 'packName',
label: '产品包名称',
component: 'JInput',
colProps: { xxl: 8 },
},
];
//产品包表单
export const packMenuFormSchema: FormSchema[] = [
{
field: 'packName',
label: '产品包名称',
component: 'Input',
},
{
field: 'permissionIds',
label: '菜单列表',
component: 'JTreeSelect',
componentProps: {
dict: 'sys_permission,name,id',
pidField: 'parent_id',
multiple: true,
treeCheckAble:true,
treeCheckStrictly: true,
getPopupContainer: () => document.body,
},
},
{
field: 'remarks',
label: '描述',
component: 'InputTextArea',
},
{
field: 'status',
label: '开启状态',
component: 'Switch',
componentProps: {
checkedValue: '1',
checkedChildren: '开启',
unCheckedValue: '0',
unCheckedChildren: '关闭',
},
defaultValue: '1',
},
{
field: 'id',
label: '开启状态',
component: 'Input',
show: false
},
];
//回收站列表
export const recycleColumns : BasicColumn[] = [
{
title: '租户名称',
dataIndex: 'name',
width: 100,
align: 'left',
},
{
title: '租户编号(ID)',
dataIndex: 'id',
width: 100,
},
{
title: '组织LOGO',
dataIndex: 'companyLogo',
width: 100,
customRender: ({ text }) => {
if(!text){
return text;
}
return render.renderImage({text});
},
},
{
dataIndex: 'houseNumber',
title: '门牌号',
width: 100,
}
]
//租户回收站搜索表单
export const searchRecycleFormSchema : FormSchema[] = [
{
field: 'name',
label: '租户名称',
component: 'Input',
},
{
field: 'houseNumber',
label: '门牌号',
component: 'Input',
},
]
//产品包用户列表
export const tenantPackUserColumns: BasicColumn[] = [
{
title: '用户',
dataIndex: 'realname',
width: 200,
},
{
title: '部门',
dataIndex: 'departNames',
width: 200,
ellipsis: true,
slots: { customRender: 'departNames' }
},
{
title: '职位',
dataIndex: 'positionNames',
ellipsis: true,
width: 200,
slots: { customRender: 'positionNames' }
}
]
/**
* 用户租户新增编辑表单
*/
export const tenantUserSchema: FormSchema[] = [
{ field: 'id', label: 'id', component: 'Input', show: false },
{ field: 'username', label: 'username', component: 'Input', show: false },
{
field: 'realname',
label: '姓名',
component: 'Input',
dynamicDisabled: ({ values }) => {
return !!values.id;
},
},
{
field: 'phone',
label: '手机',
component: 'Input',
dynamicRules: ({ model, schema }) => {
if (model.id) {
return [];
}
return [{ ...rules.phone(true)[0] }, { ...rules.duplicateCheckRule('sys_user', 'phone', model, schema, false)[0] }];
},
dynamicDisabled: ({ values }) => {
return !!values.id;
},
},
{
field: 'email',
label: '邮箱',
component: 'Input',
dynamicRules: ({ model, schema }) => {
if (model.id) {
return [];
}
return [{ ...rules.email(true)[0] }, { ...rules.duplicateCheckRule('sys_user', 'email', model, schema, false)[0] }];
},
dynamicDisabled: ({ values }) => {
return !!values.id;
},
},
{ field: 'selecteddeparts', label: '部门', component: 'JSelectDept', componentProps: { checkStrictly: true } },
{
field: 'post',
label: '职位',
component: 'JSelectPosition',
},
{
field: 'workNo',
label: '工号',
component: 'Input',
dynamicRules: ({ model, schema }) => {
return [{ required: true, 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 },
];