refactor:优化 VITE_APP_TENANT_ENABLE、VITE_APP_CAPTCHA_ENABLE 变量的加载,不使用 useAppConfig 处理

pull/78/MERGE
YunaiV 2025-04-22 21:18:10 +08:00
parent e9f2b5701c
commit f202e1c69c
13 changed files with 93 additions and 88 deletions

View File

@ -4,7 +4,7 @@ VITE_PORT=5666
VITE_BASE=/ VITE_BASE=/
# 请求路径 # 请求路径
VITE_BASE_URL='http://127.0.0.1:48080' VITE_BASE_URL=http://127.0.0.1:48080
# 接口地址 # 接口地址
VITE_GLOB_API_URL=/admin-api VITE_GLOB_API_URL=/admin-api
# 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务 # 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务

View File

@ -1,9 +1,9 @@
VITE_BASE=/ VITE_BASE=/
# 请求路径 # 请求路径
VITE_BASE_URL='http://127.0.0.1:48080' VITE_BASE_URL=http://127.0.0.1:48080
# 接口地址 # 接口地址
VITE_GLOB_API_URL=/admin-api VITE_GLOB_API_URL=http://127.0.0.1:48080/admin-api
# 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务 # 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务
VITE_UPLOAD_TYPE=server VITE_UPLOAD_TYPE=server

View File

