增加租户套餐

This commit is contained in:
2026-09-15 17:28:08 +08:00
parent a82b300b1a
commit 71a14c46f9
37 changed files with 3855 additions and 178 deletions
+1
View File
@@ -54,6 +54,7 @@ declare module 'vue' {
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress']
+11
View File
@@ -81,4 +81,15 @@ export function checkTenantCode(tenant_code) {
method: 'get',
params: { tenant_code }
});
}
/**
* 获取当前租户的用户数配额(套餐、已用/上限、剩余)
* @returns {Promise}
*/
export function getTenantQuotaInfo() {
return request({
url: '/backend/tenant/quotaInfo',
method: 'get',
});
}
@@ -354,7 +354,7 @@ const handleExport = async (row) => {
const money = (value) => Number(value || 0).toFixed(2);
// 日期显示统一为:YYYY-MM-DD
const formatDate = (value: any) => {
const formatDate = (value) => {
if (!value) return "-";
return formatDateUtil(value);
};
@@ -1,7 +1,13 @@
<template>
<div class="container-box">
<div class="header-bar">
<h2>用户管理</h2>
<h2>
用户管理
<el-tag v-if="quotaInfo" size="small" :type="quotaFull ? 'danger' : 'info'" effect="plain"
class="quota-tag">
用户数 {{ quotaInfo.used }} / {{ quotaInfo.quota }}
</el-tag>
</h2>
<div class="header-actions">
<el-button type="primary" @click="handleAddUser">
<el-icon>
@@ -20,6 +26,9 @@
<el-divider></el-divider>
<el-alert v-if="quotaFull" type="warning" show-icon :closable="false" class="quota-alert"
title="用户数已达上限,新增账号前请联系平台管理员增购用户数" />
<div class="filter-bar">
<el-form inline>
<el-form-item label="租户筛选">
@@ -91,10 +100,11 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { ref, computed, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, Refresh } from "@element-plus/icons-vue";
import { getTenantUsers, deleteUser } from "@/api/user";
import { getTenantQuotaInfo } from "@/api/tenant";
import { getAllRoles } from "@/api/role";
import { useAuthStore } from "@/stores/auth";
import UserEditDialog from "./components/userEdit.vue";
@@ -150,9 +160,30 @@ const isEdit = ref(false);
const currentUserId = ref<number | undefined>(undefined);
const currentUser = ref<User | undefined>(undefined);
// 用户数配额(由平台端配置:默认 20,可增购)
const quotaInfo = ref<any>(null);
const quotaFull = computed(
() =>
!!quotaInfo.value &&
Number(quotaInfo.value.quota) > 0 &&
Number(quotaInfo.value.used) >= Number(quotaInfo.value.quota)
);
const fetchQuotaInfo = async () => {
try {
const res = await getTenantQuotaInfo();
if (res?.code === 200) {
quotaInfo.value = res.data || null;
}
} catch {
quotaInfo.value = null;
}
};
//刷新
const refresh = async () => {
await fetchUsers();
fetchQuotaInfo();
};
// 获取角色列表
@@ -206,6 +237,15 @@ const fetchUsers = async () => {
// 添加用户
const handleAddUser = () => {
// 用户数达到上限时不允许再新增,提示联系平台增购
if (quotaFull.value) {
ElMessageBox.alert(
`当前租户用户数已达上限(${quotaInfo.value.used}/${quotaInfo.value.quota}),请联系平台管理员增购用户数。`,
"用户数已达上限",
{ type: "warning", confirmButtonText: "我知道了" }
).catch(() => {});
return;
}
isEdit.value = false;
editDialogVisible.value = true;
if (userEditRef.value) {
@@ -243,6 +283,7 @@ const handleEditSuccess = () => {
editDialogVisible.value = false;
ElMessage.success(isEdit.value ? "编辑成功" : "添加成功");
fetchUsers();
fetchQuotaInfo();
};
// 密码修改成功回调
@@ -268,6 +309,7 @@ const handleDelete = async (user: User) => {
await deleteUser(user.id);
ElMessage.success("删除成功");
fetchUsers();
fetchQuotaInfo();
} catch (e) {
ElMessage.error("删除失败");
}
@@ -278,6 +320,7 @@ onMounted(async () => {
selectedTenantId.value = Number(authStore.user.tid || 0);
fetchUsers();
fetchRoles();
fetchQuotaInfo();
});
</script>
@@ -286,6 +329,15 @@ onMounted(async () => {
margin-bottom: 12px;
}
.quota-tag {
margin-left: 10px;
vertical-align: middle;
}
.quota-alert {
margin-bottom: 12px;
}
.card-header {
display: flex;
justify-content: space-between;