Showing
5 changed files
with
614 additions
and
96 deletions
| 1 | import { AccountParams } from './model/systemModel'; | 1 | import { AccountParams } from './model/systemModel'; |
| 2 | import { defHttp } from '/@/utils/http/axios'; | 2 | import { defHttp } from '/@/utils/http/axios'; |
| 3 | enum Api { | 3 | enum Api { |
| 4 | - TENANT_List = '/user/tenantt/page', | 4 | + GET_TENANT_List = '/user/tenant/page', |
| 5 | + ADD_TANANT_LIST = '/user/save_common_tenant', | ||
| 5 | } | 6 | } |
| 6 | 7 | ||
| 7 | export const getTenantList = (params: AccountParams) => { | 8 | export const getTenantList = (params: AccountParams) => { |
| 8 | - const url = Api.TENANT_List; | 9 | + const url = Api.GET_TENANT_List; |
| 9 | return defHttp.get({ url: url, params }); | 10 | return defHttp.get({ url: url, params }); |
| 10 | }; | 11 | }; |
| 12 | +export const addTenantList = (params: AccountParams) => { | ||
| 13 | + const url = Api.ADD_TANANT_LIST; | ||
| 14 | + return defHttp.post({ url: url, params }); | ||
| 15 | +}; |
| @@ -94,12 +94,17 @@ export const getAllRoleList = async (params?: RoleParams) => { | @@ -94,12 +94,17 @@ export const getAllRoleList = async (params?: RoleParams) => { | ||
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | // 过滤角色列表----根据登录的账号所属的角色-过滤掉其他平台类型的角色 | 96 | // 过滤角色列表----根据登录的账号所属的角色-过滤掉其他平台类型的角色 |
| 97 | -export const filterRoleList = async () => { | ||
| 98 | - const res = await defHttp.post<RoleListGetResultModel>({ url: Api.GetAllRoleList }); | 97 | +export const filterRoleList = async (params?: { roleType: string }) => { |
| 98 | + const res = await defHttp.post<RoleListGetResultModel>({ | ||
| 99 | + url: Api.GetAllRoleList, | ||
| 100 | + params: params, | ||
| 101 | + }); | ||
| 99 | const userInfo: any = getAuthCache(USER_INFO_KEY); | 102 | const userInfo: any = getAuthCache(USER_INFO_KEY); |
| 100 | const role = userInfo.roles[0]; | 103 | const role = userInfo.roles[0]; |
| 101 | const options = res.filter((item) => { | 104 | const options = res.filter((item) => { |
| 102 | - if (role === 'SYS_ADMIN' || role === 'PLATFORM_ADMIN') { | 105 | + if (params?.roleType && params.roleType === 'TENANT_ADMIN') { |
| 106 | + return item; | ||
| 107 | + } else if (role === 'SYS_ADMIN' || role === 'PLATFORM_ADMIN') { | ||
| 103 | return item.roleType === 'PLATFORM_ADMIN'; | 108 | return item.roleType === 'PLATFORM_ADMIN'; |
| 104 | } else { | 109 | } else { |
| 105 | return item.roleType === 'CUSTOMER_USER'; | 110 | return item.roleType === 'CUSTOMER_USER'; |
| 1 | +<template> | ||
| 2 | + <BasicModal | ||
| 3 | + width="650px" | ||
| 4 | + v-bind="$attrs" | ||
| 5 | + @register="registerModal" | ||
| 6 | + :title="getTitle" | ||
| 7 | + @ok="handleSubmit" | ||
| 8 | + > | ||
| 9 | + <div style="height: 40vh"> | ||
| 10 | + <BasicForm @register="registerForm"> | ||
| 11 | + <template #organizationId="{ model, field }"> | ||
| 12 | + <Button type="link" @click="handleOpenCreate" style="padding: 0; z-index: 9999" | ||
| 13 | + >新增组织 | ||
| 14 | + </Button> | ||
| 15 | + <BasicTree | ||
| 16 | + v-if="organizationTreeData.length" | ||
| 17 | + v-model:value="model[field]" | ||
| 18 | + :treeData="organizationTreeData" | ||
| 19 | + :checked-keys="checkGroup" | ||
| 20 | + :expandedKeys="treeExpandData" | ||
| 21 | + ref="basicTreeRef" | ||
| 22 | + @check="handleCheckClick" | ||
| 23 | + @unSelectAll="handleUnSelectAll" | ||
| 24 | + @strictlyStatus="handleStrictlyStatus" | ||
| 25 | + checkable | ||
| 26 | + toolbar | ||
| 27 | + @change="handleTreeSelect" | ||
| 28 | + /> | ||
| 29 | + </template> | ||
| 30 | + <template #roleSlot="{ model, field }"> | ||
| 31 | + <a-select | ||
| 32 | + mode="multiple" | ||
| 33 | + allowClear | ||
| 34 | + placeholder="请选择角色" | ||
| 35 | + v-model:value="model[field]" | ||
| 36 | + @change="handleRoleSelect" | ||
| 37 | + :options="roleOptions.map((item) => ({ value: item.value, label: item.label }))" | ||
| 38 | + > | ||
| 39 | + <template #dropdownRender="{ menuNode: menu }"> | ||
| 40 | + <v-nodes :vnodes="menu" /> | ||
| 41 | + <a-divider style="margin: 4px 0" /> | ||
| 42 | + <div @click="handleOpenRole" style="padding: 4px 0; cursor: pointer"> | ||
| 43 | + <plus-outlined /> | ||
| 44 | + 新增角色 | ||
| 45 | + </div> | ||
| 46 | + </template> | ||
| 47 | + </a-select> | ||
| 48 | + </template> | ||
| 49 | + </BasicForm> | ||
| 50 | + | ||
| 51 | + <OrganizationDrawer @register="registerDrawer" @success="handleReload" /> | ||
| 52 | + </div> | ||
| 53 | + </BasicModal> | ||
| 54 | + <RoleDrawer @register="registerRoleDrawer" @success="handleSuccess" /> | ||
| 55 | +</template> | ||
| 56 | +<script lang="ts"> | ||
| 57 | + import { defineComponent, ref, computed, unref, reactive, onMounted } from 'vue'; | ||
| 58 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 59 | + import { BasicForm, useForm } from '/@/components/Form/index'; | ||
| 60 | + import { accountFormSchema } from './config'; | ||
| 61 | + import { Button } from 'ant-design-vue'; | ||
| 62 | + import { findCurrentUserRelation, filterRoleList } from '/@/api/system/system'; | ||
| 63 | + import { addTenantList } from '/@/api/system/account'; | ||
| 64 | + import { BasicTree, TreeItem, CheckKeys, CheckEvent } from '/@/components/Tree'; | ||
| 65 | + import { findCurrentUserGroups } from '/@/api/system/group'; | ||
| 66 | + import { RoleOrOrganizationParam } from '/@/api/system/model/systemModel'; | ||
| 67 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 68 | + import { copyTransTreeFun } from '/@/utils/fnUtils'; | ||
| 69 | + import { TOption } from '/@/views/rule/linkedge/config/config.data'; | ||
| 70 | + import { PlusOutlined } from '@ant-design/icons-vue'; | ||
| 71 | + import { useDrawer } from '/@/components/Drawer'; | ||
| 72 | + import RoleDrawer from '../../role/RoleDrawer.vue'; | ||
| 73 | + import OrganizationDrawer from '/@/views/system/organization/OrganizationDrawer.vue'; | ||
| 74 | + | ||
| 75 | + export default defineComponent({ | ||
| 76 | + name: 'TenantModal', | ||
| 77 | + components: { | ||
| 78 | + BasicModal, | ||
| 79 | + BasicForm, | ||
| 80 | + Button, | ||
| 81 | + BasicTree, | ||
| 82 | + OrganizationDrawer, | ||
| 83 | + PlusOutlined, | ||
| 84 | + RoleDrawer, | ||
| 85 | + VNodes: (_, { attrs }) => { | ||
| 86 | + return attrs.vnodes; | ||
| 87 | + }, | ||
| 88 | + }, | ||
| 89 | + emits: ['success', 'register'], | ||
| 90 | + setup(_, { emit }) { | ||
| 91 | + const [registerRoleDrawer, { openDrawer }] = useDrawer(); | ||
| 92 | + const { createMessage } = useMessage(); | ||
| 93 | + | ||
| 94 | + const roleOptions = ref<TOption[]>([]); | ||
| 95 | + const isUpdate = ref(true); | ||
| 96 | + const rowId = ref(''); | ||
| 97 | + const organizationTreeData = ref<TreeItem[]>([]); | ||
| 98 | + const basicTreeRef = ref(); | ||
| 99 | + const checkGroup = ref<string[]>([]); | ||
| 100 | + const treeExpandData = ref([]); | ||
| 101 | + const olderPhoneNumber = ref(); | ||
| 102 | + const singleEditPostPhoneNumber = reactive({ | ||
| 103 | + phoneNumber: '', | ||
| 104 | + }); | ||
| 105 | + const checkedKeysWithHalfChecked = ref<(string | number)[]>([]); | ||
| 106 | + const getRoleList = async () => { | ||
| 107 | + const res = await filterRoleList({ roleType: 'TENANT_ADMIN' }); | ||
| 108 | + roleOptions.value = res.map((m) => { | ||
| 109 | + return { | ||
| 110 | + label: m.name, | ||
| 111 | + value: m.id, | ||
| 112 | + }; | ||
| 113 | + }); | ||
| 114 | + }; | ||
| 115 | + | ||
| 116 | + onMounted(async () => { | ||
| 117 | + await getRoleList(); | ||
| 118 | + }); | ||
| 119 | + const handleOpenRole = () => { | ||
| 120 | + openDrawer(true, { | ||
| 121 | + isUpdate: false, | ||
| 122 | + }); | ||
| 123 | + }; | ||
| 124 | + const clearValidateByField = (field: string) => { | ||
| 125 | + clearValidate(field); | ||
| 126 | + }; | ||
| 127 | + const handleRoleSelect = (e) => { | ||
| 128 | + if (e?.length > 0) clearValidateByField('roleIds'); | ||
| 129 | + else validateFields(['roleIds']); | ||
| 130 | + }; | ||
| 131 | + const handleTreeSelect = (e) => { | ||
| 132 | + if (e) clearValidateByField('organizationIds'); | ||
| 133 | + }; | ||
| 134 | + const handleSuccess = async () => { | ||
| 135 | + await getRoleList(); | ||
| 136 | + }; | ||
| 137 | + const [ | ||
| 138 | + registerForm, | ||
| 139 | + { | ||
| 140 | + setFieldsValue, | ||
| 141 | + updateSchema, | ||
| 142 | + resetFields, | ||
| 143 | + validate, | ||
| 144 | + getFieldsValue, | ||
| 145 | + clearValidate, | ||
| 146 | + validateFields, | ||
| 147 | + }, | ||
| 148 | + ] = useForm({ | ||
| 149 | + labelWidth: 100, | ||
| 150 | + schemas: accountFormSchema, | ||
| 151 | + showActionButtonGroup: false, | ||
| 152 | + actionColOptions: { | ||
| 153 | + span: 18, | ||
| 154 | + }, | ||
| 155 | + }); | ||
| 156 | + //获取所有父级id | ||
| 157 | + function findForAllId(data = [], arr = []) { | ||
| 158 | + for (const item of data) { | ||
| 159 | + arr.push(item.id); | ||
| 160 | + } | ||
| 161 | + return arr; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { | ||
| 165 | + await resetFields(); | ||
| 166 | + setModalProps({ confirmLoading: false }); | ||
| 167 | + isUpdate.value = !!data?.isUpdate; | ||
| 168 | + const groupListModel = await findCurrentUserGroups(); | ||
| 169 | + if (!unref(organizationTreeData).length) { | ||
| 170 | + copyTransTreeFun(groupListModel); | ||
| 171 | + organizationTreeData.value = groupListModel; | ||
| 172 | + const getAllIds = findForAllId(organizationTreeData.value as any, []); | ||
| 173 | + //设置要展开的id | ||
| 174 | + treeExpandData.value = getAllIds; | ||
| 175 | + } | ||
| 176 | + if (unref(isUpdate)) { | ||
| 177 | + rowId.value = data.record.id; | ||
| 178 | + const roleParams = new RoleOrOrganizationParam(rowId.value, true, false); | ||
| 179 | + olderPhoneNumber.value = data.record.phoneNumber; | ||
| 180 | + singleEditPostPhoneNumber.phoneNumber = data.record.phoneNumber; | ||
| 181 | + findCurrentUserRelation(roleParams).then((result) => { | ||
| 182 | + Reflect.set(data.record, 'roleIds', result); | ||
| 183 | + Reflect.set(data.record, 'password', '******'); | ||
| 184 | + setFieldsValue(data.record); | ||
| 185 | + }); | ||
| 186 | + const organizationParams = new RoleOrOrganizationParam(rowId.value, false, true); | ||
| 187 | + checkGroup.value = await findCurrentUserRelation(organizationParams); | ||
| 188 | + } | ||
| 189 | + await updateSchema([ | ||
| 190 | + { | ||
| 191 | + field: 'username', | ||
| 192 | + dynamicDisabled: unref(isUpdate), | ||
| 193 | + }, | ||
| 194 | + { | ||
| 195 | + field: 'password', | ||
| 196 | + ifShow: !unref(isUpdate), | ||
| 197 | + }, | ||
| 198 | + ]); | ||
| 199 | + }); | ||
| 200 | + const getTitle = computed(() => (!unref(isUpdate) ? '新增账号' : '编辑账号')); | ||
| 201 | + | ||
| 202 | + async function handleSubmit() { | ||
| 203 | + setModalProps({ confirmLoading: true }); | ||
| 204 | + try { | ||
| 205 | + await validate(); | ||
| 206 | + const values = getFieldsValue(); | ||
| 207 | + await addTenantList({ ...values, level: 4 }); | ||
| 208 | + createMessage.success('操作成功'); | ||
| 209 | + closeModal(); | ||
| 210 | + emit('success'); | ||
| 211 | + } finally { | ||
| 212 | + setModalProps({ confirmLoading: false }); | ||
| 213 | + } | ||
| 214 | + } | ||
| 215 | + // 取消全部的时候清除回显时获取的 | ||
| 216 | + const handleUnSelectAll = () => { | ||
| 217 | + checkedKeysWithHalfChecked.value = []; | ||
| 218 | + }; | ||
| 219 | + | ||
| 220 | + const strictlyStatus = ref(false); //层级关联或独立的状态 false为层级关联 true为层级独立 | ||
| 221 | + | ||
| 222 | + const handleStrictlyStatus = (status) => (strictlyStatus.value = status); | ||
| 223 | + | ||
| 224 | + const handleCheckClick = (selectedKeys: CheckKeys, event: CheckEvent) => { | ||
| 225 | + //fix 取消层级独立后selectedKeys不是数组,是{checked:[],halfChecked:[]}对象 迭代报错 | ||
| 226 | + // 层级独立 | ||
| 227 | + if (strictlyStatus.value) { | ||
| 228 | + if (!Array.isArray(selectedKeys)) { | ||
| 229 | + selectedKeys = selectedKeys?.checked; | ||
| 230 | + event.halfCheckedKeys = []; | ||
| 231 | + } | ||
| 232 | + } else { | ||
| 233 | + // 层级关联 | ||
| 234 | + event.halfCheckedKeys = []; | ||
| 235 | + } | ||
| 236 | + checkedKeysWithHalfChecked.value = [ | ||
| 237 | + ...selectedKeys, | ||
| 238 | + ...(event.halfCheckedKeys as string[]), | ||
| 239 | + ]; | ||
| 240 | + }; | ||
| 241 | + | ||
| 242 | + const [registerDrawer, { openDrawer: addOpenDrawer }] = useDrawer(); | ||
| 243 | + | ||
| 244 | + const handleOpenCreate = () => { | ||
| 245 | + addOpenDrawer(true, { isUpdate: false }); | ||
| 246 | + }; | ||
| 247 | + const handleReload = async () => { | ||
| 248 | + const groupListModel = await findCurrentUserGroups(); | ||
| 249 | + copyTransTreeFun(groupListModel); | ||
| 250 | + organizationTreeData.value = groupListModel; | ||
| 251 | + }; | ||
| 252 | + | ||
| 253 | + return { | ||
| 254 | + registerModal, | ||
| 255 | + registerForm, | ||
| 256 | + handleSubmit, | ||
| 257 | + getTitle, | ||
| 258 | + organizationTreeData, | ||
| 259 | + checkGroup, | ||
| 260 | + basicTreeRef, | ||
| 261 | + treeExpandData, | ||
| 262 | + roleOptions, | ||
| 263 | + registerRoleDrawer, | ||
| 264 | + handleOpenRole, | ||
| 265 | + handleSuccess, | ||
| 266 | + handleRoleSelect, | ||
| 267 | + handleTreeSelect, | ||
| 268 | + handleCheckClick, | ||
| 269 | + handleUnSelectAll, | ||
| 270 | + handleStrictlyStatus, | ||
| 271 | + handleOpenCreate, | ||
| 272 | + registerDrawer, | ||
| 273 | + handleReload, | ||
| 274 | + }; | ||
| 275 | + }, | ||
| 276 | + }); | ||
| 277 | +</script> | ||
| 278 | +<style scoped lang="less"> | ||
| 279 | + :deep(.vben-basic-tree) { | ||
| 280 | + width: 100% !important; | ||
| 281 | + margin-top: -28px !important; | ||
| 282 | + padding: 0; | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + :deep(.is-unflod) { | ||
| 286 | + display: none !important; | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + :deep(.is-flod) { | ||
| 290 | + display: none !important; | ||
| 291 | + } | ||
| 292 | +</style> |
| 1 | +import { IsPhoneExist, isAccountExist } from '/@/api/system/system'; | ||
| 1 | import { BasicColumn, FormSchema } from '/@/components/Table'; | 2 | import { BasicColumn, FormSchema } from '/@/components/Table'; |
| 3 | +import { ChineseRegexp, EmailRegexp, emailRule, phoneRegexp } from '/@/utils/rules'; | ||
| 4 | + | ||
| 5 | +let olderPhoneNumber; | ||
| 2 | 6 | ||
| 3 | export const columns: BasicColumn[] = [ | 7 | export const columns: BasicColumn[] = [ |
| 4 | { | 8 | { |
| @@ -56,3 +60,180 @@ export const searchFormSchema: FormSchema[] = [ | @@ -56,3 +60,180 @@ export const searchFormSchema: FormSchema[] = [ | ||
| 56 | }, | 60 | }, |
| 57 | }, | 61 | }, |
| 58 | ]; | 62 | ]; |
| 63 | + | ||
| 64 | +export const accountFormSchema: FormSchema[] = [ | ||
| 65 | + { | ||
| 66 | + field: 'id', | ||
| 67 | + label: 'id', | ||
| 68 | + component: 'Input', | ||
| 69 | + show: false, | ||
| 70 | + componentProps: { | ||
| 71 | + maxLength: 36, | ||
| 72 | + }, | ||
| 73 | + }, | ||
| 74 | + { | ||
| 75 | + field: 'username', | ||
| 76 | + label: '用户名', | ||
| 77 | + component: 'Input', | ||
| 78 | + colProps: { span: 12 }, | ||
| 79 | + dynamicDisabled: false, | ||
| 80 | + componentProps: { | ||
| 81 | + maxLength: 36, | ||
| 82 | + placeholder: '请输入用户名', | ||
| 83 | + }, | ||
| 84 | + dynamicRules: ({ values }) => { | ||
| 85 | + return [ | ||
| 86 | + { | ||
| 87 | + required: true, | ||
| 88 | + validator(_, value) { | ||
| 89 | + return new Promise((resolve, reject) => { | ||
| 90 | + if (value == '') { | ||
| 91 | + reject('请输入用户名'); | ||
| 92 | + } else if (ChineseRegexp.test(value)) { | ||
| 93 | + reject('用户名不能含有中文'); | ||
| 94 | + } else if (EmailRegexp.test(value)) { | ||
| 95 | + reject('用户名不能为电子邮箱格式'); | ||
| 96 | + } else { | ||
| 97 | + if (values.username != undefined && values.id == undefined) { | ||
| 98 | + isAccountExist(value).then(({ data }) => { | ||
| 99 | + if (data != null) { | ||
| 100 | + reject('用户名已存在'); | ||
| 101 | + } else { | ||
| 102 | + resolve(); | ||
| 103 | + } | ||
| 104 | + }); | ||
| 105 | + } else { | ||
| 106 | + resolve(); | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + }); | ||
| 110 | + }, | ||
| 111 | + }, | ||
| 112 | + ]; | ||
| 113 | + }, | ||
| 114 | + }, | ||
| 115 | + // { | ||
| 116 | + // field: 'password', | ||
| 117 | + // label: '密码', | ||
| 118 | + // component: 'InputPassword', | ||
| 119 | + // required: true, | ||
| 120 | + // colProps: { span: 12 }, | ||
| 121 | + // }, | ||
| 122 | + { | ||
| 123 | + field: 'realName', | ||
| 124 | + label: '真实姓名', | ||
| 125 | + component: 'Input', | ||
| 126 | + colProps: { span: 12 }, | ||
| 127 | + required: true, | ||
| 128 | + componentProps: { | ||
| 129 | + maxLength: 10, | ||
| 130 | + }, | ||
| 131 | + }, | ||
| 132 | + | ||
| 133 | + { | ||
| 134 | + label: '手机号', | ||
| 135 | + field: 'phoneNumber', | ||
| 136 | + component: 'Input', | ||
| 137 | + colProps: { span: 12 }, | ||
| 138 | + dynamicRules: ({ values }) => { | ||
| 139 | + return [ | ||
| 140 | + { | ||
| 141 | + required: true, | ||
| 142 | + validator(_, value) { | ||
| 143 | + return new Promise((resolve, reject) => { | ||
| 144 | + if (value == '') { | ||
| 145 | + reject('请输入手机号'); | ||
| 146 | + } else if (!phoneRegexp.test(value)) { | ||
| 147 | + reject('请输入正确的手机号'); | ||
| 148 | + } else { | ||
| 149 | + if (values.phoneNumber != undefined) { | ||
| 150 | + // 此处可以用防抖函数优化性能 | ||
| 151 | + IsPhoneExist(value).then(({ data }) => { | ||
| 152 | + if (data != null) { | ||
| 153 | + reject('手机号已存在'); | ||
| 154 | + } else { | ||
| 155 | + resolve(); | ||
| 156 | + } | ||
| 157 | + }); | ||
| 158 | + } else { | ||
| 159 | + resolve(); | ||
| 160 | + } | ||
| 161 | + } | ||
| 162 | + }); | ||
| 163 | + }, | ||
| 164 | + }, | ||
| 165 | + ]; | ||
| 166 | + }, | ||
| 167 | + componentProps({ formActionType }) { | ||
| 168 | + const { clearValidate } = formActionType; | ||
| 169 | + return { | ||
| 170 | + onChange(value) { | ||
| 171 | + if (value == olderPhoneNumber) { | ||
| 172 | + clearValidate('phoneNumber'); | ||
| 173 | + } | ||
| 174 | + }, | ||
| 175 | + }; | ||
| 176 | + }, | ||
| 177 | + }, | ||
| 178 | + { | ||
| 179 | + label: '角色', | ||
| 180 | + field: 'roleIds', | ||
| 181 | + component: 'Select', | ||
| 182 | + colProps: { span: 12 }, | ||
| 183 | + slot: 'roleSlot', | ||
| 184 | + rules: [ | ||
| 185 | + { | ||
| 186 | + required: true, | ||
| 187 | + message: '请选择角色', | ||
| 188 | + type: 'array', | ||
| 189 | + }, | ||
| 190 | + ], | ||
| 191 | + }, | ||
| 192 | + { | ||
| 193 | + label: '邮箱', | ||
| 194 | + field: 'email', | ||
| 195 | + component: 'Input', | ||
| 196 | + colProps: { span: 12 }, | ||
| 197 | + rules: emailRule, | ||
| 198 | + }, | ||
| 199 | + // { | ||
| 200 | + // field: 'accountExpireTime', | ||
| 201 | + // label: '有效期', | ||
| 202 | + // component: 'DatePicker', | ||
| 203 | + // colProps: { span: 12 }, | ||
| 204 | + // componentProps: { | ||
| 205 | + // showTime: true, | ||
| 206 | + // format: 'YYYY-MM-DD HH:mm:ss', | ||
| 207 | + // }, | ||
| 208 | + // }, | ||
| 209 | + { | ||
| 210 | + field: 'enabled', | ||
| 211 | + label: '状态', | ||
| 212 | + component: 'RadioButtonGroup', | ||
| 213 | + colProps: { span: 12 }, | ||
| 214 | + defaultValue: true, | ||
| 215 | + componentProps: { | ||
| 216 | + options: [ | ||
| 217 | + { label: '启用', value: true }, | ||
| 218 | + { label: '禁用', value: false }, | ||
| 219 | + ], | ||
| 220 | + }, | ||
| 221 | + }, | ||
| 222 | + // { | ||
| 223 | + // field: 'remark', | ||
| 224 | + // label: '备注', | ||
| 225 | + // component: 'InputTextArea', | ||
| 226 | + // colProps: { span: 24 }, | ||
| 227 | + // componentProps: { | ||
| 228 | + // maxLength: 255, | ||
| 229 | + // placeholder: '请输入备注', | ||
| 230 | + // }, | ||
| 231 | + // }, | ||
| 232 | + { | ||
| 233 | + field: 'organizationIds', | ||
| 234 | + label: '所属组织', | ||
| 235 | + component: 'Input', | ||
| 236 | + slot: 'organizationId', | ||
| 237 | + required: true, | ||
| 238 | + }, | ||
| 239 | +]; |
| 1 | <template> | 1 | <template> |
| 2 | <div> | 2 | <div> |
| 3 | - <BasicTable style="flex: auto" :clickToRowSelect="false" @register="registerTable"> | ||
| 4 | - <template #toolbar> | ||
| 5 | - <Authority value="api:yt:user:post"> | ||
| 6 | - <a-button type="primary" @click="handleCreate">新增账号</a-button> | ||
| 7 | - </Authority> | ||
| 8 | - <Authority value="api:yt:user:delete"> | ||
| 9 | - <Popconfirm | ||
| 10 | - title="您确定要批量删除数据" | ||
| 11 | - ok-text="确定" | ||
| 12 | - cancel-text="取消" | ||
| 13 | - @confirm="() => {}" | 3 | + <PageWrapper dense contentFullHeight contentClass="flex"> |
| 4 | + <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" /> | ||
| 5 | + | ||
| 6 | + <BasicTable | ||
| 7 | + style="flex: auto" | ||
| 8 | + :clickToRowSelect="false" | ||
| 9 | + @register="registerTable" | ||
| 10 | + class="w-3/4 xl:w-4/5" | ||
| 11 | + > | ||
| 12 | + <template #toolbar> | ||
| 13 | + <Authority value="api:yt:user:post"> | ||
| 14 | + <a-button type="primary" @click="handleCreate">新增租户</a-button> | ||
| 15 | + </Authority> | ||
| 16 | + <Authority value="api:yt:user:delete"> | ||
| 17 | + <Popconfirm | ||
| 18 | + title="您确定要批量删除数据" | ||
| 19 | + ok-text="确定" | ||
| 20 | + cancel-text="取消" | ||
| 21 | + @confirm="() => {}" | ||
| 22 | + > | ||
| 23 | + <a-button color="error"> 批量删除 </a-button> | ||
| 24 | + </Popconfirm> | ||
| 25 | + </Authority> | ||
| 26 | + </template> | ||
| 27 | + <template #status="{ record }"> | ||
| 28 | + <Tag | ||
| 29 | + :color=" | ||
| 30 | + record.userStatusEnum === 'NORMAL' | ||
| 31 | + ? 'green' | ||
| 32 | + : record.userStatusEnum === 'DISABLED' | ||
| 33 | + ? 'red' | ||
| 34 | + : 'orange' | ||
| 35 | + " | ||
| 14 | > | 36 | > |
| 15 | - <a-button color="error"> 批量删除 </a-button> | ||
| 16 | - </Popconfirm> | ||
| 17 | - </Authority> | ||
| 18 | - </template> | ||
| 19 | - <template #status="{ record }"> | ||
| 20 | - <Tag | ||
| 21 | - :color=" | ||
| 22 | - record.userStatusEnum === 'NORMAL' | ||
| 23 | - ? 'green' | ||
| 24 | - : record.userStatusEnum === 'DISABLED' | ||
| 25 | - ? 'red' | ||
| 26 | - : 'orange' | ||
| 27 | - " | ||
| 28 | - > | ||
| 29 | - {{ | ||
| 30 | - record.userStatusEnum === 'NORMAL' | ||
| 31 | - ? '正常' | ||
| 32 | - : record.userStatusEnum === 'DISABLED' | ||
| 33 | - ? '已禁用' | ||
| 34 | - : '已过期' | ||
| 35 | - }} | ||
| 36 | - </Tag> | ||
| 37 | - </template> | ||
| 38 | - <template #action="{ record }"> | ||
| 39 | - <TableAction | ||
| 40 | - :actions="[ | ||
| 41 | - // { | ||
| 42 | - // label: '进入', | ||
| 43 | - // icon: 'ant-design:login-outlined', | ||
| 44 | - // tooltip: `以${!isAdmin(role) ? '客户' : '平台'}用户身份登录`, | ||
| 45 | - // onClick: handleLoginCustomAdmin.bind(null, record), | ||
| 46 | - // }, | ||
| 47 | - { | ||
| 48 | - label: '用户详情', | ||
| 49 | - auth: 'api:yt:user:get', | ||
| 50 | - icon: 'clarity:info-standard-line', | ||
| 51 | - tooltip: '用户详情', | ||
| 52 | - onClick: handledetail.bind(null, record), | ||
| 53 | - ifShow: record.level != 0, | ||
| 54 | - }, | ||
| 55 | - { | ||
| 56 | - label: '编辑', | ||
| 57 | - auth: 'api:yt:user:update', | ||
| 58 | - icon: 'clarity:note-edit-line', | ||
| 59 | - tooltip: '编辑', | ||
| 60 | - onClick: handleEdit.bind(null, record), | ||
| 61 | - ifShow: record.level != 0, | ||
| 62 | - }, | ||
| 63 | - ]" | ||
| 64 | - :drop-down-actions="[ | ||
| 65 | - { | ||
| 66 | - label: '删除', | ||
| 67 | - auth: 'api:yt:user:delete', | ||
| 68 | - icon: 'ant-design:delete-outlined', | ||
| 69 | - color: 'error', | ||
| 70 | - tooltip: '删除', | ||
| 71 | - ifShow: record.level != 0, | ||
| 72 | - popConfirm: { | ||
| 73 | - title: '是否确认删除', | ||
| 74 | - confirm: handleDeleteOrBatchDelete.bind(null, record), | 37 | + {{ |
| 38 | + record.userStatusEnum === 'NORMAL' | ||
| 39 | + ? '正常' | ||
| 40 | + : record.userStatusEnum === 'DISABLED' | ||
| 41 | + ? '已禁用' | ||
| 42 | + : '已过期' | ||
| 43 | + }} | ||
| 44 | + </Tag> | ||
| 45 | + </template> | ||
| 46 | + <template #action="{ record }"> | ||
| 47 | + <TableAction | ||
| 48 | + :actions="[ | ||
| 49 | + // { | ||
| 50 | + // label: '进入', | ||
| 51 | + // icon: 'ant-design:login-outlined', | ||
| 52 | + // tooltip: `以${!isAdmin(role) ? '客户' : '平台'}用户身份登录`, | ||
| 53 | + // onClick: handleLoginCustomAdmin.bind(null, record), | ||
| 54 | + // }, | ||
| 55 | + { | ||
| 56 | + label: '用户详情', | ||
| 57 | + auth: 'api:yt:user:get', | ||
| 58 | + icon: 'clarity:info-standard-line', | ||
| 59 | + tooltip: '用户详情', | ||
| 60 | + onClick: handledetail.bind(null, record), | ||
| 61 | + ifShow: record.level != 0, | ||
| 62 | + }, | ||
| 63 | + { | ||
| 64 | + label: '编辑', | ||
| 65 | + auth: 'api:yt:user:update', | ||
| 66 | + icon: 'clarity:note-edit-line', | ||
| 67 | + tooltip: '编辑', | ||
| 68 | + onClick: handleEdit.bind(null, record), | ||
| 69 | + ifShow: record.level != 0, | ||
| 75 | }, | 70 | }, |
| 76 | - }, | ||
| 77 | - { | ||
| 78 | - label: '清除密码', | ||
| 79 | - auth: 'api:yt:user:resetPassword', | ||
| 80 | - icon: 'ant-design:delete-outlined', | ||
| 81 | - color: 'error', | ||
| 82 | - tooltip: '清除密码', | ||
| 83 | - popConfirm: { | ||
| 84 | - title: '是否确认清除密码', | ||
| 85 | - confirm: handleClearPassword.bind(null, record), | 71 | + ]" |
| 72 | + :drop-down-actions="[ | ||
| 73 | + { | ||
| 74 | + label: '删除', | ||
| 75 | + auth: 'api:yt:user:delete', | ||
| 76 | + icon: 'ant-design:delete-outlined', | ||
| 77 | + color: 'error', | ||
| 78 | + tooltip: '删除', | ||
| 79 | + ifShow: record.level != 0, | ||
| 80 | + popConfirm: { | ||
| 81 | + title: '是否确认删除', | ||
| 82 | + confirm: handleDeleteOrBatchDelete.bind(null, record), | ||
| 83 | + }, | ||
| 86 | }, | 84 | }, |
| 87 | - }, | ||
| 88 | - ]" | ||
| 89 | - /> | ||
| 90 | - </template> | ||
| 91 | - </BasicTable> | 85 | + { |
| 86 | + label: '清除密码', | ||
| 87 | + auth: 'api:yt:user:resetPassword', | ||
| 88 | + icon: 'ant-design:delete-outlined', | ||
| 89 | + color: 'error', | ||
| 90 | + tooltip: '清除密码', | ||
| 91 | + popConfirm: { | ||
| 92 | + title: '是否确认清除密码', | ||
| 93 | + confirm: handleClearPassword.bind(null, record), | ||
| 94 | + }, | ||
| 95 | + }, | ||
| 96 | + ]" | ||
| 97 | + /> | ||
| 98 | + </template> | ||
| 99 | + </BasicTable> | ||
| 100 | + <TenantModal @register="registerModal" @success="handleSuccess" /> | ||
| 101 | + </PageWrapper> | ||
| 92 | </div> | 102 | </div> |
| 93 | </template> | 103 | </template> |
| 94 | 104 | ||
| @@ -96,22 +106,35 @@ | @@ -96,22 +106,35 @@ | ||
| 96 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 106 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
| 97 | import { getTenantList } from '/@/api/system/account'; | 107 | import { getTenantList } from '/@/api/system/account'; |
| 98 | import { columns, searchFormSchema } from './config'; | 108 | import { columns, searchFormSchema } from './config'; |
| 99 | - // import { useResetOrganizationTree } from '/@/views/common/organizationIdTree'; | 109 | + import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree'; |
| 100 | import { reactive } from 'vue'; | 110 | import { reactive } from 'vue'; |
| 101 | import { Authority } from '/@/components/Authority'; | 111 | import { Authority } from '/@/components/Authority'; |
| 112 | + import { useUserStore } from '/@/store/modules/user'; | ||
| 113 | + import { PageWrapper } from '/@/components/Page'; | ||
| 114 | + import { Tag, Popconfirm } from 'ant-design-vue'; | ||
| 115 | + import TenantModal from './TenantModal.vue'; | ||
| 116 | + import { useModal } from '/@/components/Modal'; | ||
| 102 | 117 | ||
| 103 | const searchInfo = reactive<Recordable>({}); | 118 | const searchInfo = reactive<Recordable>({}); |
| 104 | 119 | ||
| 105 | - // const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); | 120 | + const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); |
| 106 | 121 | ||
| 107 | - const [registerTable, {}] = useTable({ | 122 | + const userInfo = useUserStore(); |
| 123 | + const [registerTable, { reload }] = useTable({ | ||
| 108 | title: '租户账号列表', | 124 | title: '租户账号列表', |
| 109 | columns, | 125 | columns, |
| 110 | api: getTenantList, | 126 | api: getTenantList, |
| 111 | formConfig: { | 127 | formConfig: { |
| 112 | labelWidth: 100, | 128 | labelWidth: 100, |
| 113 | schemas: searchFormSchema, | 129 | schemas: searchFormSchema, |
| 114 | - // resetFunc: resetFn, | 130 | + resetFunc: resetFn, |
| 131 | + }, | ||
| 132 | + | ||
| 133 | + beforeFetch: (params) => { | ||
| 134 | + return { | ||
| 135 | + ...params, | ||
| 136 | + tenantId: userInfo.getUserInfo.tenantId!, | ||
| 137 | + }; | ||
| 115 | }, | 138 | }, |
| 116 | useSearchForm: true, | 139 | useSearchForm: true, |
| 117 | showTableSetting: true, | 140 | showTableSetting: true, |
| @@ -128,9 +151,21 @@ | @@ -128,9 +151,21 @@ | ||
| 128 | }, | 151 | }, |
| 129 | }); | 152 | }); |
| 130 | 153 | ||
| 131 | - const handleCreate = () => {}; | 154 | + const [registerModal, { openModal }] = useModal(); |
| 155 | + | ||
| 156 | + function handleSelect(organization) { | ||
| 157 | + searchInfo.organizationId = organization; | ||
| 158 | + reload(); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + const handleCreate = () => { | ||
| 162 | + openModal(true, { | ||
| 163 | + isAdd: true, | ||
| 164 | + }); | ||
| 165 | + }; | ||
| 132 | const handledetail = (_data?: any[]) => {}; | 166 | const handledetail = (_data?: any[]) => {}; |
| 133 | const handleEdit = (_data?: any[]) => {}; | 167 | const handleEdit = (_data?: any[]) => {}; |
| 134 | const handleDeleteOrBatchDelete = (_data?: any[]) => {}; | 168 | const handleDeleteOrBatchDelete = (_data?: any[]) => {}; |
| 135 | const handleClearPassword = (_data?: any[]) => {}; | 169 | const handleClearPassword = (_data?: any[]) => {}; |
| 170 | + const handleSuccess = () => {}; | ||
| 136 | </script> | 171 | </script> |