@ -3,7 +3,7 @@
*/ */
import type { RequestClientOptions } from '@vben/request'; import type { RequestClientOptions } from '@vben/request';
import { useAppConfig } from '@vben/hooks'; import { isTenantEnable, useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences'; import { preferences } from '@vben/preferences';
import { import {
authenticateResponseInterceptor, authenticateResponseInterceptor,
@ -19,7 +19,8 @@ import { useAuthStore } from '#/store';
import { refreshTokenApi } from './core'; import { refreshTokenApi } from './core';
const { apiURL, tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD); const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
const tenantEnable = isTenantEnable();
function createRequestClient(baseURL: string, options?: RequestClientOptions) { function createRequestClient(baseURL: string, options?: RequestClientOptions) {
const client = new RequestClient({ const client = new RequestClient({

View File

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
// TODO @ src import { isDocAlertEnable } from '@vben/hooks';
import { computed } from 'vue';
import { Alert, Typography } from 'ant-design-vue'; import { Alert, Typography } from 'ant-design-vue';
export interface DocAlertProps { export interface DocAlertProps {
@ -20,16 +20,11 @@ const props = defineProps<DocAlertProps>();
const goToUrl = () => { const goToUrl = () => {
window.open(props.url); window.open(props.url);
}; };
/** 是否开启 */
const isEnabled = computed(() => {
return import.meta.env.VITE_APP_DOCALERT_ENABLE !== 'false';
});
</script> </script>
<template> <template>
<Alert <Alert
v-if="isEnabled" v-if="isDocAlertEnable()"
type="info" type="info"
show-icon show-icon
class="mb-2 rounded" class="mb-2 rounded"

View File

@ -1,11 +1,28 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import type { AxiosProgressEvent, InfraFileApi } from '#/api/infra/file'; import type { AxiosProgressEvent, InfraFileApi } from '#/api/infra/file';
import { computed, unref } from 'vue'; import { computed, unref } from 'vue';
import { useAppConfig } from '@vben/hooks';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import CryptoJS from 'crypto-js'
import CryptoJS from 'crypto-js';
import { createFile, getFilePresignedUrl, uploadFile } from '#/api/infra/file';
import { baseRequestClient } from '#/api/request'; import { baseRequestClient } from '#/api/request';
import { uploadFile, getFilePresignedUrl, createFile } from '#/api/infra/file';
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
/**
*
*/
enum UPLOAD_TYPE {
// 客户端直接上传只支持S3服务
CLIENT = 'client',
// 客户端发送到后端上传
SERVER = 'server',
}
export function useUploadType({ export function useUploadType({
acceptRef, acceptRef,
@ -66,48 +83,52 @@ export function useUploadType({
// TODO @芋艿:目前保持和 admin-vue3 一致,后续可能重构 // TODO @芋艿:目前保持和 admin-vue3 一致,后续可能重构
export const useUpload = () => { export const useUpload = () => {
// 后端上传地址 // 后端上传地址
const uploadUrl = getUploadUrl() const uploadUrl = getUploadUrl();
// 是否使用前端直连上传 // 是否使用前端直连上传
const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE const isClientUpload =
UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE;
// 重写ElUpload上传方法 // 重写ElUpload上传方法
const httpRequest = async (file: File, onUploadProgress?: AxiosProgressEvent) => { const httpRequest = async (
file: File,
onUploadProgress?: AxiosProgressEvent,
) => {
// 模式一:前端上传 // 模式一:前端上传
if (isClientUpload) { if (isClientUpload) {
// 1.1 生成文件名称 // 1.1 生成文件名称
const fileName = await generateFileName(file) const fileName = await generateFileName(file);
// 1.2 获取文件预签名地址 // 1.2 获取文件预签名地址
const presignedInfo = await getFilePresignedUrl(fileName) const presignedInfo = await getFilePresignedUrl(fileName);
// 1.3 上传文件 // 1.3 上传文件
return baseRequestClient return baseRequestClient
.put(presignedInfo.uploadUrl, file, { .put(presignedInfo.uploadUrl, file, {
headers: { headers: {
'Content-Type': file.type 'Content-Type': file.type,
} },
}) })
.then(() => { .then(() => {
// 1.4. 记录文件信息到后端(异步) // 1.4. 记录文件信息到后端(异步)
createFile0(presignedInfo, fileName, file) createFile0(presignedInfo, fileName, file);
// 通知成功,数据格式保持与后端上传的返回结果一致 // 通知成功,数据格式保持与后端上传的返回结果一致
return { data: presignedInfo.url } return { data: presignedInfo.url };
}) });
} else { } else {
// 模式二:后端上传 // 模式二:后端上传
return uploadFile({ file }, onUploadProgress); return uploadFile({ file }, onUploadProgress);
} }
} };
return { return {
uploadUrl, uploadUrl,
httpRequest httpRequest,
} };
} };
/** /**
* URL * URL
*/ */
export const getUploadUrl = (): string => { export const getUploadUrl = (): string => {
return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_GLOB_API_URL + '/infra/file/upload' return `${apiURL}/infra/file/upload`;
} };
/** /**
* *
@ -116,17 +137,21 @@ export const getUploadUrl = (): string => {
* @param name * @param name
* @param file * @param file
*/ */
function createFile0(vo: InfraFileApi.FilePresignedUrlRespVO, name: string, file: File) { function createFile0(
vo: InfraFileApi.FilePresignedUrlRespVO,
name: string,
file: File,
) {
const fileVO = { const fileVO = {
configId: vo.configId, configId: vo.configId,
url: vo.url, url: vo.url,
path: name, path: name,
name: file.name, name: file.name,
type: file.type, type: file.type,
size: file.size size: file.size,
} };
createFile(fileVO) createFile(fileVO);
return fileVO return fileVO;
} }
/** /**
@ -136,21 +161,11 @@ function createFile0(vo: InfraFileApi.FilePresignedUrlRespVO, name: string, file
*/ */
async function generateFileName(file: File) { async function generateFileName(file: File) {
// 读取文件内容 // 读取文件内容
const data = await file.arrayBuffer() const data = await file.arrayBuffer();
const wordArray = CryptoJS.lib.WordArray.create(data) const wordArray = CryptoJS.lib.WordArray.create(data);
// 计算SHA256 // 计算SHA256
const sha256 = CryptoJS.SHA256(wordArray).toString() const sha256 = CryptoJS.SHA256(wordArray).toString();
// 拼接后缀 // 拼接后缀
const ext = file.name.substring(file.name.lastIndexOf('.')) const ext = file.name.slice(Math.max(0, file.name.lastIndexOf('.')));
return `${sha256}${ext}` return `${sha256}${ext}`;
}
/**
*
*/
enum UPLOAD_TYPE {
// 客户端直接上传只支持S3服务
CLIENT = 'client',
// 客户端发送到后端上传
SERVER = 'server'
} }

View File

@ -7,7 +7,7 @@ import type { AuthApi } from '#/api';
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { AuthenticationCodeLogin, z } from '@vben/common-ui'; import { AuthenticationCodeLogin, z } from '@vben/common-ui';
import { useAppConfig } from '@vben/hooks'; import { isTenantEnable } from '@vben/hooks';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
@ -19,10 +19,9 @@ import { useAuthStore } from '#/store';
defineOptions({ name: 'CodeLogin' }); defineOptions({ name: 'CodeLogin' });
const { tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
const authStore = useAuthStore(); const authStore = useAuthStore();
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const tenantEnable = isTenantEnable();
const loading = ref(false); const loading = ref(false);
const CODE_LENGTH = 4; const CODE_LENGTH = 4;

View File

@ -8,7 +8,7 @@ import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { AuthenticationForgetPassword, z } from '@vben/common-ui'; import { AuthenticationForgetPassword, z } from '@vben/common-ui';
import { useAppConfig } from '@vben/hooks'; import { isTenantEnable } from '@vben/hooks';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
@ -19,9 +19,9 @@ import { getTenantByWebsite, getTenantSimpleList } from '#/api/core/auth';
defineOptions({ name: 'ForgetPassword' }); defineOptions({ name: 'ForgetPassword' });
const { tenantEnable } = useAppConfig(import.meta.env, import.meta.env.PROD);
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const router = useRouter(); const router = useRouter();
const tenantEnable = isTenantEnable();
const loading = ref(false); const loading = ref(false);
const CODE_LENGTH = 4; const CODE_LENGTH = 4;

View File

@ -7,7 +7,7 @@ import { computed, onMounted, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { AuthenticationLogin, Verification, z } from '@vben/common-ui'; import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
import { useAppConfig } from '@vben/hooks'; import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
@ -22,14 +22,11 @@ import { useAuthStore } from '#/store';
defineOptions({ name: 'Login' }); defineOptions({ name: 'Login' });
const { tenantEnable, captchaEnable } = useAppConfig(
import.meta.env,
import.meta.env.PROD,
);
const { query } = useRoute(); const { query } = useRoute();
const authStore = useAuthStore(); const authStore = useAuthStore();
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const tenantEnable = isTenantEnable();
const captchaEnable = isCaptchaEnable();
const loginRef = ref(); const loginRef = ref();
const verifyRef = ref(); const verifyRef = ref();
@ -46,7 +43,6 @@ const fetchTenantList = async () => {
// //
const websiteTenantPromise = getTenantByWebsite(window.location.hostname); const websiteTenantPromise = getTenantByWebsite(window.location.hostname);
tenantList.value = await getTenantSimpleList(); tenantList.value = await getTenantSimpleList();
console.error('tenantList', tenantList.value);
// > store > // > store >
let tenantId: null | number = null; let tenantId: null | number = null;

View File

@ -6,7 +6,7 @@ import type { AuthApi } from '#/api/core/auth';
import { computed, h, onMounted, ref } from 'vue'; import { computed, h, onMounted, ref } from 'vue';
import { AuthenticationRegister, Verification, z } from '@vben/common-ui'; import { AuthenticationRegister, Verification, z } from '@vben/common-ui';
import { useAppConfig } from '@vben/hooks'; import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
@ -20,16 +20,15 @@ import { useAuthStore } from '#/store';
defineOptions({ name: 'Register' }); defineOptions({ name: 'Register' });
const { tenantEnable, captchaEnable } = useAppConfig(
import.meta.env,
import.meta.env.PROD,
);
const loading = ref(false); const loading = ref(false);
const registerRef = ref();
const verifyRef = ref();
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const authStore = useAuthStore(); const authStore = useAuthStore();
const tenantEnable = isTenantEnable();
const captchaEnable = isCaptchaEnable();
const registerRef = ref();
const verifyRef = ref();
const captchaType = 'blockPuzzle'; // 'blockPuzzle' | 'clickWord' const captchaType = 'blockPuzzle'; // 'blockPuzzle' | 'clickWord'

View File

@ -7,7 +7,7 @@ import { computed, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { AuthenticationLogin, Verification, z } from '@vben/common-ui'; import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
import { useAppConfig } from '@vben/hooks'; import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
@ -21,15 +21,12 @@ import { useAuthStore } from '#/store';
defineOptions({ name: 'SocialLogin' }); defineOptions({ name: 'SocialLogin' });
const { tenantEnable, captchaEnable } = useAppConfig(
import.meta.env,
import.meta.env.PROD,
);
const authStore = useAuthStore(); const authStore = useAuthStore();
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const { query } = useRoute(); const { query } = useRoute();
const router = useRouter(); const router = useRouter();
const tenantEnable = isTenantEnable();
const captchaEnable = isCaptchaEnable();
const loginRef = ref(); const loginRef = ref();
const verifyRef = ref(); const verifyRef = ref();

View File

@ -7,7 +7,6 @@ import { ref, onMounted } from 'vue'
import { getConfigKey } from '#/api/infra/config' import { getConfigKey } from '#/api/infra/config'
const loading = ref(true) // const loading = ref(true) //
// TODO @VITE_BASE_URL
const src = ref(import.meta.env.VITE_BASE_URL + '/druid/index.html') const src = ref(import.meta.env.VITE_BASE_URL + '/druid/index.html')
/** 初始化 */ /** 初始化 */

View File

@ -15,13 +15,21 @@ export function useAppConfig(
? window._VBEN_ADMIN_PRO_APP_CONF_ ? window._VBEN_ADMIN_PRO_APP_CONF_
: (env as VbenAdminProAppConfigRaw); : (env as VbenAdminProAppConfigRaw);
const { VITE_APP_CAPTCHA_ENABLE, VITE_APP_TENANT_ENABLE, VITE_GLOB_API_URL } = const { VITE_GLOB_API_URL } = config;
config;
// TODO @芋艿:貌似 VITE_APP_CAPTCHA_ENABLE 读取的是字符串,所以这里暂时这么转换
return { return {
apiURL: VITE_GLOB_API_URL, apiURL: VITE_GLOB_API_URL,
captchaEnable: VITE_APP_CAPTCHA_ENABLE === 'true',
tenantEnable: VITE_APP_TENANT_ENABLE === 'true',
}; };
} }
export function isTenantEnable(): boolean {
return import.meta.env.VITE_APP_TENANT_ENABLE === 'true';
}
export function isCaptchaEnable(): boolean {
return import.meta.env.VITE_APP_CAPTCHA_ENABLE === 'true';
}
export function isDocAlertEnable(): boolean {
return import.meta.env.VITE_APP_DOCALERT_ENABLE !== 'false';
}

View File

@ -9,14 +9,10 @@ declare module 'vue-router' {
export interface VbenAdminProAppConfigRaw { export interface VbenAdminProAppConfigRaw {
VITE_GLOB_API_URL: string; VITE_GLOB_API_URL: string;
VITE_APP_TENANT_ENABLE: boolean;
VITE_APP_CAPTCHA_ENABLE: boolean;
} }
export interface ApplicationConfig { export interface ApplicationConfig {
apiURL: string; apiURL: string;
captchaEnable: boolean;
tenantEnable: boolean;
} }
declare global { declare global {