Merge remote-tracking branch 'origin/developer' into developer
This commit is contained in:
7
.env
7
.env
@@ -16,9 +16,14 @@ VITE_API_URL = /api
|
|||||||
# ADMIN 服务地址
|
# ADMIN 服务地址
|
||||||
VITE_ADMIN_PROXY_PATH = http://scj-v3.zhxy.link/
|
VITE_ADMIN_PROXY_PATH = http://scj-v3.zhxy.link/
|
||||||
|
|
||||||
# 前端加密密钥
|
# 前端加密密钥(AES,未启用 SM2 时使用)
|
||||||
VITE_PWD_ENC_KEY='pigxpigxpigxpigx'
|
VITE_PWD_ENC_KEY='pigxpigxpigxpigx'
|
||||||
|
|
||||||
|
# 登录使用 SM2 加密密码:设为 true 时密码用 SM2 公钥加密,需后端配置 security.sm2-private-key
|
||||||
|
VITE_LOGIN_SM2_ENABLE=true
|
||||||
|
# SM2 公钥(十六进制,04 开头 130 字符),与后端私钥成对
|
||||||
|
VITE_SM2_PUBLIC_KEY=04de67d5234bb13b5bbe524a71d1e48ac302014be3c3c6ba74b33bb5a125717b0e8873ad3971a6082138e0556a7ec334d460458c6c46753b65acc93ec1b99bb8fd
|
||||||
|
|
||||||
# OAUTH2 密码模式客户端信息
|
# OAUTH2 密码模式客户端信息
|
||||||
VITE_OAUTH2_PASSWORD_CLIENT='pig:pig'
|
VITE_OAUTH2_PASSWORD_CLIENT='pig:pig'
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import request from '/@/utils/request';
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
export function fetchList(query?: Object) {
|
export function fetchList(query?: Object) {
|
||||||
return request({
|
// return request({
|
||||||
url: '/admin/audit/page',
|
// url: '/admin/audit/page',
|
||||||
method: 'get',
|
// method: 'get',
|
||||||
params: query,
|
// params: query,
|
||||||
});
|
// });
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getObj(id?: string) {
|
export function getObj(id?: string) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import request from '/@/utils/request';
|
|||||||
import { Session } from '/@/utils/storage';
|
import { Session } from '/@/utils/storage';
|
||||||
import { validateNull } from '/@/utils/validate';
|
import { validateNull } from '/@/utils/validate';
|
||||||
import { useUserInfo } from '/@/stores/userInfo';
|
import { useUserInfo } from '/@/stores/userInfo';
|
||||||
import other from '/@/utils/other';
|
import other, { sm2Encrypt } from '/@/utils/other';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://www.ietf.org/rfc/rfc6749.txt
|
* https://www.ietf.org/rfc/rfc6749.txt
|
||||||
@@ -10,6 +10,11 @@ import other from '/@/utils/other';
|
|||||||
*/
|
*/
|
||||||
const FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded';
|
const FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded';
|
||||||
|
|
||||||
|
/** 登录是否使用 SM2 加密密码(需后端配置 SM2 私钥并支持 Enc-Flag: sm2) */
|
||||||
|
const LOGIN_SM2_ENABLE = import.meta.env.VITE_LOGIN_SM2_ENABLE === 'true';
|
||||||
|
/** SM2 公钥(十六进制,与后端私钥成对),用于前端加密密码 */
|
||||||
|
const SM2_PUBLIC_KEY = import.meta.env.VITE_SM2_PUBLIC_KEY || '';
|
||||||
|
|
||||||
// 登录方式
|
// 登录方式
|
||||||
export enum LoginTypeEnum {
|
export enum LoginTypeEnum {
|
||||||
PASSWORD,
|
PASSWORD,
|
||||||
@@ -47,8 +52,15 @@ export enum SocialLoginEnum {
|
|||||||
export const login = (data: any) => {
|
export const login = (data: any) => {
|
||||||
const basicAuth = 'Basic ' + window.btoa(import.meta.env.VITE_OAUTH2_PASSWORD_CLIENT);
|
const basicAuth = 'Basic ' + window.btoa(import.meta.env.VITE_OAUTH2_PASSWORD_CLIENT);
|
||||||
Session.set('basicAuth', basicAuth);
|
Session.set('basicAuth', basicAuth);
|
||||||
// 密码加密
|
let encPassword: string;
|
||||||
const encPassword = other.encryption(data.password, import.meta.env.VITE_PWD_ENC_KEY);
|
let encFlag: string;
|
||||||
|
if (LOGIN_SM2_ENABLE && SM2_PUBLIC_KEY) {
|
||||||
|
encPassword = sm2Encrypt(data.password, SM2_PUBLIC_KEY);
|
||||||
|
encFlag = 'sm2';
|
||||||
|
} else {
|
||||||
|
encPassword = other.encryption(data.password, import.meta.env.VITE_PWD_ENC_KEY);
|
||||||
|
encFlag = 'false';
|
||||||
|
}
|
||||||
const { username, randomStr, code, grant_type, scope } = data;
|
const { username, randomStr, code, grant_type, scope } = data;
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/oauth2/token',
|
url: '/auth/oauth2/token',
|
||||||
@@ -59,7 +71,7 @@ export const login = (data: any) => {
|
|||||||
skipToken: true,
|
skipToken: true,
|
||||||
Authorization: basicAuth,
|
Authorization: basicAuth,
|
||||||
'Content-Type': FORM_CONTENT_TYPE,
|
'Content-Type': FORM_CONTENT_TYPE,
|
||||||
"Enc-Flag": "false",
|
'Enc-Flag': encFlag,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
const HEATH='heath'
|
const HEATH='heath'
|
||||||
const TEACHER_CATE='teacher_cate'
|
const TEACHER_CATE='professional_teacher_cate'
|
||||||
const EXAM_STATUS="EXAM_STATUS"
|
const EXAM_STATUS="EXAM_STATUS"
|
||||||
|
|
||||||
//技能提升
|
//技能提升
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import pinia from '/@/stores/index';
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useKeepALiveNames } from '/@/stores/keepAliveNames';
|
import { useKeepALiveNames } from '/@/stores/keepAliveNames';
|
||||||
import { useRoutesList } from '/@/stores/routesList';
|
import { useRoutesList } from '/@/stores/routesList';
|
||||||
|
import { useUserInfo } from '/@/stores/userInfo';
|
||||||
import { Session } from '/@/utils/storage';
|
import { Session } from '/@/utils/storage';
|
||||||
import { staticRoutes, notFoundAndNoPower } from '/@/router/route';
|
import { staticRoutes, notFoundAndNoPower } from '/@/router/route';
|
||||||
import { initBackEndControlRoutes } from '/@/router/backEnd';
|
import { initBackEndControlRoutes } from '/@/router/backEnd';
|
||||||
@@ -91,6 +92,18 @@ export function formatTwoStageRoutes(arr: any) {
|
|||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
NProgress.configure({ showSpinner: false });
|
NProgress.configure({ showSpinner: false });
|
||||||
if (to.name) NProgress.start();
|
if (to.name) NProgress.start();
|
||||||
|
|
||||||
|
// 全局监听 URL 参数 token:若存在则写入缓存(与登录成功同一方法),不在此处 redirect,避免先跳转再 init 导致 tagsView 首次丢失
|
||||||
|
const urlToken = to.query?.token as string | undefined;
|
||||||
|
if (urlToken) {
|
||||||
|
useUserInfo().setTokenCache(urlToken, to.query?.refresh_token as string | undefined);
|
||||||
|
}
|
||||||
|
// 若上面刚写了 token,后续用去掉 token 的 query 做一次 replace(在 init 之后统一做,保证只一次导航、tagsView 能正确加 tag)
|
||||||
|
const stripTokenQuery =
|
||||||
|
urlToken && to.query
|
||||||
|
? Object.fromEntries(Object.entries(to.query).filter(([k]) => k !== 'token' && k !== 'refresh_token'))
|
||||||
|
: null;
|
||||||
|
|
||||||
const token = Session.getToken();
|
const token = Session.getToken();
|
||||||
if (to.meta.isAuth !== undefined && !to.meta.isAuth) {
|
if (to.meta.isAuth !== undefined && !to.meta.isAuth) {
|
||||||
next();
|
next();
|
||||||
@@ -117,9 +130,16 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
if (routesList.value.length === 0) {
|
if (routesList.value.length === 0) {
|
||||||
// 后端控制路由:路由数据初始化,防止刷新时丢失
|
// 后端控制路由:路由数据初始化,防止刷新时丢失
|
||||||
await initBackEndControlRoutes();
|
await initBackEndControlRoutes();
|
||||||
next({ path: to.path, query: to.query });
|
// 只传 path/params/query,让路由器用刚添加的动态路由重新解析,避免沿用进入守卫时解析到的 404
|
||||||
|
const query = stripTokenQuery ?? to.query;
|
||||||
|
next({ path: to.path, params: to.params, query, replace: true });
|
||||||
} else {
|
} else {
|
||||||
next();
|
// 已有路由列表,若本次是带 token 的 URL,做一次 replace 去掉地址栏 token
|
||||||
|
if (stripTokenQuery) {
|
||||||
|
next({ path: to.path, params: to.params, query: stripTokenQuery, replace: true });
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,18 @@ export const useUserInfo = defineStore('userInfo', {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
/**
|
||||||
|
* 统一写入 token 到缓存(登录成功、URL 参数 token 等共用)
|
||||||
|
* @param token 访问令牌
|
||||||
|
* @param refreshToken 刷新令牌,可选
|
||||||
|
*/
|
||||||
|
setTokenCache(token: string, refreshToken?: string) {
|
||||||
|
Session.set('token', token);
|
||||||
|
if (refreshToken != null && refreshToken !== '') {
|
||||||
|
Session.set('refresh_token', refreshToken);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录方法
|
* 登录方法
|
||||||
* @function login
|
* @function login
|
||||||
@@ -30,14 +42,11 @@ export const useUserInfo = defineStore('userInfo', {
|
|||||||
async login(data:any) {
|
async login(data:any) {
|
||||||
data.grant_type = 'password';
|
data.grant_type = 'password';
|
||||||
data.scope = 'server';
|
data.scope = 'server';
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
login(data)
|
login(data)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
debugger
|
debugger
|
||||||
// 存储token 信息
|
this.setTokenCache(res.access_token, res.refresh_token);
|
||||||
Session.set('token', res.access_token);
|
|
||||||
Session.set('refresh_token', res.refresh_token);
|
|
||||||
Local.remove('roleCode');
|
Local.remove('roleCode');
|
||||||
Local.remove('roleName');
|
Local.remove('roleName');
|
||||||
Local.remove('roleId');
|
Local.remove('roleId');
|
||||||
@@ -61,9 +70,7 @@ export const useUserInfo = defineStore('userInfo', {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
loginByMobile(data.mobile, data.code)
|
loginByMobile(data.mobile, data.code)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// 存储token 信息
|
this.setTokenCache(res.access_token, res.refresh_token);
|
||||||
Session.set('token', res.access_token);
|
|
||||||
Session.set('refresh_token', res.refresh_token);
|
|
||||||
resolve(res);
|
resolve(res);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -85,9 +92,7 @@ export const useUserInfo = defineStore('userInfo', {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
loginBySocial(state, code)
|
loginBySocial(state, code)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// 存储token 信息
|
this.setTokenCache(res.access_token, res.refresh_token);
|
||||||
Session.set('token', res.access_token);
|
|
||||||
Session.set('refresh_token', res.refresh_token);
|
|
||||||
resolve(res);
|
resolve(res);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -108,9 +113,7 @@ export const useUserInfo = defineStore('userInfo', {
|
|||||||
const refreshToken = Session.get('refresh_token');
|
const refreshToken = Session.get('refresh_token');
|
||||||
refreshTokenApi(refreshToken)
|
refreshTokenApi(refreshToken)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// 存储token 信息
|
this.setTokenCache(res.access_token, res.refresh_token);
|
||||||
Session.set('token', res.access_token);
|
|
||||||
Session.set('refresh_token', res.refresh_token);
|
|
||||||
resolve(res);
|
resolve(res);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {verifyUrl} from '/@/utils/toolsValidate';
|
|||||||
import request from '/@/utils/request';
|
import request from '/@/utils/request';
|
||||||
import {useMessage} from '/@/hooks/message';
|
import {useMessage} from '/@/hooks/message';
|
||||||
import * as CryptoJS from 'crypto-js';
|
import * as CryptoJS from 'crypto-js';
|
||||||
import {sm4} from 'sm-crypto'
|
import { sm4, sm2 } from 'sm-crypto'
|
||||||
import {validateNull} from './validate';
|
import {validateNull} from './validate';
|
||||||
|
|
||||||
|
|
||||||
@@ -240,6 +240,17 @@ export function sm4Decryption(src: string, keyWord: string) {
|
|||||||
return sm4.decrypt(src, keyWord);
|
return sm4.decrypt(src, keyWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SM2 加密(登录密码等,与后端 SM2 私钥解密配套)
|
||||||
|
* @param msg 明文
|
||||||
|
* @param publicKey 后端提供的 SM2 公钥(十六进制,04 开头 130 字符或 128 字符压缩格式)
|
||||||
|
* @returns 十六进制密文,格式 C1C3C2
|
||||||
|
*/
|
||||||
|
export function sm2Encrypt(msg: string, publicKey: string): string {
|
||||||
|
if (!msg || !publicKey) return msg;
|
||||||
|
return sm2.doEncrypt(msg, publicKey, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64 加密
|
* Base64 加密
|
||||||
* @param {*} src 明文
|
* @param {*} src 明文
|
||||||
@@ -370,6 +381,9 @@ const other = {
|
|||||||
decryption: (src: string, keyWord: string) => {
|
decryption: (src: string, keyWord: string) => {
|
||||||
return decryption(src, keyWord);
|
return decryption(src, keyWord);
|
||||||
},
|
},
|
||||||
|
sm2Encrypt: (msg: string, publicKey: string) => {
|
||||||
|
return sm2Encrypt(msg, publicKey);
|
||||||
|
},
|
||||||
base64Encrypt: (data: any) => {
|
base64Encrypt: (data: any) => {
|
||||||
return base64Encrypt(data);
|
return base64Encrypt(data);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -145,23 +145,23 @@ const changeSwitch = async (id: string) => {
|
|||||||
|
|
||||||
const initscheduleList = () => {
|
const initscheduleList = () => {
|
||||||
// 初始化日程列表
|
// 初始化日程列表
|
||||||
list({
|
// list({
|
||||||
startDate: startDateRef.value,
|
// startDate: startDateRef.value,
|
||||||
endDate: endDateRef.value,
|
// endDate: endDateRef.value,
|
||||||
}).then((res) => {
|
// }).then((res) => {
|
||||||
// 获取返回结果的数据并转换为合适的格式
|
// // 获取返回结果的数据并转换为合适的格式
|
||||||
reminders.value = res.data.map((item: any) => {
|
// reminders.value = res.data.map((item: any) => {
|
||||||
return {
|
// return {
|
||||||
key: item.id,
|
// key: item.id,
|
||||||
highlight: {
|
// highlight: {
|
||||||
color: 'primary',
|
// color: 'primary',
|
||||||
fillMode: 'outline',
|
// fillMode: 'outline',
|
||||||
},
|
// },
|
||||||
dates: item.scheduleDate,
|
// dates: item.scheduleDate,
|
||||||
customData: item,
|
// customData: item,
|
||||||
};
|
// };
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 过滤日历中选中的单元格是否有日程
|
// 过滤日历中选中的单元格是否有日程
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ const state = reactive({
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await queryTaskData();
|
// const { data } = await queryTaskData();
|
||||||
state.pendingNum = Number.parseInt(data?.pendingNum || 0);
|
// state.pendingNum = Number.parseInt(data?.pendingNum || 0);
|
||||||
state.copyNum = Number.parseInt(data?.copyNum || 0);
|
// state.copyNum = Number.parseInt(data?.copyNum || 0);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 避免没有启动 flow模块 vue 组件渲染 warning
|
// 避免没有启动 flow模块 vue 组件渲染 warning
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2248,10 +2248,10 @@
|
|||||||
fetchSecondTree()
|
fetchSecondTree()
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
// 批量获取字典数据 religious_belief宗教信仰 health健康状况 teacher_cate授课类型 teacher_classify职位类别 yes_no_type是否类型
|
// 批量获取字典数据 religious_belief宗教信仰 health健康状况 teacher_cate授课类型 teacher_classify职位类别 yes_no_type是否类型
|
||||||
getDictsByTypes(['religious_belief', 'heath', 'teacher_cate', 'teacher_classify', 'yes_no_type']).then((response: any) => {
|
getDictsByTypes(['religious_belief', 'heath', 'professional_teacher_cate', 'teacher_classify', 'yes_no_type']).then((response: any) => {
|
||||||
religiousBeliefDic.value = response.data.religious_belief;
|
religiousBeliefDic.value = response.data.religious_belief;
|
||||||
healthList.value = response.data.heath;
|
healthList.value = response.data.heath;
|
||||||
teacherCateList.value = response.data.teacher_cate;
|
teacherCateList.value = response.data.professional_teacher_cate;
|
||||||
teacherClassifyData.value = response.data.teacher_classify || [];
|
teacherClassifyData.value = response.data.teacher_classify || [];
|
||||||
inoutFlagOptions.value = response.data.yes_no_type || [];
|
inoutFlagOptions.value = response.data.yes_no_type || [];
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1099,10 +1099,10 @@ const init = (id: string | null, typeParam: number, groupId?: string) => {
|
|||||||
areaHomeAreaList.value = []
|
areaHomeAreaList.value = []
|
||||||
|
|
||||||
// 批量获取数据字典(新增和编辑都需要) 文化程度 学费 代办费 户口性质 学校归属地
|
// 批量获取数据字典(新增和编辑都需要) 文化程度 学费 代办费 户口性质 学校归属地
|
||||||
getDictsByTypes(['id_type','finance_student_source', 'agency_fee', 'tuition_fee','house_hold_properties','recruit_school_form']).then((res: any) => {
|
getDictsByTypes(['id_type','finance_student_source', 'recruit_agency_fee', 'tuition_fee','house_hold_properties','recruit_school_form']).then((res: any) => {
|
||||||
idCardTypeList.value = res.data.id_type || []
|
idCardTypeList.value = res.data.id_type || []
|
||||||
eduList.value = res.data.finance_student_source || []
|
eduList.value = res.data.finance_student_source || []
|
||||||
agencyFeeList.value = res.data.agency_fee || []
|
agencyFeeList.value = res.data.recruit_agency_fee || []
|
||||||
tuitionFeeList.value = res.data.tuition_fee || []
|
tuitionFeeList.value = res.data.tuition_fee || []
|
||||||
residenceTypeList.value = res.data.house_hold_properties || []
|
residenceTypeList.value = res.data.house_hold_properties || []
|
||||||
schoolFromList.value = res.data.recruit_school_form || []
|
schoolFromList.value = res.data.recruit_school_form || []
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ const init = () => {
|
|||||||
canSubmit.value = true
|
canSubmit.value = true
|
||||||
circleShow.value = true
|
circleShow.value = true
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
getDicts("dorm_jw").then((data: any) => {
|
getDicts("recruit_dorm_jw").then((data: any) => {
|
||||||
const arr = data.data
|
const arr = data.data
|
||||||
arr.forEach((e: any) => {
|
arr.forEach((e: any) => {
|
||||||
if (e.label == 'bj') {
|
if (e.label == 'bj') {
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ const init = (id: string | null) => {
|
|||||||
dataFormRef.value?.resetFields()
|
dataFormRef.value?.resetFields()
|
||||||
if (dataForm.id) {
|
if (dataForm.id) {
|
||||||
// 获取数据字典代办费
|
// 获取数据字典代办费
|
||||||
getDicts('agency_fee').then((res: any) => {
|
getDicts('recruit_agency_fee').then((res: any) => {
|
||||||
agencyFeeList.value = res.data
|
agencyFeeList.value = res.data
|
||||||
getObj(dataForm.id).then((response: any) => {
|
getObj(dataForm.id).then((response: any) => {
|
||||||
Object.assign(dataForm, response.data)
|
Object.assign(dataForm, response.data)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ const init = (row: any) => {
|
|||||||
form.homeLng = row.homeLng || row.homeLongitude || 0
|
form.homeLng = row.homeLng || row.homeLongitude || 0
|
||||||
form.homeLat = row.homeLat || row.homeLatitude || 0
|
form.homeLat = row.homeLat || row.homeLatitude || 0
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
getDicts("dorm_jw").then((data: any) => {
|
getDicts("recruit_dorm_jw").then((data: any) => {
|
||||||
const arr = data.data
|
const arr = data.data
|
||||||
arr.forEach((e: any) => {
|
arr.forEach((e: any) => {
|
||||||
if (e.label == 'bj') {
|
if (e.label == 'bj') {
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
|
|||||||
port: env.VITE_PORT as unknown as number, // 服务器端口号
|
port: env.VITE_PORT as unknown as number, // 服务器端口号
|
||||||
open: env.VITE_OPEN === 'true', // 是否自动打开浏览器
|
open: env.VITE_OPEN === 'true', // 是否自动打开浏览器
|
||||||
hmr: true, // 启用热更新
|
hmr: true, // 启用热更新
|
||||||
|
allowedHosts: ['mycomputer.top'],
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: env.VITE_ADMIN_PROXY_PATH, // 目标服务器地址
|
target: env.VITE_ADMIN_PROXY_PATH, // 目标服务器地址
|
||||||
|
|||||||
Reference in New Issue
Block a user