diff --git a/src/apis/auth/index.ts b/src/apis/auth/index.ts index 6b7cd93..f804d2b 100644 --- a/src/apis/auth/index.ts +++ b/src/apis/auth/index.ts @@ -5,19 +5,29 @@ export type * from './type' const BASE_URL = '/auth' -/** @desc 账号登录 */ -export function accountLogin(req: T.AccountLoginReq) { - return http.post(`${BASE_URL}/login`, req) +const login = (req: T.AccountLoginReq | T.PhoneLoginReq | T.EmailLoginReq, tenantCode?: string) => { + const headers = {} + if (tenantCode) { + headers['X-Tenant-Code'] = tenantCode + } + return http.post(`${BASE_URL}/login`, req, { + headers, + }) } -/** @desc 手机号登录 */ -export function phoneLogin(req: T.PhoneLoginReq) { - return http.post(`${BASE_URL}/login`, req) +/** @desc 账号登录 */ +export function accountLogin(req: T.AccountLoginReq, tenantCode?: string) { + return login(req, tenantCode) } /** @desc 邮箱登录 */ -export function emailLogin(req: T.EmailLoginReq) { - return http.post(`${BASE_URL}/login`, req) +export function emailLogin(req: T.EmailLoginReq, tenantCode?: string) { + return login(req, tenantCode) +} + +/** @desc 手机号登录 */ +export function phoneLogin(req: T.PhoneLoginReq, tenantCode?: string) { + return login(req, tenantCode) } /** @desc 三方账号登录 */ diff --git a/src/apis/auth/type.ts b/src/apis/auth/type.ts index 36b187d..2db1fd5 100644 --- a/src/apis/auth/type.ts +++ b/src/apis/auth/type.ts @@ -80,6 +80,7 @@ export interface EmailLoginReq extends AuthReq { /** 登录响应类型 */ export interface LoginResp { token: string + tenantId: string } /** 第三方登录授权类型 */ diff --git a/src/apis/common/index.ts b/src/apis/common/index.ts index 8dbb1bd..66d535f 100644 --- a/src/apis/common/index.ts +++ b/src/apis/common/index.ts @@ -1,3 +1,2 @@ -export * from './common' export * from './captcha' export * from './dashboard' diff --git a/src/apis/index.ts b/src/apis/index.ts index 453901a..90be2e0 100644 --- a/src/apis/index.ts +++ b/src/apis/index.ts @@ -3,13 +3,17 @@ export * from './auth' export * from './common' export * from './monitor' export * from './system' -export * from './code' +export * from './open' +export * from './tenant' export * from './schedule' +export * from './code' export * from './area/type' export * from './auth/type' export * from './common/type' export * from './monitor/type' export * from './system/type' -export * from './code/type' +export * from './open/type' +export * from './tenant/type' export * from './schedule/type' +export * from './code/type' diff --git a/src/apis/open/index.ts b/src/apis/open/index.ts new file mode 100644 index 0000000..57a8338 --- /dev/null +++ b/src/apis/open/index.ts @@ -0,0 +1 @@ +export * from './app' diff --git a/src/apis/common/common.ts b/src/apis/system/common.ts similarity index 84% rename from src/apis/common/common.ts rename to src/apis/system/common.ts index 004abbc..0fcc629 100644 --- a/src/apis/common/common.ts +++ b/src/apis/system/common.ts @@ -2,7 +2,7 @@ import type { TreeNodeData } from '@arco-design/web-vue' import http from '@/utils/http' import type { LabelValueState } from '@/types/global' -const BASE_URL = '/common' +const BASE_URL = '/system/common' /** @desc 查询部门树 */ export function listDeptTree(query: { description: string | unknown }) { @@ -35,6 +35,11 @@ export function listSiteOptionDict() { } /** @desc 上传文件 */ -export function uploadFile(data: FormData) { +export function upload(data: FormData) { return http.post(`${BASE_URL}/file`, data) } + +/** @desc 查询租户开启状态 */ +export function getTenantStatus() { + return http.get(`${BASE_URL}/dict/option/tenant`) +} diff --git a/src/apis/system/index.ts b/src/apis/system/index.ts index 8e7bb5b..2295982 100644 --- a/src/apis/system/index.ts +++ b/src/apis/system/index.ts @@ -1,3 +1,4 @@ +export * from './common' export * from './user' export * from './role' export * from './menu' diff --git a/src/apis/tenant/common.ts b/src/apis/tenant/common.ts new file mode 100644 index 0000000..b2cefe4 --- /dev/null +++ b/src/apis/tenant/common.ts @@ -0,0 +1,14 @@ +import http from '@/utils/http' +import type { LabelValueState } from '@/types/global' + +const BASE_URL = '/tenant/common' + +/** @desc 查询租户套餐列表 */ +export function listTenantPackageDict(query?: { description: string, status: number }) { + return http.get(`${BASE_URL}/dict/package`, query) +} + +/** @desc 根据域名查询租户 ID */ +export function getTenantIdByDomain(domain: string) { + return http.get(`${BASE_URL}/id`, { domain }) +} diff --git a/src/apis/tenant/index.ts b/src/apis/tenant/index.ts new file mode 100644 index 0000000..2b9c52d --- /dev/null +++ b/src/apis/tenant/index.ts @@ -0,0 +1,3 @@ +export * from './common' +export * from './management' +export * from './package' diff --git a/src/apis/tenant/management.ts b/src/apis/tenant/management.ts new file mode 100644 index 0000000..3c356d7 --- /dev/null +++ b/src/apis/tenant/management.ts @@ -0,0 +1,36 @@ +import type * as T from './type' +import http from '@/utils/http' + +export type * from './type' + +const BASE_URL = '/tenant/management' + +/** @desc 查询租户列表 */ +export function listTenant(query: T.TenantPageQuery) { + return http.get>(`${BASE_URL}`, query) +} + +/** @desc 查询租户详情 */ +export function getTenant(id: string) { + return http.get(`${BASE_URL}/${id}`) +} + +/** @desc 新增租户 */ +export function addTenant(data: any) { + return http.post(`${BASE_URL}`, data) +} + +/** @desc 修改租户 */ +export function updateTenant(data: any, id: string) { + return http.put(`${BASE_URL}/${id}`, data) +} + +/** @desc 删除租户 */ +export function deleteTenant(id: string) { + return http.del(`${BASE_URL}/${id}`) +} + +/** @desc 修改租户管理员密码 */ +export const updateTenantAdminUserPwd = (data: any, id: string) => { + return http.put(`${BASE_URL}/${id}/admin/pwd`, data) +} diff --git a/src/apis/tenant/package.ts b/src/apis/tenant/package.ts new file mode 100644 index 0000000..97ba1a8 --- /dev/null +++ b/src/apis/tenant/package.ts @@ -0,0 +1,41 @@ +import type * as T from './type' +import http from '@/utils/http' + +export type * from './type' + +const BASE_URL = '/tenant/package' + +/** @desc 查询租户套餐列表 */ +export function listTenantPackage(query: T.TenantPackagePageQuery) { + return http.get>(`${BASE_URL}`, query) +} + +/** @desc 查询租户套餐详情 */ +export function getTenantPackage(id: string) { + return http.get(`${BASE_URL}/${id}`) +} + +/** @desc 新增租户套餐 */ +export function addTenantPackage(data: any) { + return http.post(`${BASE_URL}`, data) +} + +/** @desc 修改租户套餐 */ +export function updateTenantPackage(data: any, id: string) { + return http.put(`${BASE_URL}/${id}`, data) +} + +/** @desc 删除租户套餐 */ +export function deleteTenantPackage(id: string) { + return http.del(`${BASE_URL}/${id}`) +} + +/** @desc 查询所有套餐 */ +export function listAllTenantPackage() { + return http.get(`${BASE_URL}/list`) +} + +/** @desc 查询套餐菜单 */ +export function listTenantPackageMenu() { + return http.get(`${BASE_URL}/menu/tree`) +} diff --git a/src/apis/tenant/type.ts b/src/apis/tenant/type.ts new file mode 100644 index 0000000..d8695b5 --- /dev/null +++ b/src/apis/tenant/type.ts @@ -0,0 +1,48 @@ +/** 租户 */ +export interface TenantResp { + id: string + name: string + code: string + domain: string + expireTime: string + description: number + status: string + packageId: string + createUser: string + createTime: string + updateUser: string + updateTime: string + createUserString: string + updateUserString: string + packageName: string +} +export interface TenantQuery { + description?: string + packageId?: string + status?: string + sort: Array +} +export interface TenantPageQuery extends TenantQuery, PageQuery {} + +/** 租户套餐 */ +export interface TenantPackageResp { + id: string + name: string + sort: number + menuCheckStrictly: string + description: string + status: string + menuIds: [] + createUser: string + createTime: string + updateUser: string + updateTime: string + createUserString: string + updateUserString: string +} +export interface TenantPackageQuery { + description?: string + status?: string + sort: Array +} +export interface TenantPackagePageQuery extends TenantPackageQuery, PageQuery {} diff --git a/src/assets/icons/block-storage.svg b/src/assets/icons/block-storage.svg new file mode 100644 index 0000000..a12ac8a --- /dev/null +++ b/src/assets/icons/block-storage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/project.svg b/src/assets/icons/project.svg new file mode 100644 index 0000000..4c6b90a --- /dev/null +++ b/src/assets/icons/project.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/user-management.svg b/src/assets/icons/user-management.svg new file mode 100644 index 0000000..cede964 --- /dev/null +++ b/src/assets/icons/user-management.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/hooks/app/useDept.ts b/src/hooks/app/useDept.ts index 2cceb8f..964b1af 100644 --- a/src/hooks/app/useDept.ts +++ b/src/hooks/app/useDept.ts @@ -1,6 +1,6 @@ import { ref } from 'vue' import type { TreeNodeData } from '@arco-design/web-vue' -import { listDeptTree } from '@/apis' +import { listDeptTree } from '@/apis/system' /** 部门模块 */ export function useDept(options?: { onSuccess?: () => void }) { diff --git a/src/hooks/app/useDict.ts b/src/hooks/app/useDict.ts index 1c587e5..2f90330 100644 --- a/src/hooks/app/useDict.ts +++ b/src/hooks/app/useDict.ts @@ -1,5 +1,5 @@ import { ref, toRefs } from 'vue' -import { listCommonDict } from '@/apis' +import { listCommonDict } from '@/apis/system' import { useDictStore } from '@/stores' const pendingRequests = new Map>() diff --git a/src/hooks/app/useMenu.ts b/src/hooks/app/useMenu.ts index d3e0309..2ca0105 100644 --- a/src/hooks/app/useMenu.ts +++ b/src/hooks/app/useMenu.ts @@ -1,6 +1,7 @@ import { ref } from 'vue' import type { TreeNodeData } from '@arco-design/web-vue' -import { listMenuTree } from '@/apis' +import { listMenuTree } from '@/apis/system' +import { listTenantPackageMenu } from '@/apis/tenant/package' /** 菜单模块 */ export function useMenu(options?: { onSuccess?: () => void }) { @@ -17,5 +18,18 @@ export function useMenu(options?: { onSuccess?: () => void }) { loading.value = false } } - return { menuList, getMenuList, loading } + + // 获取租户套餐菜单 + const getTenantPackageMenuList = async () => { + try { + loading.value = true + const res = await listTenantPackageMenu() + menuList.value = res.data + options?.onSuccess && options.onSuccess() + } finally { + loading.value = false + } + } + + return { menuList, getMenuList, loading, getTenantPackageMenuList } } diff --git a/src/hooks/app/useRole.ts b/src/hooks/app/useRole.ts index d3878a7..6eb5e7f 100644 --- a/src/hooks/app/useRole.ts +++ b/src/hooks/app/useRole.ts @@ -1,5 +1,5 @@ import { ref } from 'vue' -import { listRoleDict } from '@/apis' +import { listRoleDict } from '@/apis/system' import type { LabelValueState } from '@/types/global' /** 角色模块 */ diff --git a/src/stores/index.ts b/src/stores/index.ts index 875abe8..2ec60fa 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -6,6 +6,7 @@ export * from './modules/route' export * from './modules/tabs' export * from './modules/dict' export * from './modules/user' +export * from './modules/tenant' const pinia = createPinia() pinia.use(piniaPluginPersistedstate) diff --git a/src/stores/modules/app.ts b/src/stores/modules/app.ts index 286834f..321656d 100644 --- a/src/stores/modules/app.ts +++ b/src/stores/modules/app.ts @@ -1,7 +1,7 @@ import { defineStore } from 'pinia' import { computed, reactive, toRefs } from 'vue' import { generate, getRgbStr } from '@arco-design/color' -import { type BasicConfig, listSiteOptionDict } from '@/apis' +import { type BasicConfig, listSiteOptionDict } from '@/apis/system' import { getSettings } from '@/config/setting' const storeSetup = () => { diff --git a/src/stores/modules/tenant.ts b/src/stores/modules/tenant.ts new file mode 100644 index 0000000..e9ba0ca --- /dev/null +++ b/src/stores/modules/tenant.ts @@ -0,0 +1,40 @@ +import { defineStore } from 'pinia' +import { computed, ref } from 'vue' + +export const useTenantStore = defineStore('tenant', () => { + const tenantEnabled = ref(false) + const tenantId = ref() + + const setTenantEnable = (status: boolean) => { + tenantEnabled.value = status + } + const setTenantId = (id: string) => { + tenantId.value = id + } + + // 判断是否需要用户输入租户编码 + const needInputTenantCode = computed(() => { + return tenantEnabled.value && !tenantId.value + }) + + // 判断租户是否已正确配置 + const isTenantConfigured = computed(() => { + return tenantEnabled.value && !!tenantId.value + }) + + // 清空租户ID + const resetTenantId = () => { + tenantId.value = undefined + } + return { + tenantEnabled, + tenantId, + setTenantEnable, + setTenantId, + needInputTenantCode, + isTenantConfigured, + resetTenantId, + } +}, { + persist: { paths: ['tenantEnabled', 'tenantId'], storage: localStorage }, +}) diff --git a/src/stores/modules/user.ts b/src/stores/modules/user.ts index a363b38..34e3b2c 100644 --- a/src/stores/modules/user.ts +++ b/src/stores/modules/user.ts @@ -1,5 +1,6 @@ import { defineStore } from 'pinia' import { computed, reactive, ref } from 'vue' +import { useTenantStore } from './tenant' import { resetRouter } from '@/router' import { type AccountLoginReq, @@ -18,6 +19,7 @@ import { clearToken, getToken, setToken } from '@/utils/auth' import { resetHasRouteFlag } from '@/router/guard' const storeSetup = () => { + const tenantStore = useTenantStore() const userInfo = reactive({ id: '', username: '', @@ -41,7 +43,6 @@ const storeSetup = () => { const pwdExpiredShow = ref(true) const roles = ref([]) // 当前用户角色 const permissions = ref([]) // 当前角色权限标识集合 - // 重置token const resetToken = () => { token.value = '' @@ -50,30 +51,34 @@ const storeSetup = () => { } // 登录 - const accountLogin = async (req: AccountLoginReq) => { - const res = await accountLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.ACCOUNT }) + const accountLogin = async (req: AccountLoginReq, tenantCode?: string) => { + const res = await accountLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.ACCOUNT }, tenantCode) setToken(res.data.token) + tenantStore.setTenantId(res.data.tenantId) token.value = res.data.token } // 邮箱登录 - const emailLogin = async (req: EmailLoginReq) => { - const res = await emailLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.EMAIL }) + const emailLogin = async (req: EmailLoginReq, tenantCode?: string) => { + const res = await emailLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.EMAIL }, tenantCode) setToken(res.data.token) + tenantStore.setTenantId(res.data.tenantId) token.value = res.data.token } // 手机号登录 - const phoneLogin = async (req: PhoneLoginReq) => { - const res = await phoneLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.PHONE }) + const phoneLogin = async (req: PhoneLoginReq, tenantCode?: string) => { + const res = await phoneLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.PHONE }, tenantCode) setToken(res.data.token) + tenantStore.setTenantId(res.data.tenantId) token.value = res.data.token } // 三方账号登录 const socialLogin = async (source: string, req: any) => { - const res = await socialLoginApi({ ...req, source, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.SOCIAL }) + const res: any = await socialLoginApi({ ...req, source, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.SOCIAL }) setToken(res.data.token) + tenantStore.setTenantId(res.data.tenantId) token.value = res.data.token } @@ -84,6 +89,7 @@ const storeSetup = () => { pwdExpiredShow.value = true resetToken() resetRouter() + tenantStore.resetTenantId() } // 退出登录 diff --git a/src/types/components.d.ts b/src/types/components.d.ts index 7ea3f11..89686ef 100644 --- a/src/types/components.d.ts +++ b/src/types/components.d.ts @@ -56,6 +56,7 @@ declare module 'vue' { RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] SecondForm: typeof import('./../components/GenCron/CronForm/component/second-form.vue')['default'] + SelectTenant: typeof import('./../components/SelectTenant/index.vue')['default'] SplitPanel: typeof import('./../components/SplitPanel/index.vue')['default'] TextCopy: typeof import('./../components/TextCopy/index.vue')['default'] UserSelect: typeof import('./../components/UserSelect/index.vue')['default'] diff --git a/src/utils/http.ts b/src/utils/http.ts index 5868f50..61b5d28 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -1,6 +1,7 @@ import axios from 'axios' import qs from 'query-string' import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios' +import { useTenantStore } from '@/stores/modules/tenant' import { useUserStore } from '@/stores' import { getToken } from '@/utils/auth' import modalErrorWrapper from '@/utils/modal-error-wrapper' @@ -51,12 +52,16 @@ const handleError = (msg: string) => { http.interceptors.request.use( (config: AxiosRequestConfig) => { const token = getToken() + if (!config.headers) { + config.headers = {} + } if (token) { - if (!config.headers) { - config.headers = {} - } config.headers.Authorization = `Bearer ${token}` } + const tenantStore = useTenantStore() + if (tenantStore.tenantEnabled && tenantStore.tenantId) { + config.headers['X-Tenant-Id'] = tenantStore.tenantId + } return config }, (error) => Promise.reject(error), diff --git a/src/views/login/components/account/index.vue b/src/views/login/components/account/index.vue index 32431bd..396a571 100644 --- a/src/views/login/components/account/index.vue +++ b/src/views/login/components/account/index.vue @@ -8,6 +8,9 @@ size="large" @submit="handleLogin" > + + + @@ -41,7 +44,7 @@ import { type FormInstance, Message } from '@arco-design/web-vue' import { useStorage } from '@vueuse/core' import { getImageCaptcha } from '@/apis/common' -import { useTabsStore, useUserStore } from '@/stores' +import { useTabsStore, useTenantStore, useUserStore } from '@/stores' import { encryptByRsa } from '@/utils/encrypt' const loginConfig = useStorage('login-config', { @@ -55,7 +58,7 @@ const loginConfig = useStorage('login-config', { const isCaptchaEnabled = ref(true) // 验证码图片 const captchaImgBase64 = ref() - +const tenantCode = ref() const formRef = ref() const form = reactive({ username: loginConfig.value.username, @@ -64,6 +67,7 @@ const form = reactive({ uuid: '', expired: false, }) +// 校验规则部分 const rules: FormInstance['rules'] = { username: [{ required: true, message: '请输入用户名' }], password: [{ required: true, message: '请输入密码' }], @@ -104,6 +108,7 @@ const getCaptcha = () => { }) } +const tenantStore = useTenantStore() const userStore = useUserStore() const tabsStore = useTabsStore() const router = useRouter() @@ -114,12 +119,13 @@ const handleLogin = async () => { const isInvalid = await formRef.value?.validate() if (isInvalid) return loading.value = true + await userStore.accountLogin({ username: form.username, password: encryptByRsa(form.password) || '', captcha: form.captcha, uuid: form.uuid, - }) + }, tenantCode.value) tabsStore.reset() const { redirect, ...othersQuery } = router.currentRoute.value.query const { rememberMe } = loginConfig.value diff --git a/src/views/login/components/email/index.vue b/src/views/login/components/email/index.vue index 4566a68..4f2791e 100644 --- a/src/views/login/components/email/index.vue +++ b/src/views/login/components/email/index.vue @@ -8,6 +8,9 @@ size="large" @submit="handleLogin" > + + + @@ -42,7 +45,7 @@ import { type FormInstance, Message } from '@arco-design/web-vue' import type { BehaviorCaptchaReq } from '@/apis' // import { type BehaviorCaptchaReq, getEmailCaptcha } from '@/apis' -import { useTabsStore, useUserStore } from '@/stores' +import { useTabsStore, useTenantStore, useUserStore } from '@/stores' import * as Regexp from '@/utils/regexp' const formRef = ref() @@ -50,6 +53,7 @@ const form = reactive({ email: '', captcha: '', }) +const tenantCode = ref() const rules: FormInstance['rules'] = { email: [ @@ -59,6 +63,7 @@ const rules: FormInstance['rules'] = { captcha: [{ required: true, message: '请输入验证码' }], } +const tenantStore = useTenantStore() const userStore = useUserStore() const tabsStore = useTabsStore() const router = useRouter() @@ -69,7 +74,7 @@ const handleLogin = async () => { const isInvalid = await formRef.value?.validate() if (isInvalid) return loading.value = true - await userStore.emailLogin(form) + await userStore.emailLogin(form, tenantCode.value) tabsStore.reset() const { redirect, ...othersQuery } = router.currentRoute.value.query diff --git a/src/views/login/components/phone/index.vue b/src/views/login/components/phone/index.vue index 413a68c..09e7161 100644 --- a/src/views/login/components/phone/index.vue +++ b/src/views/login/components/phone/index.vue @@ -8,6 +8,9 @@ size="large" @submit="handleLogin" > + + + @@ -42,7 +45,7 @@ import { type FormInstance, Message } from '@arco-design/web-vue' // import type { BehaviorCaptchaReq } from '@/apis' import { type BehaviorCaptchaReq, getSmsCaptcha } from '@/apis' -import { useTabsStore, useUserStore } from '@/stores' +import { useTabsStore, useTenantStore, useUserStore } from '@/stores' import * as Regexp from '@/utils/regexp' const formRef = ref() @@ -50,6 +53,7 @@ const form = reactive({ phone: '', captcha: '', }) +const tenantCode = ref() const rules: FormInstance['rules'] = { phone: [ @@ -59,6 +63,7 @@ const rules: FormInstance['rules'] = { captcha: [{ required: true, message: '请输入验证码' }], } +const tenantStore = useTenantStore() const userStore = useUserStore() const tabsStore = useTabsStore() const router = useRouter() @@ -69,7 +74,7 @@ const handleLogin = async () => { if (isInvalid) return try { loading.value = true - await userStore.phoneLogin(form) + await userStore.phoneLogin(form, tenantCode.value) tabsStore.reset() const { redirect, ...othersQuery } = router.currentRoute.value.query diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 636d078..0de9a37 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -78,10 +78,10 @@
账号/手机号登录
邮箱登录
- + - +
@@ -97,12 +97,16 @@ import PhoneLogin from './components/phone/index.vue' import EmailLogin from './components/email/index.vue' import { socialAuth } from '@/apis/auth' import { useAppStore } from '@/stores' +import { useTenantStore } from '@/stores/modules/tenant' import { useDevice } from '@/hooks' +import { getTenantIdByDomain, getTenantStatus } from '@/apis' defineOptions({ name: 'Login' }) -const { isDesktop } = useDevice() const appStore = useAppStore() +const tenantStore = useTenantStore() + +const { isDesktop } = useDevice() const title = computed(() => appStore.getTitle()) const logo = computed(() => appStore.getLogo()) @@ -119,6 +123,21 @@ const onOauth = async (source: string) => { const { data } = await socialAuth(source) window.location.href = data.authorizeUrl } + +// 查询租户状态和租户编码 +const onGetTenant = async () => { + const { data } = await getTenantStatus() + tenantStore.setTenantEnable(data) + // 开启租户 根据地址(域名)查询租户code + if (data) { + const domain = window.location.hostname + const { data: tenantId } = await getTenantIdByDomain(domain) + tenantStore.setTenantId(tenantId) + } +} +onMounted(() => { + onGetTenant() +}) diff --git a/src/views/tenant/management/AdminUserPwdUpdateModal.vue b/src/views/tenant/management/AdminUserPwdUpdateModal.vue new file mode 100644 index 0000000..6ba2526 --- /dev/null +++ b/src/views/tenant/management/AdminUserPwdUpdateModal.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/views/tenant/management/DetailDrawer.vue b/src/views/tenant/management/DetailDrawer.vue new file mode 100644 index 0000000..070dbdf --- /dev/null +++ b/src/views/tenant/management/DetailDrawer.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/views/tenant/management/index.vue b/src/views/tenant/management/index.vue new file mode 100644 index 0000000..3d2e0ad --- /dev/null +++ b/src/views/tenant/management/index.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/src/views/tenant/package/AddModal.vue b/src/views/tenant/package/AddModal.vue new file mode 100644 index 0000000..ec223e8 --- /dev/null +++ b/src/views/tenant/package/AddModal.vue @@ -0,0 +1,170 @@ + + + + + diff --git a/src/views/tenant/package/DetailDrawer.vue b/src/views/tenant/package/DetailDrawer.vue new file mode 100644 index 0000000..2bc9d88 --- /dev/null +++ b/src/views/tenant/package/DetailDrawer.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/views/tenant/package/index.vue b/src/views/tenant/package/index.vue new file mode 100644 index 0000000..5d559e8 --- /dev/null +++ b/src/views/tenant/package/index.vue @@ -0,0 +1,141 @@ + + + + +