mirror of
https://gitee.com/nicefold/seewis-soybean-plus.git
synced 2026-10-14 03:52:28 +08:00
refactor(tenant): remove frontend multi-tenant features / 删除前端多租户能力
This commit is contained in:
@@ -39,8 +39,7 @@ export function useFormRules() {
|
|||||||
phone: [createRequiredRule($t('form.phone.required')), patternRules.phone],
|
phone: [createRequiredRule($t('form.phone.required')), patternRules.phone],
|
||||||
pwd: [createRequiredRule($t('form.pwd.required')), patternRules.pwd],
|
pwd: [createRequiredRule($t('form.pwd.required')), patternRules.pwd],
|
||||||
code: [createRequiredRule($t('form.code.required')), patternRules.code],
|
code: [createRequiredRule($t('form.code.required')), patternRules.code],
|
||||||
email: [createRequiredRule($t('form.email.required')), patternRules.email],
|
email: [createRequiredRule($t('form.email.required')), patternRules.email]
|
||||||
tenantId: [createRequiredRule('请选择/输入公司名称')]
|
|
||||||
} satisfies Record<string, App.Global.FormRule[]>;
|
} satisfies Record<string, App.Global.FormRule[]>;
|
||||||
|
|
||||||
/** the default required rule */
|
/** the default required rule */
|
||||||
|
|||||||
@@ -284,8 +284,6 @@ const local: App.I18n.Schema = {
|
|||||||
system_oss: 'File Management',
|
system_oss: 'File Management',
|
||||||
'system_oss-config': 'OSS Config',
|
'system_oss-config': 'OSS Config',
|
||||||
system_client: 'Client Management',
|
system_client: 'Client Management',
|
||||||
system_tenant: 'Tenant Management',
|
|
||||||
'system_tenant-package': 'Tenant Package Management',
|
|
||||||
monitor: 'Monitor',
|
monitor: 'Monitor',
|
||||||
monitor_logininfor: 'Login Log',
|
monitor_logininfor: 'Login Log',
|
||||||
monitor_operlog: 'Operate Log',
|
monitor_operlog: 'Operate Log',
|
||||||
@@ -305,7 +303,6 @@ const local: App.I18n.Schema = {
|
|||||||
about: 'About'
|
about: 'About'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
system_tenant: 'Tenant Management',
|
|
||||||
system_log: 'Log Management',
|
system_log: 'Log Management',
|
||||||
'monitor_snail-job': 'Job Management',
|
'monitor_snail-job': 'Job Management',
|
||||||
monitor_admin: 'Admin Monitor'
|
monitor_admin: 'Admin Monitor'
|
||||||
@@ -1036,104 +1033,6 @@ const local: App.I18n.Schema = {
|
|||||||
selectDataScope: 'Select Data Scope',
|
selectDataScope: 'Select Data Scope',
|
||||||
selectDeptPermission: 'Select Dept Permission'
|
selectDeptPermission: 'Select Dept Permission'
|
||||||
},
|
},
|
||||||
tenant: {
|
|
||||||
title: 'Tenant List',
|
|
||||||
tenantName: 'Tenant Name',
|
|
||||||
tenantId: 'Tenant ID',
|
|
||||||
contactUserName: 'Contact Person',
|
|
||||||
contactPhone: 'Contact Phone',
|
|
||||||
companyName: 'Company Name',
|
|
||||||
licenseNumber: 'License Number',
|
|
||||||
address: 'Address',
|
|
||||||
intro: 'Introduction',
|
|
||||||
domain: 'Domain',
|
|
||||||
packageId: 'Tenant Package',
|
|
||||||
expireTime: 'Expiration Time',
|
|
||||||
accountCount: 'Account Count',
|
|
||||||
status: 'Status',
|
|
||||||
createTime: 'Create Time',
|
|
||||||
form: {
|
|
||||||
tenantName: {
|
|
||||||
required: 'Please enter Tenant Name',
|
|
||||||
invalid: 'Tenant Name cannot be empty'
|
|
||||||
},
|
|
||||||
contactUserName: {
|
|
||||||
required: 'Please enter Contact Person',
|
|
||||||
invalid: 'Contact Person cannot be empty'
|
|
||||||
},
|
|
||||||
contactPhone: {
|
|
||||||
required: 'Please enter Contact Phone',
|
|
||||||
invalid: 'Contact Phone cannot be empty'
|
|
||||||
},
|
|
||||||
companyName: {
|
|
||||||
required: 'Please enter Company Name',
|
|
||||||
invalid: 'Company Name cannot be empty'
|
|
||||||
},
|
|
||||||
licenseNumber: {
|
|
||||||
required: 'Please enter License Number',
|
|
||||||
invalid: 'License Number cannot be empty'
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
required: 'Please enter Address',
|
|
||||||
invalid: 'Address cannot be empty'
|
|
||||||
},
|
|
||||||
intro: {
|
|
||||||
required: 'Please enter Introduction',
|
|
||||||
invalid: 'Introduction cannot be empty'
|
|
||||||
},
|
|
||||||
domain: {
|
|
||||||
required: 'Please enter Domain',
|
|
||||||
invalid: 'Domain cannot be empty'
|
|
||||||
},
|
|
||||||
packageId: {
|
|
||||||
required: 'Please select Tenant Package',
|
|
||||||
invalid: 'Tenant Package cannot be empty'
|
|
||||||
},
|
|
||||||
expireTime: {
|
|
||||||
required: 'Please select Expiration Time',
|
|
||||||
invalid: 'Expiration Time cannot be empty'
|
|
||||||
},
|
|
||||||
accountCount: {
|
|
||||||
required: 'Please enter Account Count',
|
|
||||||
invalid: 'Account Count cannot be empty'
|
|
||||||
},
|
|
||||||
status: {
|
|
||||||
required: 'Please select Status',
|
|
||||||
invalid: 'Status cannot be empty'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addTenant: 'Add Tenant',
|
|
||||||
editTenant: 'Edit Tenant'
|
|
||||||
},
|
|
||||||
tenantPackage: {
|
|
||||||
title: 'Tenant Package List',
|
|
||||||
packageName: 'Package Name',
|
|
||||||
menuIds: 'Menu Permission',
|
|
||||||
remark: 'Remark',
|
|
||||||
status: 'Status',
|
|
||||||
createTime: 'Create Time',
|
|
||||||
form: {
|
|
||||||
packageName: {
|
|
||||||
required: 'Please enter Package Name',
|
|
||||||
invalid: 'Package Name cannot be empty'
|
|
||||||
},
|
|
||||||
menuIds: {
|
|
||||||
required: 'Please select Menu Permission',
|
|
||||||
invalid: 'Menu Permission cannot be empty'
|
|
||||||
},
|
|
||||||
status: {
|
|
||||||
required: 'Please select Status',
|
|
||||||
invalid: 'Status cannot be empty'
|
|
||||||
},
|
|
||||||
remark: {
|
|
||||||
required: 'Please enter Remark',
|
|
||||||
invalid: 'Remark cannot be empty'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addTenantPackage: 'Add Tenant Package',
|
|
||||||
editTenantPackage: 'Edit Tenant Package',
|
|
||||||
statusChangeSuccess: 'Status modified successfully'
|
|
||||||
},
|
|
||||||
user: {
|
user: {
|
||||||
title: 'User List',
|
title: 'User List',
|
||||||
userName: 'Username',
|
userName: 'Username',
|
||||||
|
|||||||
@@ -280,8 +280,6 @@ const local: App.I18n.Schema = {
|
|||||||
system_oss: '文件管理',
|
system_oss: '文件管理',
|
||||||
'system_oss-config': 'OSS 配置',
|
'system_oss-config': 'OSS 配置',
|
||||||
system_client: '客户端管理',
|
system_client: '客户端管理',
|
||||||
system_tenant: '租户管理',
|
|
||||||
'system_tenant-package': '租户套餐',
|
|
||||||
monitor: '系统监控',
|
monitor: '系统监控',
|
||||||
monitor_cache: '缓存监控',
|
monitor_cache: '缓存监控',
|
||||||
monitor_logininfor: '登录日志',
|
monitor_logininfor: '登录日志',
|
||||||
@@ -301,7 +299,6 @@ const local: App.I18n.Schema = {
|
|||||||
about: '关于'
|
about: '关于'
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
system_tenant: '租户管理',
|
|
||||||
system_log: '日志管理',
|
system_log: '日志管理',
|
||||||
'monitor_snail-job': '任务调度中心',
|
'monitor_snail-job': '任务调度中心',
|
||||||
monitor_admin: 'Admin 监控'
|
monitor_admin: 'Admin 监控'
|
||||||
@@ -1028,104 +1025,6 @@ const local: App.I18n.Schema = {
|
|||||||
selectDataScope: '选择数据权限',
|
selectDataScope: '选择数据权限',
|
||||||
selectDeptPermission: '选择部门权限'
|
selectDeptPermission: '选择部门权限'
|
||||||
},
|
},
|
||||||
tenant: {
|
|
||||||
title: '租户列表',
|
|
||||||
tenantName: '租户名称',
|
|
||||||
tenantId: '租户编号',
|
|
||||||
contactUserName: '联系人',
|
|
||||||
contactPhone: '联系电话',
|
|
||||||
companyName: '公司名称',
|
|
||||||
licenseNumber: '营业执照编号',
|
|
||||||
address: '地址',
|
|
||||||
intro: '企业简介',
|
|
||||||
domain: '域名',
|
|
||||||
packageId: '租户套餐',
|
|
||||||
expireTime: '过期时间',
|
|
||||||
accountCount: '账号数量',
|
|
||||||
status: '状态',
|
|
||||||
createTime: '创建时间',
|
|
||||||
form: {
|
|
||||||
tenantName: {
|
|
||||||
required: '请输入租户名称',
|
|
||||||
invalid: '租户名称不能为空'
|
|
||||||
},
|
|
||||||
contactUserName: {
|
|
||||||
required: '请输入联系人',
|
|
||||||
invalid: '联系人不能为空'
|
|
||||||
},
|
|
||||||
contactPhone: {
|
|
||||||
required: '请输入联系电话',
|
|
||||||
invalid: '联系电话不能为空'
|
|
||||||
},
|
|
||||||
companyName: {
|
|
||||||
required: '请输入公司名称',
|
|
||||||
invalid: '公司名称不能为空'
|
|
||||||
},
|
|
||||||
licenseNumber: {
|
|
||||||
required: '请输入营业执照编号',
|
|
||||||
invalid: '营业执照编号不能为空'
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
required: '请输入地址',
|
|
||||||
invalid: '地址不能为空'
|
|
||||||
},
|
|
||||||
intro: {
|
|
||||||
required: '请输入企业简介',
|
|
||||||
invalid: '企业简介不能为空'
|
|
||||||
},
|
|
||||||
domain: {
|
|
||||||
required: '请输入域名',
|
|
||||||
invalid: '域名不能为空'
|
|
||||||
},
|
|
||||||
packageId: {
|
|
||||||
required: '请选择租户套餐',
|
|
||||||
invalid: '租户套餐不能为空'
|
|
||||||
},
|
|
||||||
expireTime: {
|
|
||||||
required: '请选择过期时间',
|
|
||||||
invalid: '过期时间不能为空'
|
|
||||||
},
|
|
||||||
accountCount: {
|
|
||||||
required: '请输入账号数量',
|
|
||||||
invalid: '账号数量不能为空'
|
|
||||||
},
|
|
||||||
status: {
|
|
||||||
required: '请选择状态',
|
|
||||||
invalid: '状态不能为空'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addTenant: '新增租户',
|
|
||||||
editTenant: '编辑租户'
|
|
||||||
},
|
|
||||||
tenantPackage: {
|
|
||||||
title: '租户套餐列表',
|
|
||||||
packageName: '套餐名称',
|
|
||||||
menuIds: '菜单权限',
|
|
||||||
remark: '备注',
|
|
||||||
status: '状态',
|
|
||||||
createTime: '创建时间',
|
|
||||||
form: {
|
|
||||||
packageName: {
|
|
||||||
required: '请输入套餐名称',
|
|
||||||
invalid: '套餐名称不能为空'
|
|
||||||
},
|
|
||||||
menuIds: {
|
|
||||||
required: '请选择菜单权限',
|
|
||||||
invalid: '菜单权限不能为空'
|
|
||||||
},
|
|
||||||
status: {
|
|
||||||
required: '请选择状态',
|
|
||||||
invalid: '状态不能为空'
|
|
||||||
},
|
|
||||||
remark: {
|
|
||||||
required: '请输入备注',
|
|
||||||
invalid: '备注不能为空'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addTenantPackage: '新增租户套餐',
|
|
||||||
editTenantPackage: '编辑租户套餐',
|
|
||||||
statusChangeSuccess: '状态修改成功'
|
|
||||||
},
|
|
||||||
user: {
|
user: {
|
||||||
title: '用户列表',
|
title: '用户列表',
|
||||||
userName: '用户名称',
|
userName: '用户名称',
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
system_oss: () => import("@/views/system/oss/index.vue"),
|
system_oss: () => import("@/views/system/oss/index.vue"),
|
||||||
system_post: () => import("@/views/system/post/index.vue"),
|
system_post: () => import("@/views/system/post/index.vue"),
|
||||||
system_role: () => import("@/views/system/role/index.vue"),
|
system_role: () => import("@/views/system/role/index.vue"),
|
||||||
"system_tenant-package": () => import("@/views/system/tenant-package/index.vue"),
|
|
||||||
system_tenant: () => import("@/views/system/tenant/index.vue"),
|
|
||||||
system_user: () => import("@/views/system/user/index.vue"),
|
system_user: () => import("@/views/system/user/index.vue"),
|
||||||
tool_gen: () => import("@/views/tool/gen/index.vue"),
|
tool_gen: () => import("@/views/tool/gen/index.vue"),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -279,24 +279,6 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
i18nKey: 'route.system_role'
|
i18nKey: 'route.system_role'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'system_tenant',
|
|
||||||
path: '/system/tenant',
|
|
||||||
component: 'view.system_tenant',
|
|
||||||
meta: {
|
|
||||||
title: 'system_tenant',
|
|
||||||
i18nKey: 'route.system_tenant'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'system_tenant-package',
|
|
||||||
path: '/system/tenant-package',
|
|
||||||
component: 'view.system_tenant-package',
|
|
||||||
meta: {
|
|
||||||
title: 'system_tenant-package',
|
|
||||||
i18nKey: 'route.system_tenant-package'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'system_user',
|
name: 'system_user',
|
||||||
path: '/system/user',
|
path: '/system/user',
|
||||||
|
|||||||
@@ -194,8 +194,6 @@ const routeMap: RouteMap = {
|
|||||||
"system_oss-config": "/system/oss-config",
|
"system_oss-config": "/system/oss-config",
|
||||||
"system_post": "/system/post",
|
"system_post": "/system/post",
|
||||||
"system_role": "/system/role",
|
"system_role": "/system/role",
|
||||||
"system_tenant": "/system/tenant",
|
|
||||||
"system_tenant-package": "/system/tenant-package",
|
|
||||||
"system_user": "/system/user",
|
"system_user": "/system/user",
|
||||||
"tool": "/tool",
|
"tool": "/tool",
|
||||||
"tool_gen": "/tool/gen",
|
"tool_gen": "/tool/gen",
|
||||||
|
|||||||
@@ -52,14 +52,6 @@ export function fetchGetRoleMenuTreeSelect(roleId: CommonType.IdType) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取租户套餐关联菜单 */
|
|
||||||
export function fetchGetTenantPackageMenuTreeSelect(packageId: CommonType.IdType) {
|
|
||||||
return request<Api.System.TenantPackageMenuTreeSelect>({
|
|
||||||
url: `/system/menu/tenantPackageMenuTreeselect/${packageId}`,
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 级联删除菜单 */
|
/** 级联删除菜单 */
|
||||||
export function fetchCascadeDeleteMenu(menuIds: CommonType.IdType[]) {
|
export function fetchCascadeDeleteMenu(menuIds: CommonType.IdType[]) {
|
||||||
return request<boolean>({
|
return request<boolean>({
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
import { request } from '@/service/request';
|
|
||||||
|
|
||||||
/** 获取租户套餐列表 */
|
|
||||||
export function fetchGetTenantPackageList(params?: Api.System.TenantPackageSearchParams) {
|
|
||||||
return request<Api.System.TenantPackageList>({
|
|
||||||
url: '/system/tenant/package/list',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/** 获取租户下拉列表 */
|
|
||||||
export function fetchGetTenantPackageSelectList() {
|
|
||||||
return request<Api.System.TenantPackageSelectList[]>({
|
|
||||||
url: '/system/tenant/package/selectList',
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增租户套餐 */
|
|
||||||
export function fetchCreateTenantPackage(data: Api.System.TenantPackageOperateParams) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant/package',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改租户套餐 */
|
|
||||||
export function fetchUpdateTenantPackage(data: Api.System.TenantPackageOperateParams) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant/package',
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 批量删除租户套餐 */
|
|
||||||
export function fetchBatchDeleteTenantPackage(packageIds: CommonType.IdType[]) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: `/system/tenant/package/${packageIds.join(',')}`,
|
|
||||||
method: 'delete'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改租户套餐状态 */
|
|
||||||
export function fetchUpdateTenantPackageStatus(data: Api.System.TenantPackageOperateParams) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: `/system/tenant/package/changeStatus`,
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
import { request } from '@/service/request';
|
|
||||||
|
|
||||||
/** 获取租户列表 */
|
|
||||||
export function fetchGetTenantList(params?: Api.System.TenantSearchParams) {
|
|
||||||
return request<Api.System.TenantList>({
|
|
||||||
url: '/system/tenant/list',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增租户 */
|
|
||||||
export function fetchCreateTenant(data: Api.System.TenantOperateParams) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
isEncrypt: true,
|
|
||||||
repeatSubmit: false
|
|
||||||
},
|
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改租户 */
|
|
||||||
export function fetchUpdateTenant(data: Api.System.TenantOperateParams) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant',
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 批量删除租户 */
|
|
||||||
export function fetchBatchDeleteTenant(ids: CommonType.IdType[]) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: `/system/tenant/${ids.join(',')}`,
|
|
||||||
method: 'delete'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 同步租户字典 */
|
|
||||||
export function fetchSyncTenantDict() {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant/syncTenantDict',
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 同步租户套餐 */
|
|
||||||
export function fetchSyncTenantPackage(params: Api.System.TenantPackageSyncParams) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant/syncTenantPackage',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 同步租户参数配置 */
|
|
||||||
export function fetchSyncTenantConfig() {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant/syncTenantConfig',
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 动态切换租户 */
|
|
||||||
export function fetchChangeTenant(tenantId: CommonType.IdType) {
|
|
||||||
return request<boolean>({
|
|
||||||
url: `/system/tenant/dynamic/${tenantId}`,
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 清空租户 */
|
|
||||||
export function fetchClearTenant() {
|
|
||||||
return request<boolean>({
|
|
||||||
url: '/system/tenant/dynamic/clear',
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Vendored
-18
@@ -80,24 +80,6 @@ declare namespace Api {
|
|||||||
permissions: string[];
|
permissions: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** tenant */
|
|
||||||
interface Tenant {
|
|
||||||
/** 企业名称 */
|
|
||||||
companyName: string;
|
|
||||||
/** 域名 */
|
|
||||||
domain: string;
|
|
||||||
/** 租户编号 */
|
|
||||||
tenantId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** login tenant */
|
|
||||||
interface LoginTenant {
|
|
||||||
/** 租户开关 */
|
|
||||||
tenantEnabled: boolean;
|
|
||||||
/** 租户列表 */
|
|
||||||
voList: Tenant[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CaptchaCode {
|
interface CaptchaCode {
|
||||||
/** 是否开启验证码 */
|
/** 是否开启验证码 */
|
||||||
captchaEnabled: boolean;
|
captchaEnabled: boolean;
|
||||||
|
|||||||
Vendored
-108
@@ -517,114 +517,6 @@ declare namespace Api {
|
|||||||
/** config list */
|
/** config list */
|
||||||
type ConfigList = Api.Common.PaginatingQueryRecord<Config>;
|
type ConfigList = Api.Common.PaginatingQueryRecord<Config>;
|
||||||
|
|
||||||
/** tenant */
|
|
||||||
type Tenant = Common.CommonRecord<{
|
|
||||||
/** id */
|
|
||||||
id: CommonType.IdType;
|
|
||||||
/** 租户编号 */
|
|
||||||
tenantId: CommonType.IdType;
|
|
||||||
/** 联系人 */
|
|
||||||
contactUserName: string;
|
|
||||||
/** 联系电话 */
|
|
||||||
contactPhone: string;
|
|
||||||
/** 企业名称 */
|
|
||||||
companyName: string;
|
|
||||||
/** 统一社会信用代码 */
|
|
||||||
licenseNumber: string;
|
|
||||||
/** 地址 */
|
|
||||||
address: string;
|
|
||||||
/** 企业简介 */
|
|
||||||
intro: string;
|
|
||||||
/** 域名 */
|
|
||||||
domain: string;
|
|
||||||
/** 备注 */
|
|
||||||
remark: string;
|
|
||||||
/** 租户套餐编号 */
|
|
||||||
packageId: CommonType.IdType;
|
|
||||||
/** 过期时间 */
|
|
||||||
expireTime: string;
|
|
||||||
/** 用户数量(-1不限制) */
|
|
||||||
accountCount: number;
|
|
||||||
/** 租户状态(0正常 1停用) */
|
|
||||||
status: Common.EnableStatus;
|
|
||||||
/** 删除标志(0代表存在 1代表删除) */
|
|
||||||
delFlag: string;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
/** tenant search params */
|
|
||||||
type TenantSearchParams = CommonType.RecordNullable<
|
|
||||||
Pick<Api.System.Tenant, 'tenantId' | 'contactUserName' | 'contactPhone' | 'companyName'> &
|
|
||||||
Api.Common.CommonSearchParams
|
|
||||||
>;
|
|
||||||
|
|
||||||
/** tenant operate params */
|
|
||||||
type TenantOperateParams = CommonType.RecordNullable<
|
|
||||||
Pick<
|
|
||||||
Api.System.Tenant,
|
|
||||||
| 'id'
|
|
||||||
| 'tenantId'
|
|
||||||
| 'contactUserName'
|
|
||||||
| 'contactPhone'
|
|
||||||
| 'companyName'
|
|
||||||
| 'licenseNumber'
|
|
||||||
| 'address'
|
|
||||||
| 'intro'
|
|
||||||
| 'domain'
|
|
||||||
| 'remark'
|
|
||||||
| 'packageId'
|
|
||||||
| 'expireTime'
|
|
||||||
| 'accountCount'
|
|
||||||
| 'status'
|
|
||||||
> & {
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
|
|
||||||
/** tenant package sync params */
|
|
||||||
type TenantPackageSyncParams = CommonType.RecordNullable<Pick<Api.System.Tenant, 'tenantId' | 'packageId'>>;
|
|
||||||
|
|
||||||
/** tenant list */
|
|
||||||
type TenantList = Api.Common.PaginatingQueryRecord<Tenant>;
|
|
||||||
|
|
||||||
/** tenant package */
|
|
||||||
type TenantPackage = Common.CommonRecord<{
|
|
||||||
/** 租户套餐id */
|
|
||||||
packageId: CommonType.IdType;
|
|
||||||
/** 套餐名称 */
|
|
||||||
packageName: string;
|
|
||||||
/** 关联菜单id */
|
|
||||||
menuIds: CommonType.IdType[];
|
|
||||||
/** 备注 */
|
|
||||||
remark: string;
|
|
||||||
/** 菜单树选择项是否关联显示 */
|
|
||||||
menuCheckStrictly: boolean;
|
|
||||||
/** 状态(0正常 1停用) */
|
|
||||||
status: Common.EnableStatus;
|
|
||||||
/** 删除标志(0代表存在 1代表删除) */
|
|
||||||
delFlag: string;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
/** tenant package search params */
|
|
||||||
type TenantPackageSearchParams = CommonType.RecordNullable<
|
|
||||||
Pick<Api.System.TenantPackage, 'packageName' | 'menuIds' | 'menuCheckStrictly' | 'status'> &
|
|
||||||
Api.Common.CommonSearchParams
|
|
||||||
>;
|
|
||||||
|
|
||||||
/** tenant package operate params */
|
|
||||||
type TenantPackageOperateParams = CommonType.RecordNullable<
|
|
||||||
Pick<
|
|
||||||
Api.System.TenantPackage,
|
|
||||||
'packageId' | 'packageName' | 'menuIds' | 'remark' | 'menuCheckStrictly' | 'status'
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
/** tenant package list */
|
|
||||||
type TenantPackageList = Api.Common.PaginatingQueryRecord<TenantPackage>;
|
|
||||||
|
|
||||||
/** tenant package select list */
|
|
||||||
type TenantPackageSelectList = Common.CommonRecord<Pick<TenantPackage, 'packageId' | 'packageName'>>;
|
|
||||||
|
|
||||||
/** 通知公告类型 */
|
/** 通知公告类型 */
|
||||||
type NoticeType = '1' | '2';
|
type NoticeType = '1' | '2';
|
||||||
|
|
||||||
|
|||||||
Vendored
-50
@@ -926,56 +926,6 @@ declare namespace App {
|
|||||||
selectDataScope: string;
|
selectDataScope: string;
|
||||||
selectDeptPermission: string;
|
selectDeptPermission: string;
|
||||||
};
|
};
|
||||||
tenant: {
|
|
||||||
title: string;
|
|
||||||
tenantName: string;
|
|
||||||
tenantId: string;
|
|
||||||
contactUserName: string;
|
|
||||||
contactPhone: string;
|
|
||||||
companyName: string;
|
|
||||||
licenseNumber: string;
|
|
||||||
address: string;
|
|
||||||
intro: string;
|
|
||||||
domain: string;
|
|
||||||
packageId: string;
|
|
||||||
expireTime: string;
|
|
||||||
accountCount: string;
|
|
||||||
status: string;
|
|
||||||
createTime: string;
|
|
||||||
form: {
|
|
||||||
tenantName: FormMsg;
|
|
||||||
contactUserName: FormMsg;
|
|
||||||
contactPhone: FormMsg;
|
|
||||||
companyName: FormMsg;
|
|
||||||
licenseNumber: FormMsg;
|
|
||||||
address: FormMsg;
|
|
||||||
intro: FormMsg;
|
|
||||||
domain: FormMsg;
|
|
||||||
packageId: FormMsg;
|
|
||||||
expireTime: FormMsg;
|
|
||||||
accountCount: FormMsg;
|
|
||||||
status: FormMsg;
|
|
||||||
};
|
|
||||||
addTenant: string;
|
|
||||||
editTenant: string;
|
|
||||||
};
|
|
||||||
tenantPackage: {
|
|
||||||
title: string;
|
|
||||||
packageName: string;
|
|
||||||
menuIds: string;
|
|
||||||
remark: string;
|
|
||||||
status: string;
|
|
||||||
createTime: string;
|
|
||||||
form: {
|
|
||||||
packageName: FormMsg;
|
|
||||||
menuIds: FormMsg;
|
|
||||||
status: FormMsg;
|
|
||||||
remark: FormMsg;
|
|
||||||
};
|
|
||||||
addTenantPackage: string;
|
|
||||||
editTenantPackage: string;
|
|
||||||
statusChangeSuccess: string;
|
|
||||||
};
|
|
||||||
user: {
|
user: {
|
||||||
title: string;
|
title: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
|
|||||||
Vendored
-14
@@ -51,17 +51,11 @@ declare module 'vue' {
|
|||||||
IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
||||||
IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
||||||
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||||
IconMdiArrowRightThick: typeof import('~icons/mdi/arrow-right-thick')['default']
|
|
||||||
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||||
IconMdiCheckCircleOutline: typeof import('~icons/mdi/check-circle-outline')['default']
|
|
||||||
IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
||||||
IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
||||||
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||||
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||||
IconMdiLoading: typeof import('~icons/mdi/loading')['default']
|
|
||||||
IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
|
|
||||||
IconMdiShieldAlertOutline: typeof import('~icons/mdi/shield-alert-outline')['default']
|
|
||||||
IconMdiShieldCheckOutline: typeof import('~icons/mdi/shield-check-outline')['default']
|
|
||||||
IconOcticonPin16: typeof import('~icons/octicon/pin16')['default']
|
IconOcticonPin16: typeof import('~icons/octicon/pin16')['default']
|
||||||
IconOcticonPinSlash16: typeof import('~icons/octicon/pin-slash16')['default']
|
IconOcticonPinSlash16: typeof import('~icons/octicon/pin-slash16')['default']
|
||||||
IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
||||||
@@ -159,7 +153,6 @@ declare module 'vue' {
|
|||||||
TableHeaderOperation: typeof import('./../components/advanced/table-header-operation.vue')['default']
|
TableHeaderOperation: typeof import('./../components/advanced/table-header-operation.vue')['default']
|
||||||
TableRowCheckAlert: typeof import('./../components/advanced/table-row-check-alert.vue')['default']
|
TableRowCheckAlert: typeof import('./../components/advanced/table-row-check-alert.vue')['default']
|
||||||
TableSiderLayout: typeof import('./../components/advanced/table-sider-layout.vue')['default']
|
TableSiderLayout: typeof import('./../components/advanced/table-sider-layout.vue')['default']
|
||||||
TenantSelect: typeof import('./../components/custom/tenant-select.vue')['default']
|
|
||||||
ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default']
|
ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default']
|
||||||
UserSelect: typeof import('./../components/custom/user-select.vue')['default']
|
UserSelect: typeof import('./../components/custom/user-select.vue')['default']
|
||||||
WangEditor: typeof import('./../components/custom/wang-editor.vue')['default']
|
WangEditor: typeof import('./../components/custom/wang-editor.vue')['default']
|
||||||
@@ -208,17 +201,11 @@ declare global {
|
|||||||
const IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
const IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
||||||
const IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
const IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
||||||
const IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
const IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||||
const IconMdiArrowRightThick: typeof import('~icons/mdi/arrow-right-thick')['default']
|
|
||||||
const IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
const IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||||
const IconMdiCheckCircleOutline: typeof import('~icons/mdi/check-circle-outline')['default']
|
|
||||||
const IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
const IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
||||||
const IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
const IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
||||||
const IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
const IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||||
const IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
const IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||||
const IconMdiLoading: typeof import('~icons/mdi/loading')['default']
|
|
||||||
const IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
|
|
||||||
const IconMdiShieldAlertOutline: typeof import('~icons/mdi/shield-alert-outline')['default']
|
|
||||||
const IconMdiShieldCheckOutline: typeof import('~icons/mdi/shield-check-outline')['default']
|
|
||||||
const IconOcticonPin16: typeof import('~icons/octicon/pin16')['default']
|
const IconOcticonPin16: typeof import('~icons/octicon/pin16')['default']
|
||||||
const IconOcticonPinSlash16: typeof import('~icons/octicon/pin-slash16')['default']
|
const IconOcticonPinSlash16: typeof import('~icons/octicon/pin-slash16')['default']
|
||||||
const IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
const IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
||||||
@@ -316,7 +303,6 @@ declare global {
|
|||||||
const TableHeaderOperation: typeof import('./../components/advanced/table-header-operation.vue')['default']
|
const TableHeaderOperation: typeof import('./../components/advanced/table-header-operation.vue')['default']
|
||||||
const TableRowCheckAlert: typeof import('./../components/advanced/table-row-check-alert.vue')['default']
|
const TableRowCheckAlert: typeof import('./../components/advanced/table-row-check-alert.vue')['default']
|
||||||
const TableSiderLayout: typeof import('./../components/advanced/table-sider-layout.vue')['default']
|
const TableSiderLayout: typeof import('./../components/advanced/table-sider-layout.vue')['default']
|
||||||
const TenantSelect: typeof import('./../components/custom/tenant-select.vue')['default']
|
|
||||||
const ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default']
|
const ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default']
|
||||||
const UserSelect: typeof import('./../components/custom/user-select.vue')['default']
|
const UserSelect: typeof import('./../components/custom/user-select.vue')['default']
|
||||||
const WangEditor: typeof import('./../components/custom/wang-editor.vue')['default']
|
const WangEditor: typeof import('./../components/custom/wang-editor.vue')['default']
|
||||||
|
|||||||
Vendored
-4
@@ -48,8 +48,6 @@ declare module "@elegant-router/types" {
|
|||||||
"system_oss-config": "/system/oss-config";
|
"system_oss-config": "/system/oss-config";
|
||||||
"system_post": "/system/post";
|
"system_post": "/system/post";
|
||||||
"system_role": "/system/role";
|
"system_role": "/system/role";
|
||||||
"system_tenant": "/system/tenant";
|
|
||||||
"system_tenant-package": "/system/tenant-package";
|
|
||||||
"system_user": "/system/user";
|
"system_user": "/system/user";
|
||||||
"tool": "/tool";
|
"tool": "/tool";
|
||||||
"tool_gen": "/tool/gen";
|
"tool_gen": "/tool/gen";
|
||||||
@@ -144,8 +142,6 @@ declare module "@elegant-router/types" {
|
|||||||
| "system_oss"
|
| "system_oss"
|
||||||
| "system_post"
|
| "system_post"
|
||||||
| "system_role"
|
| "system_role"
|
||||||
| "system_tenant-package"
|
|
||||||
| "system_tenant"
|
|
||||||
| "system_user"
|
| "system_user"
|
||||||
| "tool_gen"
|
| "tool_gen"
|
||||||
>;
|
>;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, reactive, ref } from 'vue';
|
import { computed, reactive, ref } from 'vue';
|
||||||
import type { SelectOption } from 'naive-ui';
|
|
||||||
import { useLoading } from '@sa/hooks';
|
import { useLoading } from '@sa/hooks';
|
||||||
import CryptoJS from 'crypto-js';
|
import CryptoJS from 'crypto-js';
|
||||||
import { fetchCaptchaCode } from '@/service/api';
|
import { fetchCaptchaCode } from '@/service/api';
|
||||||
@@ -22,34 +21,28 @@ const authStore = useAuthStore();
|
|||||||
const { toggleLoginModule } = useRouterPush();
|
const { toggleLoginModule } = useRouterPush();
|
||||||
const { formRef, validate } = useNaiveForm();
|
const { formRef, validate } = useNaiveForm();
|
||||||
const { loading: codeLoading, startLoading: startCodeLoading, endLoading: endCodeLoading } = useLoading();
|
const { loading: codeLoading, startLoading: startCodeLoading, endLoading: endCodeLoading } = useLoading();
|
||||||
const { loading: tenantLoading } = useLoading();
|
|
||||||
|
|
||||||
const codeUrl = ref<string>();
|
const codeUrl = ref<string>();
|
||||||
const captchaEnabled = ref<boolean>(false);
|
const captchaEnabled = ref<boolean>(false);
|
||||||
const registerEnabled = ref<boolean>(false);
|
const registerEnabled = ref<boolean>(false);
|
||||||
const remberMe = ref<boolean>(false);
|
const remberMe = ref<boolean>(false);
|
||||||
|
|
||||||
const tenantEnabled = ref<boolean>(false);
|
|
||||||
|
|
||||||
const tenantOption = ref<SelectOption[]>([]);
|
|
||||||
|
|
||||||
const model: Api.Auth.PwdLoginForm = reactive({
|
const model: Api.Auth.PwdLoginForm = reactive({
|
||||||
tenantId: '000000',
|
tenantId: '000000',
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
password: 'admin123'
|
password: 'admin123'
|
||||||
});
|
});
|
||||||
|
|
||||||
type RuleKey = Extract<keyof Api.Auth.PwdLoginForm, 'username' | 'password' | 'code' | 'tenantId'>;
|
type RuleKey = Extract<keyof Api.Auth.PwdLoginForm, 'username' | 'password' | 'code'>;
|
||||||
|
|
||||||
const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
|
const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
|
||||||
// inside computed to make locale reactive, if not apply i18n, you can define it without computed
|
// inside computed to make locale reactive, if not apply i18n, you can define it without computed
|
||||||
const { formRules, createRequiredRule } = useFormRules();
|
const { createRequiredRule } = useFormRules();
|
||||||
|
|
||||||
const loginRules: Record<RuleKey, App.Global.FormRule[]> = {
|
const loginRules: Record<RuleKey, App.Global.FormRule[]> = {
|
||||||
username: [createRequiredRule($t('form.userName.required'))],
|
username: [createRequiredRule($t('form.userName.required'))],
|
||||||
password: [createRequiredRule($t('form.pwd.required'))],
|
password: [createRequiredRule($t('form.pwd.required'))],
|
||||||
code: captchaEnabled.value ? [createRequiredRule($t('form.code.required'))] : [],
|
code: captchaEnabled.value ? [createRequiredRule($t('form.code.required'))] : []
|
||||||
tenantId: tenantEnabled.value ? formRules.tenantId : []
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return loginRules;
|
return loginRules;
|
||||||
@@ -59,8 +52,8 @@ async function handleSubmit() {
|
|||||||
await validate();
|
await validate();
|
||||||
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
|
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
|
||||||
if (remberMe.value) {
|
if (remberMe.value) {
|
||||||
const { tenantId, username, password } = model;
|
const { username, password } = model;
|
||||||
localStg.set('loginRember', encryptWithAes(JSON.stringify({ tenantId, username, password }), aesKey));
|
localStg.set('loginRember', encryptWithAes(JSON.stringify({ username, password }), aesKey));
|
||||||
} else {
|
} else {
|
||||||
// 否则移除
|
// 否则移除
|
||||||
localStg.remove('loginRember');
|
localStg.remove('loginRember');
|
||||||
@@ -126,14 +119,6 @@ async function handleSocialLogin(type: Api.System.SocialSource) {
|
|||||||
:show-label="false"
|
:show-label="false"
|
||||||
@keyup.enter="() => !authStore.loginLoading && handleSubmit()"
|
@keyup.enter="() => !authStore.loginLoading && handleSubmit()"
|
||||||
>
|
>
|
||||||
<NFormItem v-if="tenantEnabled" path="tenantId">
|
|
||||||
<NSelect
|
|
||||||
v-model:value="model.tenantId"
|
|
||||||
placeholder="请选择租户"
|
|
||||||
:options="tenantOption"
|
|
||||||
:loading="tenantLoading"
|
|
||||||
/>
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem path="username">
|
<NFormItem path="username">
|
||||||
<NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" />
|
<NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, reactive, ref } from 'vue';
|
import { computed, reactive, ref } from 'vue';
|
||||||
import type { SelectOption } from 'naive-ui';
|
|
||||||
import { useLoading } from '@sa/hooks';
|
import { useLoading } from '@sa/hooks';
|
||||||
import { fetchCaptchaCode, fetchRegister } from '@/service/api';
|
import { fetchCaptchaCode, fetchRegister } from '@/service/api';
|
||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
@@ -18,8 +17,6 @@ const { loading: registerLoading, startLoading: startRegisterLoading, endLoading
|
|||||||
|
|
||||||
const codeUrl = ref<string>();
|
const codeUrl = ref<string>();
|
||||||
const captchaEnabled = ref<boolean>(false);
|
const captchaEnabled = ref<boolean>(false);
|
||||||
const tenantEnabled = ref<boolean>(false);
|
|
||||||
const tenantOption = ref<SelectOption[]>([]);
|
|
||||||
|
|
||||||
const model: Api.Auth.RegisterForm = reactive({
|
const model: Api.Auth.RegisterForm = reactive({
|
||||||
tenantId: '000000',
|
tenantId: '000000',
|
||||||
@@ -30,13 +27,12 @@ const model: Api.Auth.RegisterForm = reactive({
|
|||||||
userType: 'sys_user'
|
userType: 'sys_user'
|
||||||
});
|
});
|
||||||
|
|
||||||
type RuleKey = Extract<keyof Api.Auth.RegisterForm, 'username' | 'password' | 'confirmPassword' | 'code' | 'tenantId'>;
|
type RuleKey = Extract<keyof Api.Auth.RegisterForm, 'username' | 'password' | 'confirmPassword' | 'code'>;
|
||||||
|
|
||||||
const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
|
const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
|
||||||
const { formRules, createConfirmPwdRule, createRequiredRule } = useFormRules();
|
const { createConfirmPwdRule, createRequiredRule } = useFormRules();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tenantId: tenantEnabled.value ? formRules.tenantId : [],
|
|
||||||
username: [createRequiredRule($t('form.userName.required'))],
|
username: [createRequiredRule($t('form.userName.required'))],
|
||||||
password: [createRequiredRule($t('form.pwd.required'))],
|
password: [createRequiredRule($t('form.pwd.required'))],
|
||||||
confirmPassword: createConfirmPwdRule(model.password!),
|
confirmPassword: createConfirmPwdRule(model.password!),
|
||||||
@@ -100,9 +96,6 @@ handleFetchCaptchaCode();
|
|||||||
:show-label="false"
|
:show-label="false"
|
||||||
@keyup.enter="() => !registerLoading && handleSubmit()"
|
@keyup.enter="() => !registerLoading && handleSubmit()"
|
||||||
>
|
>
|
||||||
<NFormItem v-if="tenantEnabled" path="tenantId">
|
|
||||||
<NSelect v-model:value="model.tenantId" :options="tenantOption" :enabled="tenantEnabled" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem path="username">
|
<NFormItem path="username">
|
||||||
<NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" />
|
<NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
|
|||||||
@@ -1,237 +0,0 @@
|
|||||||
<script setup lang="tsx">
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { NDivider } from 'naive-ui';
|
|
||||||
import {
|
|
||||||
fetchBatchDeleteTenantPackage,
|
|
||||||
fetchGetTenantPackageList,
|
|
||||||
fetchUpdateTenantPackageStatus
|
|
||||||
} from '@/service/api/system/tenant-package';
|
|
||||||
import { useAppStore } from '@/store/modules/app';
|
|
||||||
import { useAuth } from '@/hooks/business/auth';
|
|
||||||
import { useDownload } from '@/hooks/business/download';
|
|
||||||
import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table';
|
|
||||||
import { useDict } from '@/hooks/business/dict';
|
|
||||||
import { $t } from '@/locales';
|
|
||||||
import ButtonIcon from '@/components/custom/button-icon.vue';
|
|
||||||
import TableHeaderOperation from '@/components/advanced/table-header-operation.vue';
|
|
||||||
import StatusSwitch from '@/components/custom/status-switch.vue';
|
|
||||||
import TenantPackageSearch from './modules/tenant-package-search.vue';
|
|
||||||
import TenantPackageOperateDrawer from './modules/tenant-package-operate-drawer.vue';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TenantPackageList'
|
|
||||||
});
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const { download } = useDownload();
|
|
||||||
const { hasAuth } = useAuth();
|
|
||||||
|
|
||||||
useDict('sys_normal_disable', false);
|
|
||||||
|
|
||||||
const searchParams = ref<Api.System.TenantPackageSearchParams>({
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
packageName: null,
|
|
||||||
status: null,
|
|
||||||
params: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
|
|
||||||
useNaivePaginatedTable({
|
|
||||||
api: () => fetchGetTenantPackageList(searchParams.value),
|
|
||||||
transform: response => defaultTransform(response),
|
|
||||||
onPaginationParamsChange: params => {
|
|
||||||
searchParams.value.pageNum = params.page;
|
|
||||||
searchParams.value.pageSize = params.pageSize;
|
|
||||||
},
|
|
||||||
columns: () => [
|
|
||||||
{
|
|
||||||
type: 'selection',
|
|
||||||
align: 'center',
|
|
||||||
width: 48
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'index',
|
|
||||||
title: $t('common.index'),
|
|
||||||
align: 'center',
|
|
||||||
width: 64
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'packageName',
|
|
||||||
title: $t('page.system.tenantPackage.packageName'),
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'status',
|
|
||||||
title: $t('page.system.tenantPackage.status'),
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 120,
|
|
||||||
render: row => {
|
|
||||||
return (
|
|
||||||
<StatusSwitch
|
|
||||||
v-model:value={row.status}
|
|
||||||
info={row.packageName}
|
|
||||||
onSubmitted={(value, callback) => handleStatusChange(row, value, callback)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'remark',
|
|
||||||
title: $t('page.system.tenantPackage.remark'),
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'operate',
|
|
||||||
title: $t('common.operate'),
|
|
||||||
align: 'center',
|
|
||||||
width: 130,
|
|
||||||
render: row => {
|
|
||||||
const divider = () => {
|
|
||||||
if (!hasAuth('system:tenantPackage:edit') || !hasAuth('system:tenantPackage:remove')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return <NDivider vertical />;
|
|
||||||
};
|
|
||||||
|
|
||||||
const editBtn = () => {
|
|
||||||
if (!hasAuth('system:tenantPackage:edit')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<ButtonIcon
|
|
||||||
text
|
|
||||||
type="primary"
|
|
||||||
icon="material-symbols:drive-file-rename-outline-outline"
|
|
||||||
tooltipContent={$t('common.edit')}
|
|
||||||
onClick={() => edit(row.packageId!)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteBtn = () => {
|
|
||||||
if (!hasAuth('system:tenantPackage:remove')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<ButtonIcon
|
|
||||||
text
|
|
||||||
type="error"
|
|
||||||
icon="material-symbols:delete-outline"
|
|
||||||
tooltipContent={$t('common.delete')}
|
|
||||||
popconfirmContent={$t('common.confirmDelete')}
|
|
||||||
onPositiveClick={() => handleDelete(row.packageId!)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="flex-center gap-8px">
|
|
||||||
{editBtn()}
|
|
||||||
{divider()}
|
|
||||||
{deleteBtn()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
|
|
||||||
useTableOperate(data, 'packageId', getData);
|
|
||||||
|
|
||||||
async function handleBatchDelete() {
|
|
||||||
// request
|
|
||||||
const { error } = await fetchBatchDeleteTenantPackage(checkedRowKeys.value);
|
|
||||||
if (error) return;
|
|
||||||
onBatchDeleted();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleDelete(packageId: CommonType.IdType) {
|
|
||||||
// request
|
|
||||||
const { error } = await fetchBatchDeleteTenantPackage([packageId]);
|
|
||||||
if (error) return;
|
|
||||||
onDeleted();
|
|
||||||
}
|
|
||||||
|
|
||||||
function edit(packageId: CommonType.IdType) {
|
|
||||||
handleEdit(packageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleExport() {
|
|
||||||
download(
|
|
||||||
'/system/tenant/package/export',
|
|
||||||
searchParams,
|
|
||||||
`${$t('page.system.tenantPackage.title')}_${new Date().getTime()}.xlsx`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 处理状态切换 */
|
|
||||||
async function handleStatusChange(
|
|
||||||
row: Api.System.TenantPackage,
|
|
||||||
value: Api.Common.EnableStatus,
|
|
||||||
callback: (flag: boolean) => void
|
|
||||||
) {
|
|
||||||
const { error } = await fetchUpdateTenantPackageStatus({
|
|
||||||
packageId: row.packageId,
|
|
||||||
status: value
|
|
||||||
});
|
|
||||||
|
|
||||||
callback(!error);
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
window.$message?.success($t('page.system.tenantPackage.statusChangeSuccess'));
|
|
||||||
getData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
|
||||||
<TenantPackageSearch v-model:model="searchParams" @search="getDataByPage" />
|
|
||||||
<NCard
|
|
||||||
:title="$t('page.system.tenantPackage.title')"
|
|
||||||
:bordered="false"
|
|
||||||
size="small"
|
|
||||||
class="card-wrapper sm:flex-1-hidden"
|
|
||||||
>
|
|
||||||
<template #header-extra>
|
|
||||||
<TableHeaderOperation
|
|
||||||
v-model:columns="columnChecks"
|
|
||||||
:disabled-delete="checkedRowKeys.length === 0"
|
|
||||||
:loading="loading"
|
|
||||||
:show-add="hasAuth('system:tenantPackage:add')"
|
|
||||||
:show-delete="hasAuth('system:tenantPackage:remove')"
|
|
||||||
:show-export="hasAuth('system:tenantPackage:export')"
|
|
||||||
@add="handleAdd"
|
|
||||||
@delete="handleBatchDelete"
|
|
||||||
@export="handleExport"
|
|
||||||
@refresh="getData"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<NDataTable
|
|
||||||
v-model:checked-row-keys="checkedRowKeys"
|
|
||||||
:columns="columns"
|
|
||||||
:data="data"
|
|
||||||
size="small"
|
|
||||||
:flex-height="!appStore.isMobile"
|
|
||||||
:scroll-x="scrollX"
|
|
||||||
:loading="loading"
|
|
||||||
remote
|
|
||||||
:row-key="row => row.packageId"
|
|
||||||
:pagination="mobilePagination"
|
|
||||||
class="sm:h-full"
|
|
||||||
/>
|
|
||||||
<TenantPackageOperateDrawer
|
|
||||||
v-model:visible="drawerVisible"
|
|
||||||
:operate-type="operateType"
|
|
||||||
:row-data="editingData"
|
|
||||||
@submitted="getData"
|
|
||||||
/>
|
|
||||||
</NCard>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref, watch } from 'vue';
|
|
||||||
import { jsonClone } from '@sa/utils';
|
|
||||||
import { useLoading } from '@sa/hooks';
|
|
||||||
import { fetchCreateTenantPackage, fetchUpdateTenantPackage } from '@/service/api/system/tenant-package';
|
|
||||||
import { fetchGetTenantPackageMenuTreeSelect } from '@/service/api/system/menu';
|
|
||||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
|
||||||
import MenuTree from '@/components/custom/menu-tree.vue';
|
|
||||||
import { $t } from '@/locales';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TenantPackageOperateDrawer'
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/** the type of operation */
|
|
||||||
operateType: NaiveUI.TableOperateType;
|
|
||||||
/** the edit row data */
|
|
||||||
rowData?: Api.System.TenantPackage | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'submitted'): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const menuTreeRef = ref<InstanceType<typeof MenuTree> | null>(null);
|
|
||||||
|
|
||||||
const menuOptions = ref<Api.System.MenuList>([]);
|
|
||||||
|
|
||||||
const { loading: menuLoading, startLoading: startMenuLoading, endLoading: stopMenuLoading } = useLoading();
|
|
||||||
|
|
||||||
const visible = defineModel<boolean>('visible', {
|
|
||||||
default: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const { formRef, validate, restoreValidation } = useNaiveForm();
|
|
||||||
const { createRequiredRule } = useFormRules();
|
|
||||||
|
|
||||||
const title = computed(() => {
|
|
||||||
const titles: Record<NaiveUI.TableOperateType, string> = {
|
|
||||||
add: $t('page.system.tenantPackage.addTenantPackage'),
|
|
||||||
edit: $t('page.system.tenantPackage.editTenantPackage')
|
|
||||||
};
|
|
||||||
return titles[props.operateType];
|
|
||||||
});
|
|
||||||
|
|
||||||
type Model = Api.System.TenantPackageOperateParams;
|
|
||||||
|
|
||||||
const model = ref<Model>(createDefaultModel());
|
|
||||||
|
|
||||||
function createDefaultModel(): Model {
|
|
||||||
return {
|
|
||||||
packageName: '',
|
|
||||||
menuIds: [],
|
|
||||||
remark: '',
|
|
||||||
menuCheckStrictly: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type RuleKey = Extract<keyof Model, 'packageId' | 'packageName'>;
|
|
||||||
|
|
||||||
const rules: Record<RuleKey, App.Global.FormRule> = {
|
|
||||||
packageId: createRequiredRule($t('page.system.tenantPackage.form.packageName.invalid')),
|
|
||||||
packageName: createRequiredRule($t('page.system.tenantPackage.form.packageName.required'))
|
|
||||||
};
|
|
||||||
|
|
||||||
async function handleUpdateModelWhenEdit() {
|
|
||||||
menuOptions.value = [];
|
|
||||||
model.value = createDefaultModel();
|
|
||||||
model.value.menuIds = [];
|
|
||||||
|
|
||||||
if (props.operateType === 'add') {
|
|
||||||
const { data, error } = await fetchGetTenantPackageMenuTreeSelect(0);
|
|
||||||
if (error) return;
|
|
||||||
model.value.menuIds = data.checkedKeys || [];
|
|
||||||
menuOptions.value = data.menus;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.operateType === 'edit' && props.rowData) {
|
|
||||||
startMenuLoading();
|
|
||||||
Object.assign(model.value, jsonClone(props.rowData));
|
|
||||||
const { data, error } = await fetchGetTenantPackageMenuTreeSelect(model.value.packageId!);
|
|
||||||
if (error) return;
|
|
||||||
model.value.menuIds = data.checkedKeys || [];
|
|
||||||
menuOptions.value = data.menus;
|
|
||||||
stopMenuLoading();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeDrawer() {
|
|
||||||
visible.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSubmit() {
|
|
||||||
await validate();
|
|
||||||
|
|
||||||
const { packageId, packageName, remark, menuCheckStrictly } = model.value;
|
|
||||||
|
|
||||||
const menuIds = menuTreeRef.value?.getCheckedMenuIds();
|
|
||||||
// request
|
|
||||||
if (props.operateType === 'add') {
|
|
||||||
const { error } = await fetchCreateTenantPackage({ packageName, menuIds, remark, menuCheckStrictly });
|
|
||||||
if (error) return;
|
|
||||||
window.$message?.success($t('common.addSuccess'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.operateType === 'edit') {
|
|
||||||
const { error } = await fetchUpdateTenantPackage({
|
|
||||||
packageId,
|
|
||||||
packageName,
|
|
||||||
menuIds,
|
|
||||||
remark,
|
|
||||||
menuCheckStrictly
|
|
||||||
});
|
|
||||||
if (error) return;
|
|
||||||
window.$message?.success($t('common.updateSuccess'));
|
|
||||||
}
|
|
||||||
|
|
||||||
closeDrawer();
|
|
||||||
emit('submitted');
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(visible, () => {
|
|
||||||
if (visible.value) {
|
|
||||||
handleUpdateModelWhenEdit();
|
|
||||||
restoreValidation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
|
|
||||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
|
||||||
<NForm ref="formRef" :model="model" :rules="rules">
|
|
||||||
<NFormItem :label="$t('page.system.tenantPackage.packageName')" path="packageName">
|
|
||||||
<NInput
|
|
||||||
v-model:value="model.packageName"
|
|
||||||
:placeholder="$t('page.system.tenantPackage.form.packageName.required')"
|
|
||||||
/>
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem :label="$t('page.system.tenantPackage.menuIds')" path="menuIds">
|
|
||||||
<MenuTree
|
|
||||||
v-if="visible"
|
|
||||||
ref="menuTreeRef"
|
|
||||||
v-model:checked-keys="model.menuIds"
|
|
||||||
v-model:options="menuOptions"
|
|
||||||
v-model:cascade="model.menuCheckStrictly"
|
|
||||||
v-model:loading="menuLoading"
|
|
||||||
:immediate="false"
|
|
||||||
/>
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem :label="$t('page.system.tenantPackage.remark')" path="remark">
|
|
||||||
<NInput
|
|
||||||
v-model:value="model.remark"
|
|
||||||
:placeholder="$t('page.system.tenantPackage.form.remark.required')"
|
|
||||||
type="textarea"
|
|
||||||
/>
|
|
||||||
</NFormItem>
|
|
||||||
</NForm>
|
|
||||||
<template #footer>
|
|
||||||
<NSpace :size="16">
|
|
||||||
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
|
||||||
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
|
||||||
</NSpace>
|
|
||||||
</template>
|
|
||||||
</NDrawerContent>
|
|
||||||
</NDrawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { toRaw } from 'vue';
|
|
||||||
import { jsonClone } from '@sa/utils';
|
|
||||||
import { useDict } from '@/hooks/business/dict';
|
|
||||||
import { useNaiveForm } from '@/hooks/common/form';
|
|
||||||
import { $t } from '@/locales';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TenantPackageSearch'
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'search'): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const { formRef, validate, restoreValidation } = useNaiveForm();
|
|
||||||
|
|
||||||
const { options: sysNormalDisableOptions } = useDict('sys_normal_disable', false);
|
|
||||||
|
|
||||||
const model = defineModel<Api.System.TenantPackageSearchParams>('model', { required: true });
|
|
||||||
|
|
||||||
const defaultModel = jsonClone(toRaw(model.value));
|
|
||||||
|
|
||||||
function resetModel() {
|
|
||||||
Object.assign(model.value, defaultModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function reset() {
|
|
||||||
await restoreValidation();
|
|
||||||
resetModel();
|
|
||||||
emit('search');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function search() {
|
|
||||||
await validate();
|
|
||||||
emit('search');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<NCard :bordered="false" size="small" class="card-wrapper">
|
|
||||||
<NCollapse>
|
|
||||||
<NCollapseItem :title="$t('common.search')" name="user-search">
|
|
||||||
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
|
|
||||||
<NGrid responsive="screen" item-responsive>
|
|
||||||
<NFormItemGi
|
|
||||||
span="24 s:12 m:8"
|
|
||||||
:label="$t('page.system.tenantPackage.packageName')"
|
|
||||||
path="packageName"
|
|
||||||
class="pr-24px"
|
|
||||||
>
|
|
||||||
<NInput
|
|
||||||
v-model:value="model.packageName"
|
|
||||||
:placeholder="$t('page.system.tenantPackage.form.packageName.required')"
|
|
||||||
/>
|
|
||||||
</NFormItemGi>
|
|
||||||
<NFormItemGi
|
|
||||||
span="24 s:12 m:8"
|
|
||||||
:label="$t('page.system.tenantPackage.status')"
|
|
||||||
path="status"
|
|
||||||
class="pr-24px"
|
|
||||||
>
|
|
||||||
<NSelect
|
|
||||||
v-model:value="model.status"
|
|
||||||
:placeholder="$t('page.system.tenantPackage.form.status.required')"
|
|
||||||
:options="sysNormalDisableOptions"
|
|
||||||
clearable
|
|
||||||
/>
|
|
||||||
</NFormItemGi>
|
|
||||||
<NFormItemGi span="24 s:24 m:8" class="pr-24px">
|
|
||||||
<NSpace class="w-full" justify="end">
|
|
||||||
<NButton @click="reset">
|
|
||||||
<template #icon>
|
|
||||||
<icon-ic-round-refresh class="text-icon" />
|
|
||||||
</template>
|
|
||||||
{{ $t('common.reset') }}
|
|
||||||
</NButton>
|
|
||||||
<NButton type="primary" ghost @click="search">
|
|
||||||
<template #icon>
|
|
||||||
<icon-ic-round-search class="text-icon" />
|
|
||||||
</template>
|
|
||||||
{{ $t('common.search') }}
|
|
||||||
</NButton>
|
|
||||||
</NSpace>
|
|
||||||
</NFormItemGi>
|
|
||||||
</NGrid>
|
|
||||||
</NForm>
|
|
||||||
</NCollapseItem>
|
|
||||||
</NCollapse>
|
|
||||||
</NCard>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@@ -1,302 +0,0 @@
|
|||||||
<script setup lang="tsx">
|
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
import { NButton, NDivider } from 'naive-ui';
|
|
||||||
import {
|
|
||||||
fetchBatchDeleteTenant,
|
|
||||||
fetchGetTenantList,
|
|
||||||
fetchSyncTenantConfig,
|
|
||||||
fetchSyncTenantDict,
|
|
||||||
fetchSyncTenantPackage
|
|
||||||
} from '@/service/api/system/tenant';
|
|
||||||
import { useAppStore } from '@/store/modules/app';
|
|
||||||
import { useAuthStore } from '@/store/modules/auth';
|
|
||||||
import { useAuth } from '@/hooks/business/auth';
|
|
||||||
import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table';
|
|
||||||
import { useDownload } from '@/hooks/business/download';
|
|
||||||
import { useDict } from '@/hooks/business/dict';
|
|
||||||
import DictTag from '@/components/custom/dict-tag.vue';
|
|
||||||
import { $t } from '@/locales';
|
|
||||||
import ButtonIcon from '@/components/custom/button-icon.vue';
|
|
||||||
import TenantOperateDrawer from './modules/tenant-operate-drawer.vue';
|
|
||||||
import TenantSearch from './modules/tenant-search.vue';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TenantList'
|
|
||||||
});
|
|
||||||
|
|
||||||
useDict('sys_normal_disable');
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const { download } = useDownload();
|
|
||||||
const { hasAuth } = useAuth();
|
|
||||||
const { userInfo } = useAuthStore();
|
|
||||||
|
|
||||||
const isSuperAdmin = computed(() => {
|
|
||||||
return userInfo.user?.userId === 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
const searchParams = ref<Api.System.TenantSearchParams>({
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
tenantId: null,
|
|
||||||
contactUserName: null,
|
|
||||||
contactPhone: null,
|
|
||||||
companyName: null,
|
|
||||||
params: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
|
|
||||||
useNaivePaginatedTable({
|
|
||||||
api: () => fetchGetTenantList(searchParams.value),
|
|
||||||
transform: response => defaultTransform(response),
|
|
||||||
onPaginationParamsChange: params => {
|
|
||||||
searchParams.value.pageNum = params.page;
|
|
||||||
searchParams.value.pageSize = params.pageSize;
|
|
||||||
},
|
|
||||||
columns: () => [
|
|
||||||
{
|
|
||||||
type: 'selection',
|
|
||||||
align: 'center',
|
|
||||||
width: 48
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'index',
|
|
||||||
title: $t('common.index'),
|
|
||||||
align: 'center',
|
|
||||||
width: 64,
|
|
||||||
render: (_, index) => index + 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'tenantId',
|
|
||||||
title: '租户编号',
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 80
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'contactUserName',
|
|
||||||
title: '联系人',
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 80
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'contactPhone',
|
|
||||||
title: '联系电话',
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'companyName',
|
|
||||||
title: '企业名称',
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'expireTime',
|
|
||||||
title: '过期时间',
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'status',
|
|
||||||
title: '租户状态',
|
|
||||||
align: 'center',
|
|
||||||
minWidth: 120,
|
|
||||||
render(row) {
|
|
||||||
return <DictTag size="small" value={row.status} dictCode="sys_normal_disable" />;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'operate',
|
|
||||||
title: $t('common.operate'),
|
|
||||||
align: 'center',
|
|
||||||
width: 180,
|
|
||||||
render: row => {
|
|
||||||
if (row.tenantId === '000000') return null;
|
|
||||||
|
|
||||||
const editBtn = () => {
|
|
||||||
return (
|
|
||||||
<ButtonIcon
|
|
||||||
type="primary"
|
|
||||||
text
|
|
||||||
icon="material-symbols:drive-file-rename-outline-outline"
|
|
||||||
tooltipContent={$t('common.edit')}
|
|
||||||
onClick={() => edit(row.id!)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const syncBtn = () => {
|
|
||||||
return (
|
|
||||||
<ButtonIcon
|
|
||||||
text
|
|
||||||
type="primary"
|
|
||||||
icon="material-symbols:sync-outline"
|
|
||||||
tooltipContent="同步套餐"
|
|
||||||
popconfirmContent={`确认同步[${row.companyName}]的套餐吗?`}
|
|
||||||
onPositiveClick={() => handleSyncTenantPackage(row)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteBtn = () => {
|
|
||||||
return (
|
|
||||||
<ButtonIcon
|
|
||||||
text
|
|
||||||
type="error"
|
|
||||||
icon="material-symbols:delete-outline"
|
|
||||||
tooltipContent={$t('common.delete')}
|
|
||||||
popconfirmContent={$t('common.confirmDelete')}
|
|
||||||
onPositiveClick={() => handleDelete(row.id!)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const buttons = [];
|
|
||||||
|
|
||||||
if (hasAuth('system:tenant:edit')) buttons.push(editBtn());
|
|
||||||
if (hasAuth('system:tenant:edit')) buttons.push(syncBtn());
|
|
||||||
if (hasAuth('system:tenant:delete')) buttons.push(deleteBtn());
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="flex-center gap-8px">
|
|
||||||
{buttons.map((btn, index) => (
|
|
||||||
<>
|
|
||||||
{index !== 0 && <NDivider vertical />}
|
|
||||||
{btn}
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
|
|
||||||
useTableOperate(data, 'id', getData);
|
|
||||||
|
|
||||||
async function handleBatchDelete() {
|
|
||||||
// request
|
|
||||||
const { error } = await fetchBatchDeleteTenant(checkedRowKeys.value);
|
|
||||||
if (error) return;
|
|
||||||
onBatchDeleted();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleDelete(id: CommonType.IdType) {
|
|
||||||
// request
|
|
||||||
const { error } = await fetchBatchDeleteTenant([id]);
|
|
||||||
if (error) return;
|
|
||||||
onDeleted();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function edit(id: CommonType.IdType) {
|
|
||||||
handleEdit(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSyncTenantDict() {
|
|
||||||
window.$dialog?.warning({
|
|
||||||
title: '同步租户字典',
|
|
||||||
content: '确认同步租户字典吗?',
|
|
||||||
positiveText: '确认',
|
|
||||||
negativeText: '取消',
|
|
||||||
onPositiveClick: async () => {
|
|
||||||
const { error } = await fetchSyncTenantDict();
|
|
||||||
if (error) return;
|
|
||||||
window.$message?.success('同步租户字典成功');
|
|
||||||
await getData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSyncTenantConfig() {
|
|
||||||
window.$dialog?.warning({
|
|
||||||
title: '同步租户参数配置',
|
|
||||||
content: '确认同步租户参数配置吗?',
|
|
||||||
positiveText: '确认',
|
|
||||||
negativeText: '取消',
|
|
||||||
onPositiveClick: async () => {
|
|
||||||
const { error } = await fetchSyncTenantConfig();
|
|
||||||
if (error) return;
|
|
||||||
window.$message?.success('同步租户参数配置成功');
|
|
||||||
await getData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSyncTenantPackage(row: Api.System.Tenant) {
|
|
||||||
const params: Api.System.TenantPackageSyncParams = {
|
|
||||||
tenantId: row.tenantId,
|
|
||||||
packageId: row.packageId
|
|
||||||
};
|
|
||||||
const { error } = await fetchSyncTenantPackage(params);
|
|
||||||
if (error) return;
|
|
||||||
window.$message?.success('同步租户套餐成功');
|
|
||||||
await getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleExport() {
|
|
||||||
download('/system/tenant/export', searchParams.value, `租户列表_${new Date().getTime()}.xlsx`);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
|
||||||
<TenantSearch v-model:model="searchParams" @search="getDataByPage" />
|
|
||||||
<NCard title="租户列表" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
|
|
||||||
<template #header-extra>
|
|
||||||
<TableHeaderOperation
|
|
||||||
v-model:columns="columnChecks"
|
|
||||||
:disabled-delete="checkedRowKeys.length === 0"
|
|
||||||
:loading="loading"
|
|
||||||
:show-add="hasAuth('system:tenant:add')"
|
|
||||||
:show-delete="hasAuth('system:tenant:delete')"
|
|
||||||
:show-export="hasAuth('system:tenant:export')"
|
|
||||||
@add="handleAdd"
|
|
||||||
@delete="handleBatchDelete"
|
|
||||||
@export="handleExport"
|
|
||||||
@refresh="getData"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<NButton v-if="isSuperAdmin" ghost size="small" @click="handleSyncTenantDict">
|
|
||||||
<template #icon>
|
|
||||||
<icon-material-symbols-sync-outline />
|
|
||||||
</template>
|
|
||||||
同步租户字典
|
|
||||||
</NButton>
|
|
||||||
<NButton v-if="isSuperAdmin" ghost size="small" @click="handleSyncTenantConfig">
|
|
||||||
<template #icon>
|
|
||||||
<icon-material-symbols-sync-outline />
|
|
||||||
</template>
|
|
||||||
同步租户参数配置
|
|
||||||
</NButton>
|
|
||||||
</template>
|
|
||||||
</TableHeaderOperation>
|
|
||||||
</template>
|
|
||||||
<NDataTable
|
|
||||||
v-model:checked-row-keys="checkedRowKeys"
|
|
||||||
:columns="columns"
|
|
||||||
:data="data"
|
|
||||||
size="small"
|
|
||||||
:flex-height="!appStore.isMobile"
|
|
||||||
:scroll-x="scrollX"
|
|
||||||
:loading="loading"
|
|
||||||
remote
|
|
||||||
:row-key="row => row.id"
|
|
||||||
:pagination="mobilePagination"
|
|
||||||
class="sm:h-full"
|
|
||||||
/>
|
|
||||||
<TenantOperateDrawer
|
|
||||||
v-model:visible="drawerVisible"
|
|
||||||
:operate-type="operateType"
|
|
||||||
:row-data="editingData"
|
|
||||||
@submitted="getData"
|
|
||||||
/>
|
|
||||||
</NCard>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
:deep(.n-card-header__main) {
|
|
||||||
min-width: 36px !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref, watch } from 'vue';
|
|
||||||
import { useLoading } from '@sa/hooks';
|
|
||||||
import { jsonClone } from '@sa/utils';
|
|
||||||
import { fetchCreateTenant, fetchUpdateTenant } from '@/service/api/system/tenant';
|
|
||||||
import { fetchGetTenantPackageSelectList } from '@/service/api/system/tenant-package';
|
|
||||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
|
||||||
import { $t } from '@/locales';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TenantOperateDrawer'
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/** the type of operation */
|
|
||||||
operateType: NaiveUI.TableOperateType;
|
|
||||||
/** the edit row data */
|
|
||||||
rowData?: Api.System.Tenant | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'submitted'): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const visible = defineModel<boolean>('visible', {
|
|
||||||
default: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const { formRef, validate, restoreValidation } = useNaiveForm();
|
|
||||||
const { createRequiredRule, patternRules } = useFormRules();
|
|
||||||
const { loading: packageLoading, startLoading: startPackageLoading, endLoading: endPackageLoading } = useLoading();
|
|
||||||
const title = computed(() => {
|
|
||||||
const titles: Record<NaiveUI.TableOperateType, string> = {
|
|
||||||
add: '新增租户',
|
|
||||||
edit: '编辑租户'
|
|
||||||
};
|
|
||||||
return titles[props.operateType];
|
|
||||||
});
|
|
||||||
|
|
||||||
type Model = Api.System.TenantOperateParams;
|
|
||||||
|
|
||||||
const model = ref<Model>(createDefaultModel());
|
|
||||||
|
|
||||||
function createDefaultModel(): Model {
|
|
||||||
return {
|
|
||||||
tenantId: '',
|
|
||||||
contactUserName: '',
|
|
||||||
contactPhone: '',
|
|
||||||
companyName: '',
|
|
||||||
licenseNumber: '',
|
|
||||||
address: '',
|
|
||||||
intro: '',
|
|
||||||
domain: '',
|
|
||||||
remark: '',
|
|
||||||
packageId: null,
|
|
||||||
expireTime: null,
|
|
||||||
accountCount: null,
|
|
||||||
status: '0',
|
|
||||||
username: '',
|
|
||||||
password: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type RuleKey = Extract<
|
|
||||||
keyof Model,
|
|
||||||
'id' | 'contactUserName' | 'contactPhone' | 'companyName' | 'packageId' | 'accountCount' | 'username' | 'password'
|
|
||||||
>;
|
|
||||||
|
|
||||||
const rules: Record<RuleKey, App.Global.FormRule | App.Global.FormRule[]> = {
|
|
||||||
id: createRequiredRule('id不能为空'),
|
|
||||||
contactUserName: createRequiredRule('联系人不能为空'),
|
|
||||||
contactPhone: [createRequiredRule('联系电话不能为空'), { ...patternRules.phone, trigger: ['blur', 'change'] }],
|
|
||||||
companyName: createRequiredRule('企业名称不能为空'),
|
|
||||||
packageId: createRequiredRule('租户套餐不能为空'),
|
|
||||||
accountCount: createRequiredRule('用户数量不能为空'),
|
|
||||||
username: [
|
|
||||||
createRequiredRule('管理员账号不能为空'),
|
|
||||||
{
|
|
||||||
min: 2,
|
|
||||||
max: 20,
|
|
||||||
message: '账号长度必须介于2-20之间',
|
|
||||||
trigger: ['blur', 'change']
|
|
||||||
}
|
|
||||||
],
|
|
||||||
password: [
|
|
||||||
createRequiredRule('管理员密码不能为空'),
|
|
||||||
{
|
|
||||||
min: 5,
|
|
||||||
max: 20,
|
|
||||||
message: '密码长度必须介于5-20之间',
|
|
||||||
trigger: ['blur', 'change']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
/** the enabled package options */
|
|
||||||
const packageOptions = ref<CommonType.Option<CommonType.IdType>[]>([]);
|
|
||||||
async function getPackageOptions() {
|
|
||||||
startPackageLoading();
|
|
||||||
const { error, data } = await fetchGetTenantPackageSelectList();
|
|
||||||
if (!error) {
|
|
||||||
packageOptions.value = data.map(item => ({
|
|
||||||
label: item.packageName,
|
|
||||||
value: item.packageId
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
endPackageLoading();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleUpdateModelWhenEdit() {
|
|
||||||
model.value = createDefaultModel();
|
|
||||||
|
|
||||||
if (props.operateType === 'edit' && props.rowData) {
|
|
||||||
Object.assign(model.value, jsonClone(props.rowData));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeDrawer() {
|
|
||||||
visible.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSubmit() {
|
|
||||||
await validate();
|
|
||||||
|
|
||||||
const {
|
|
||||||
id,
|
|
||||||
tenantId,
|
|
||||||
contactUserName,
|
|
||||||
contactPhone,
|
|
||||||
companyName,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
licenseNumber,
|
|
||||||
address,
|
|
||||||
intro,
|
|
||||||
domain,
|
|
||||||
remark,
|
|
||||||
packageId,
|
|
||||||
expireTime,
|
|
||||||
accountCount,
|
|
||||||
status
|
|
||||||
} = model.value;
|
|
||||||
|
|
||||||
// request
|
|
||||||
if (props.operateType === 'add') {
|
|
||||||
const { error } = await fetchCreateTenant({
|
|
||||||
contactUserName,
|
|
||||||
contactPhone,
|
|
||||||
companyName,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
licenseNumber,
|
|
||||||
address,
|
|
||||||
intro,
|
|
||||||
domain,
|
|
||||||
remark,
|
|
||||||
packageId,
|
|
||||||
expireTime,
|
|
||||||
accountCount,
|
|
||||||
status
|
|
||||||
});
|
|
||||||
if (error) return;
|
|
||||||
window.$message?.success($t('common.addSuccess'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.operateType === 'edit') {
|
|
||||||
const { error } = await fetchUpdateTenant({
|
|
||||||
id,
|
|
||||||
tenantId,
|
|
||||||
contactUserName,
|
|
||||||
contactPhone,
|
|
||||||
companyName,
|
|
||||||
licenseNumber,
|
|
||||||
address,
|
|
||||||
intro,
|
|
||||||
domain,
|
|
||||||
remark,
|
|
||||||
packageId,
|
|
||||||
expireTime,
|
|
||||||
accountCount,
|
|
||||||
status
|
|
||||||
});
|
|
||||||
if (error) return;
|
|
||||||
window.$message?.success($t('common.updateSuccess'));
|
|
||||||
}
|
|
||||||
|
|
||||||
closeDrawer();
|
|
||||||
emit('submitted');
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(visible, () => {
|
|
||||||
if (visible.value) {
|
|
||||||
getPackageOptions();
|
|
||||||
handleUpdateModelWhenEdit();
|
|
||||||
restoreValidation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
|
|
||||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
|
||||||
<NForm ref="formRef" :model="model" :rules="rules">
|
|
||||||
<NDivider>基本信息</NDivider>
|
|
||||||
<NFormItem label="企业名称" path="companyName">
|
|
||||||
<NInput v-model:value="model.companyName" placeholder="请输入企业名称" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="联系人" path="contactUserName">
|
|
||||||
<NInput v-model:value="model.contactUserName" placeholder="请输入联系人" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="联系电话" path="contactPhone">
|
|
||||||
<NInput v-model:value="model.contactPhone" placeholder="请输入联系电话" />
|
|
||||||
</NFormItem>
|
|
||||||
<div v-if="props.operateType === 'add'">
|
|
||||||
<NDivider>管理员信息</NDivider>
|
|
||||||
<NFormItem label="管理员账号" path="username">
|
|
||||||
<NInput v-model:value="model.username" placeholder="请输入管理员账号" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="管理员密码" path="password">
|
|
||||||
<NInput
|
|
||||||
v-model:value="model.password"
|
|
||||||
type="password"
|
|
||||||
show-password-on="click"
|
|
||||||
placeholder="请输入管理员密码"
|
|
||||||
/>
|
|
||||||
</NFormItem>
|
|
||||||
</div>
|
|
||||||
<NDivider>租户设置</NDivider>
|
|
||||||
<NFormItem label="租户套餐" path="packageId">
|
|
||||||
<NSelect
|
|
||||||
v-model:value="model.packageId"
|
|
||||||
clearable
|
|
||||||
:disabled="props.operateType === 'edit'"
|
|
||||||
placeholder="请选择租户套餐"
|
|
||||||
:options="packageOptions"
|
|
||||||
:loading="packageLoading"
|
|
||||||
/>
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="过期时间" path="expireTime">
|
|
||||||
<NDatePicker
|
|
||||||
v-model:formatted-value="model.expireTime"
|
|
||||||
type="datetime"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
clearable
|
|
||||||
class="w-full"
|
|
||||||
/>
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem path="accountCount">
|
|
||||||
<template #label>
|
|
||||||
<div class="flex-center">
|
|
||||||
<FormTip content="-1不限制用户数量" />
|
|
||||||
<span>用户数量</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<NInputNumber v-model:value="model.accountCount" placeholder="请输入用户数量" min="-1" class="w-full" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem path="domain">
|
|
||||||
<template #label>
|
|
||||||
<div class="flex-center">
|
|
||||||
<FormTip
|
|
||||||
content="可填写域名/端口 填写域名如: www.test.com 或者 www.test.com:8080 填写ip:端口如: 127.0.0.1:8080"
|
|
||||||
/>
|
|
||||||
<span>绑定域名</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<NInputGroup>
|
|
||||||
<NInputGroupLabel>http(s)://</NInputGroupLabel>
|
|
||||||
<NInput v-model:value="model.domain" placeholder="请输入" />
|
|
||||||
</NInputGroup>
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="租户状态" path="status">
|
|
||||||
<DictRadio v-model:value="model.status" dict-code="sys_normal_disable" />
|
|
||||||
</NFormItem>
|
|
||||||
<NDivider>企业信息</NDivider>
|
|
||||||
<NFormItem label="企业地址" path="address">
|
|
||||||
<NInput v-model:value="model.address" placeholder="请输入企业地址" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="企业代码" path="licenseNumber">
|
|
||||||
<NInput v-model:value="model.licenseNumber" placeholder="请输入企业代码" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="企业简介" path="intro">
|
|
||||||
<NInput v-model:value="model.intro" type="textarea" placeholder="请输入企业简介" />
|
|
||||||
</NFormItem>
|
|
||||||
<NFormItem label="备注" path="remark">
|
|
||||||
<NInput v-model:value="model.remark" type="textarea" placeholder="请输入备注" />
|
|
||||||
</NFormItem>
|
|
||||||
</NForm>
|
|
||||||
<template #footer>
|
|
||||||
<NSpace :size="16">
|
|
||||||
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
|
||||||
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
|
||||||
</NSpace>
|
|
||||||
</template>
|
|
||||||
</NDrawerContent>
|
|
||||||
</NDrawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@/service/api/system/tenant-package
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { toRaw } from 'vue';
|
|
||||||
import { jsonClone } from '@sa/utils';
|
|
||||||
import { useNaiveForm } from '@/hooks/common/form';
|
|
||||||
import { $t } from '@/locales';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TenantSearch'
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'search'): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const { formRef, validate, restoreValidation } = useNaiveForm();
|
|
||||||
|
|
||||||
const model = defineModel<Api.System.TenantSearchParams>('model', { required: true });
|
|
||||||
|
|
||||||
const defaultModel = jsonClone(toRaw(model.value));
|
|
||||||
|
|
||||||
function resetModel() {
|
|
||||||
Object.assign(model.value, defaultModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function reset() {
|
|
||||||
await restoreValidation();
|
|
||||||
resetModel();
|
|
||||||
emit('search');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function search() {
|
|
||||||
await validate();
|
|
||||||
emit('search');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<NCard :bordered="false" size="small" class="card-wrapper">
|
|
||||||
<NCollapse>
|
|
||||||
<NCollapseItem :title="$t('common.search')" name="user-search">
|
|
||||||
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
|
|
||||||
<NGrid responsive="screen" item-responsive>
|
|
||||||
<NFormItemGi span="24 s:12 m:6" label="租户编号" path="tenantId" class="pr-24px">
|
|
||||||
<NInput v-model:value="model.tenantId as string" placeholder="请输入租户编号" />
|
|
||||||
</NFormItemGi>
|
|
||||||
<NFormItemGi span="24 s:12 m:6" label="联系人" path="contactUserName" class="pr-24px">
|
|
||||||
<NInput v-model:value="model.contactUserName" placeholder="请输入联系人" />
|
|
||||||
</NFormItemGi>
|
|
||||||
<NFormItemGi span="24 s:12 m:6" label="联系电话" path="contactPhone" class="pr-24px">
|
|
||||||
<NInput v-model:value="model.contactPhone" placeholder="请输入联系电话" />
|
|
||||||
</NFormItemGi>
|
|
||||||
<NFormItemGi span="24 s:12 m:6" label="企业名称" path="companyName" class="pr-24px">
|
|
||||||
<NInput v-model:value="model.companyName" placeholder="请输入企业名称" />
|
|
||||||
</NFormItemGi>
|
|
||||||
<NFormItemGi span="24" class="pr-24px">
|
|
||||||
<NSpace class="w-full" justify="end">
|
|
||||||
<NButton @click="reset">
|
|
||||||
<template #icon>
|
|
||||||
<icon-ic-round-refresh class="text-icon" />
|
|
||||||
</template>
|
|
||||||
{{ $t('common.reset') }}
|
|
||||||
</NButton>
|
|
||||||
<NButton type="primary" ghost @click="search">
|
|
||||||
<template #icon>
|
|
||||||
<icon-ic-round-search class="text-icon" />
|
|
||||||
</template>
|
|
||||||
{{ $t('common.search') }}
|
|
||||||
</NButton>
|
|
||||||
</NSpace>
|
|
||||||
</NFormItemGi>
|
|
||||||
</NGrid>
|
|
||||||
</NForm>
|
|
||||||
</NCollapseItem>
|
|
||||||
</NCollapse>
|
|
||||||
</NCard>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
Reference in New Issue
Block a user