From 89c2b07ca9538192d4deb8b1990c8cdcc7f55a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=A3=E4=BA=9B=E8=8A=B1=E5=84=BF?= <1156921458@qq.com> Date: Fri, 25 Apr 2025 08:48:11 +0800 Subject: [PATCH] .. --- .../auth/controller/ClientAuthController.java | 16 + .../controller/ClientActivityController.java | 28 +- .../activity/vo/ClientActivitySignVO.java | 9 +- .../app/module/activity/models/ActUser.java | 2 +- .../commons/auth/service/ValidateService.java | 2 +- .../app/web/commons/proc/WkFailProcessor.java | 4 +- frontend/src/App.vue | 5 + frontend/src/pages.json | 10 +- frontend/src/pages/activity/detail/index.vue | 883 +++--------------- frontend/src/pages/activity/list/index.vue | 475 +++++----- .../activity/registration-form/index.vue | 47 +- .../src/pages/activity/scan-sign/index.vue | 516 ++++++++++ frontend/src/pages/index/index.vue | 2 +- frontend/src/pages/login/index.vue | 101 +- frontend/src/pages/profile/index.vue | 766 ++++----------- frontend/src/util/request.ts | 17 +- frontend/src/utils/request.js | 317 +++++++ frontend/src/utils/routerInterceptor.js | 98 ++ frontend/vite.config.js | 8 +- 19 files changed, 1702 insertions(+), 1604 deletions(-) create mode 100644 frontend/src/pages/activity/scan-sign/index.vue create mode 100644 frontend/src/utils/request.js create mode 100644 frontend/src/utils/routerInterceptor.js diff --git a/backend/src/main/java/com/budwk/app/client/auth/controller/ClientAuthController.java b/backend/src/main/java/com/budwk/app/client/auth/controller/ClientAuthController.java index cbefce9..84b363c 100644 --- a/backend/src/main/java/com/budwk/app/client/auth/controller/ClientAuthController.java +++ b/backend/src/main/java/com/budwk/app/client/auth/controller/ClientAuthController.java @@ -1,5 +1,6 @@ package com.budwk.app.client.auth.controller; +import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; import com.budwk.app.base.constant.RedisConstant; import com.budwk.app.base.exception.BaseException; @@ -72,6 +73,9 @@ public class ClientAuthController { } } + /** + * 发送短信验证码 + */ @At("/send-sms-code/?") @Ok("json") public Object sendSmsCode(String phone) { @@ -83,4 +87,16 @@ public class ClientAuthController { } } + /** + * 退出登录 + */ + @At("/logout") + @Ok("json") + @SaCheckLogin(type = StpClientUtil.TYPE) + public Result logout() { + StpClientUtil.STP.logout(); + return Result.success(); + } + + } diff --git a/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientActivityController.java b/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientActivityController.java index e0ee24d..35b76e1 100644 --- a/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientActivityController.java +++ b/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientActivityController.java @@ -5,6 +5,8 @@ import com.budwk.app.base.page.PageForm; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.result.Result; import com.budwk.app.client.module.activity.service.ClientActivityService; +import com.budwk.app.client.module.activity.vo.ClientActivitySignVO; +import com.budwk.app.module.activity.models.Activity; import com.budwk.app.web.commons.auth.satoken.StpClientUtil; import org.nutz.dao.Cnd; import org.nutz.dao.Sqls; @@ -14,6 +16,7 @@ import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.mvc.adaptor.JsonAdaptor; import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.GET; import org.nutz.mvc.annotation.Ok; @IocBean @@ -48,15 +51,24 @@ public class ClientActivityController { return Result.success(pagination); } - /** - * 报名 - * - * @param id - * @return - */ - public Result sign(String id) { - return Result.success(); + @At("/get/?") + @GET + @SaCheckLogin(type = StpClientUtil.TYPE) + public Result get(Long id) { + Activity activity = clientActivityService.fetch(id); + clientActivityService.fetchLinks(activity, "items"); + return Result.success(activity); } + /** + * 报名 + */ + @At("/sign") + @AdaptBy(type = JsonAdaptor.class) + @SaCheckLogin(type = StpClientUtil.TYPE) + public Result sign(ClientActivitySignVO signVO) { + return Result.success(); + } + } diff --git a/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientActivitySignVO.java b/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientActivitySignVO.java index bfab850..d7d82e8 100644 --- a/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientActivitySignVO.java +++ b/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientActivitySignVO.java @@ -1,15 +1,22 @@ package com.budwk.app.client.module.activity.vo; +import com.budwk.app.module.activity.models.ActUser; + import java.util.List; /** + * 报名 */ public class ClientActivitySignVO { + private String activityId; + private String unitName; private String contactName; private String contactPhone; - + + private List userList; + } diff --git a/backend/src/main/java/com/budwk/app/module/activity/models/ActUser.java b/backend/src/main/java/com/budwk/app/module/activity/models/ActUser.java index 9735b5c..0c958bc 100644 --- a/backend/src/main/java/com/budwk/app/module/activity/models/ActUser.java +++ b/backend/src/main/java/com/budwk/app/module/activity/models/ActUser.java @@ -53,7 +53,7 @@ public class ActUser extends BaseModel { @Column @Comment("联系方式") @ColDefine(type = ColType.VARCHAR, width = 30) - private String mobile; + private String phone; @Column @Comment("参加单位名称") diff --git a/backend/src/main/java/com/budwk/app/web/commons/auth/service/ValidateService.java b/backend/src/main/java/com/budwk/app/web/commons/auth/service/ValidateService.java index 402d462..763b2e9 100644 --- a/backend/src/main/java/com/budwk/app/web/commons/auth/service/ValidateService.java +++ b/backend/src/main/java/com/budwk/app/web/commons/auth/service/ValidateService.java @@ -48,7 +48,7 @@ public class ValidateService { String text = R.captchaNumber(6); String codeFromRedis = redisService.get(RedisConstant.UCENTER_SMSCODE + mobile + ":LOCK"); if (Strings.isNotBlank(codeFromRedis)) { - throw new BaseException("请1分钟之后再试"); +// throw new BaseException("请1分钟之后再试"); } ThreadUtil.execute(()->{ smsSendServer.sendMsg(mobile, "验证码为:"+text); diff --git a/backend/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java b/backend/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java index 4d98be5..2036b0e 100644 --- a/backend/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java +++ b/backend/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java @@ -7,6 +7,7 @@ import com.budwk.app.base.exception.BaseException; import com.budwk.app.base.result.Result; import com.budwk.app.base.result.ResultCode; import com.budwk.app.base.utils.WebUtil; +import com.budwk.app.web.commons.auth.satoken.StpClientUtil; import org.nutz.castor.FailToCastObjectException; import org.nutz.dao.DaoException; import org.nutz.ioc.IocException; @@ -66,7 +67,8 @@ public class WkFailProcessor extends ViewProcessor { new ForwardView(errorUri).render(ac.getRequest(), ac.getResponse(), null); } return; - } else if (e instanceof NotLoginException) { // 如果是未登录异常 + } else if (e instanceof NotLoginException) { + // 如果是未登录异常 if (WebUtil.isAjax(ac.getRequest())) { WebUtil.rendAjaxResp(ac.getRequest(), ac.getResponse(), Result.error(ResultCode.USER_NOT_LOGIN.getCode(), ResultCode.USER_NOT_LOGIN.getMsg())); } else { diff --git a/frontend/src/App.vue b/frontend/src/App.vue index db4068d..b7e2b88 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,7 +1,12 @@ @@ -1113,268 +712,4 @@ const navigateToDetail = (id) => { box-shadow: 0 2px 8px rgba(231, 76, 60, 0.3); } -/* 报名表单样式 */ -.registration-dialog { - width: 100%; - height: 100%; -} - -.registration-container { - background: white; - width: 100%; - height: 100%; - max-height: 100vh; - display: flex; - flex-direction: column; -} - -.registration-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 16px; - background-color: #e74c3c; - color: white; -} - -.registration-title { - font-size: 18px; - font-weight: 500; -} - -.registration-close { - width: 32px; - height: 32px; - display: flex; - justify-content: center; - align-items: center; - border-radius: 50%; - background-color: rgba(255, 255, 255, 0.2); - color: white; -} - -.registration-content { - flex: 1; - overflow-y: auto; -} - -.form-block { - padding: 20px 16px; - border-bottom: 10px solid #f5f5f5; -} - -.form-block-title { - font-size: 16px; - font-weight: 500; - margin-bottom: 16px; - color: #333; - display: flex; - align-items: center; -} - -.form-block-title :deep(i) { - margin-right: 8px; - color: #e74c3c; -} - -.form-field { - margin-bottom: 16px; -} - -.form-field:last-child { - margin-bottom: 0; -} - -/* 左右布局表单 */ -.form-field-horizontal { - display: flex; - align-items: center; - margin-bottom: 16px; -} - -.form-field-horizontal:last-child { - margin-bottom: 0; -} - -.field-label-horizontal { - width: 80px; - font-size: 14px; - color: #666; - font-weight: 500; - flex-shrink: 0; -} - -.field-content { - flex: 1; -} - -.field-label { - display: block; - font-size: 14px; - color: #666; - margin-bottom: 8px; - font-weight: 500; -} - -.field-input { - width: 100%; - height: 48px; - border: none; - border-bottom: 1px solid #ddd; - font-size: 15px; - color: #333; - background: transparent; - transition: border-color 0.2s; -} - -.field-input:focus { - border-color: #e74c3c; - outline: none; -} - -.field-input::placeholder { - color: #bbb; -} - -.form-row { - display: flex; - gap: 15px; -} - -.field-col { - flex: 1; -} - -.radio-buttons { - display: flex; - gap: 10px; -} - -.radio-button { - display: flex; - align-items: center; - border: 1px solid #ddd; - padding: 8px 12px; - border-radius: 6px; - flex: none; - min-width: 60px; -} - -.radio-button.active { - border-color: #e74c3c; - background-color: rgba(231, 76, 60, 0.05); -} - -.radio-button :deep(i) { - font-size: 18px; - margin-right: 8px; - color: #999; -} - -.radio-button.active :deep(i) { - color: #e74c3c; -} - -.participant-card { - background: white; - margin-bottom: 20px; - position: relative; - border-left: 3px solid #e74c3c; - padding-left: 12px; -} - -.participant-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 15px; -} - -.participant-title { - font-weight: 500; - color: #333; - font-size: 15px; - display: flex; - align-items: center; -} - -.participant-title text { - display: flex; - justify-content: center; - align-items: center; - width: 24px; - height: 24px; - background-color: #e74c3c; - color: white; - border-radius: 50%; - font-size: 14px; - margin-right: 8px; -} - -.remove-participant { - color: #999; - font-size: 14px; - display: flex; - align-items: center; - background: none; - border: none; -} - -.add-participant { - padding: 15px; - text-align: center; - color: #e74c3c; - font-weight: 500; - display: flex; - justify-content: center; - align-items: center; - border-top: 1px solid #f0f0f0; -} - -.add-participant :deep(i) { - margin-right: 8px; - font-size: 18px; -} - -.registration-footer { - padding: 16px; - background-color: white; - box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1); -} - -.required-mark { - color: #e74c3c; - margin-left: 3px; -} - -.agreement-checkbox { - display: flex; - align-items: center; - margin-bottom: 16px; - padding: 0 4px; -} - -.agreement-checkbox input[type="checkbox"] { - width: 18px; - height: 18px; - margin-right: 8px; - accent-color: #e74c3c; -} - -.agreement-checkbox label { - font-size: 14px; - color: #666; -} - -@media (min-width: 768px) { - .registration-container { - max-width: 500px; - max-height: 90vh; - border-radius: 12px; - } - - .registration-header { - border-radius: 12px 12px 0 0; - } -} diff --git a/frontend/src/pages/activity/list/index.vue b/frontend/src/pages/activity/list/index.vue index dc861a5..a0e5b69 100644 --- a/frontend/src/pages/activity/list/index.vue +++ b/frontend/src/pages/activity/list/index.vue @@ -1,212 +1,248 @@ - diff --git a/frontend/src/pages/activity/registration-form/index.vue b/frontend/src/pages/activity/registration-form/index.vue index 1fd686d..c4560bb 100644 --- a/frontend/src/pages/activity/registration-form/index.vue +++ b/frontend/src/pages/activity/registration-form/index.vue @@ -1,13 +1,13 @@ diff --git a/frontend/src/util/request.ts b/frontend/src/util/request.ts index 5658004..9ae95c5 100644 --- a/frontend/src/util/request.ts +++ b/frontend/src/util/request.ts @@ -23,6 +23,7 @@ export function useRequest() { const token = uni.getStorageSync('token') const headers = { 'Content-Type': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', ...(token ? { 'Authorization': `Bearer ${token}` } : {}), ...options.header } @@ -35,9 +36,21 @@ export function useRequest() { timeout: options.timeout || 10000, success: (res) => { if (res.statusCode >= 200 && res.statusCode < 300) { - resolve(res.data as T) + if(res.data.code === 0){ + resolve(res.data as T) + }else if(res.data.code === 600098){ + // 未登录 + uni.removeStorageSync('token') + uni.reLaunch({ + url: '/pages/login/index' + }) + }else { + const err = new Error(res.data?.msg || '请求失败') + error.value = err + reject(err) + } } else { - const err = new Error(res.data?.message || '请求失败') + const err = new Error(res.data?.msg || '请求失败') error.value = err reject(err) } diff --git a/frontend/src/utils/request.js b/frontend/src/utils/request.js new file mode 100644 index 0000000..477a02c --- /dev/null +++ b/frontend/src/utils/request.js @@ -0,0 +1,317 @@ +import { reactive } from "vue"; + +/** + * 全局请求状态管理 + */ +export const requestState = reactive({ + // 所有正在加载的请求ID映射表 + loadingRequests: {}, + + // 是否有任何请求正在加载中 + get isLoading() { + return Object.keys(this.loadingRequests).length > 0; + }, + + // 当前正在加载的请求数量 + get loadingCount() { + return Object.keys(this.loadingRequests).length; + }, + + // 所有错误请求ID映射表 + errorRequests: {}, + + // 是否有任何请求出错 + get hasError() { + return Object.keys(this.errorRequests).length > 0; + }, + + // 当前错误的请求数量 + get errorCount() { + return Object.keys(this.errorRequests).length; + }, + + // 重置所有状态 + reset() { + this.loadingRequests = {}; + this.errorRequests = {}; + } +}); + +/** + * 生成唯一的请求ID + * @returns {string} 唯一ID + */ +function generateRequestId() { + return Date.now() + "-" + Math.random().toString(36).substr(2, 9); +} + +/** + * 请求开始处理 + * @param {string} requestId - 请求ID + */ +function handleRequestStart(requestId) { + requestState.loadingRequests[requestId] = true; + // 从错误列表中删除,因为请求重新开始了 + delete requestState.errorRequests[requestId]; +} + +/** + * 请求结束处理 + * @param {string} requestId - 请求ID + */ +function handleRequestEnd(requestId) { + delete requestState.loadingRequests[requestId]; +} + +/** + * 请求错误处理 + * @param {string} requestId - 请求ID + * @param {object} error - 错误对象 + */ +function handleRequestError(requestId, error) { + requestState.errorRequests[requestId] = error; + handleRequestEnd(requestId); +} + +/** + * 显示错误提示 + * @param {object} error - 错误对象 + * @param {boolean} showErrorToast - 是否显示错误提示 + */ +function showError(error, showErrorToast) { + if (showErrorToast) { + // 获取错误消息 + const message = error.errMsg || error.message || "请求失败"; + uni.showToast({ + title: message, + icon: "none", + duration: 2000 + }); + } + console.error("Request Error:", error); +} + +/** + * 使用增强的请求功能 + * @param {object} options - 请求配置 + * @returns {object} 包含请求方法的对象 + */ +export function useRequest(options = {}) { + const defaultOptions = { + baseUrl: "/api", + showErrorToast: true, + timeout: 60000, + retryCount: 0, + retryDelay: 1000, + ...options + }; + + /** + * 执行HTTP请求 + * @param {object} config - 请求配置 + * @returns {Promise} 请求Promise + */ + const request = (config) => { + const requestId = generateRequestId(); + let retries = 0; + + // 合并配置 + const mergedConfig = { + ...defaultOptions, + ...config, + header: { + "Content-Type": "application/json", + "X-Requested-With": "XMLHttpRequest", + ...defaultOptions.header, + ...config.header + } + }; + + // 构建完整URL + if (mergedConfig.url && !mergedConfig.url.startsWith("http")) { + mergedConfig.url = `${mergedConfig.baseUrl}${mergedConfig.url}`; + } + + /** + * 执行实际请求 + * @returns {Promise} 请求Promise + */ + const executeRequest = () => { + handleRequestStart(requestId); + + return new Promise((resolve, reject) => { + uni.request({ + ...mergedConfig, + success: (response) => { + const { statusCode, data } = response; + + // 成功状态码处理 + if (statusCode >= 200 && statusCode < 300) { + // API业务逻辑成功 + if (data.code === 0 || data.code === 200 || data.status === 200) { + resolve(data); + } + // API业务逻辑失败 + else { + const error = { + code: data.code || statusCode, + message: data.message || data.msg || "请求失败", + data: data + }; + + + // 特殊错误码处理 + if (data.code === 600098) { + // Token失效,清除存储并跳转登录 + uni.removeStorageSync("token"); + uni.removeStorageSync("userInfo"); + + uni.showToast({ + title: "登录已过期,请重新登录", + icon: "none", + duration: 2000 + }); + + setTimeout(() => { + uni.navigateTo({ url: "/pages/login/index" }); + }, 2000); + } + + showError(error, mergedConfig.showErrorToast); + handleRequestError(requestId, error); + reject(error); + } + } + // HTTP错误状态码 + else { + const error = { + code: statusCode, + message: `HTTP错误: ${statusCode}`, + data: data + }; + + showError(error, mergedConfig.showErrorToast); + + // 是否需要重试 + if (retries < mergedConfig.retryCount) { + retries++; + setTimeout(() => { + handleRequestEnd(requestId); + retryRequest(); + }, mergedConfig.retryDelay); + } else { + handleRequestError(requestId, error); + reject(error); + } + } + }, + fail: (error) => { + showError(error, mergedConfig.showErrorToast); + + // 是否需要重试 + if (retries < mergedConfig.retryCount) { + retries++; + setTimeout(() => { + handleRequestEnd(requestId); + retryRequest(); + }, mergedConfig.retryDelay); + } else { + handleRequestError(requestId, error); + reject(error); + } + }, + complete: () => { + if (retries === 0 || retries >= mergedConfig.retryCount) { + handleRequestEnd(requestId); + } + } + }); + }); + }; + + /** + * 重试请求 + * @returns {Promise} 重试请求Promise + */ + const retryRequest = () => { + console.log(`重试请求 (${retries}/${mergedConfig.retryCount})...`); + return executeRequest(); + }; + + return executeRequest(); + }; + + /** + * GET请求 + * @param {string} url - 请求URL + * @param {object} params - 查询参数 + * @param {object} config - 其他配置 + * @returns {Promise} 请求Promise + */ + const get = (url, params = {}, config = {}) => { + return request({ + method: "GET", + url, + data: params, + ...config + }); + }; + + /** + * POST请求 + * @param {string} url - 请求URL + * @param {object} data - 请求数据 + * @param {object} config - 其他配置 + * @returns {Promise} 请求Promise + */ + const post = (url, data = {}, config = {}) => { + return request({ + method: "POST", + url, + data, + ...config + }); + }; + + /** + * PUT请求 + * @param {string} url - 请求URL + * @param {object} data - 请求数据 + * @param {object} config - 其他配置 + * @returns {Promise} 请求Promise + */ + const put = (url, data = {}, config = {}) => { + return request({ + method: "PUT", + url, + data, + ...config + }); + }; + + /** + * DELETE请求 + * @param {string} url - 请求URL + * @param {object} data - 请求数据 + * @param {object} config - 其他配置 + * @returns {Promise} 请求Promise + */ + const del = (url, data = {}, config = {}) => { + return request({ + method: "DELETE", + url, + data, + ...config + }); + }; + + // 返回所有HTTP方法 + return { + request, + get, + post, + put, + delete: del + }; +} + diff --git a/frontend/src/utils/routerInterceptor.js b/frontend/src/utils/routerInterceptor.js new file mode 100644 index 0000000..e0db519 --- /dev/null +++ b/frontend/src/utils/routerInterceptor.js @@ -0,0 +1,98 @@ +import {Dialog} from "tdesign-mobile-vue"; + +/** + * 路由拦截器配置 + * @param {Array} whiteList - 不需要登录就可以访问的页面路径列表 + */ +export const setupRouterInterceptor = (whiteList = []) => { + // 添加各种导航方法的拦截器 + addNavigationInterceptors(whiteList) +} + +/** + * 添加所有导航方法的拦截器 + * @param {Array} whiteList - 白名单页面列表 + */ +function addNavigationInterceptors(whiteList) { + // 页面跳转拦截 + uni.addInterceptor('navigateTo', { + invoke: (args) => routeInterceptor(args, whiteList) + }) + + // 页面重定向拦截 + uni.addInterceptor('redirectTo', { + invoke: (args) => routeInterceptor(args, whiteList) + }) + + // 页面重启动拦截 + uni.addInterceptor('reLaunch', { + invoke: (args) => routeInterceptor(args, whiteList) + }) + + // Tab切换拦截 + uni.addInterceptor('switchTab', { + invoke: (args) => routeInterceptor(args, whiteList) + }) +} + +/** + * 路由拦截处理函数 + * @param {Object} args - 导航参数 + * @param {Array} whiteList - 白名单页面列表 + * @returns {Object|boolean} - 继续导航或阻止导航 + */ +function routeInterceptor(args, whiteList) { + // 获取目标路径 + const token = uni.getStorageSync('token') + const targetUrl = args.url + + // 检查目标路径是否在白名单中 + const isInWhiteList = whiteList.some(path => { + return targetUrl.startsWith(path) || targetUrl === path + }) + + console.log('路由拦截检查:', {url: targetUrl, isInWhiteList, hasToken: !!token}) + + // 如果不在白名单且未登录,则跳转到登录页 + if (!isInWhiteList && !token) { + console.log('拦截导航,跳转到登录页') + + // 保存用户尝试访问的页面,以便登录后跳回 + try { + uni.setStorageSync('REDIRECT_URL', targetUrl) + } catch (e) { + } + + Dialog.confirm({ + title: '提示', + content: '您尚未登录,是否前往登录页面?', + cancelBtn: '取消', + confirmBtn: '确认', + onConfirm: () => { + uni.navigateTo({ + url: '/pages/login/index' + }) + }, + onCancel: () => { + console.log('取消登录') + } + }) + // 阻止原导航 + return false + } + // 继续原导航 + return args +} + +/** + * 获取白名单页面配置 + * @returns {Array} 默认白名单页面列表 + */ +export const getDefaultWhiteList = () => { + return [ + '/', + '/pages/index/index', + '/pages/login/index', + '/pages/profile/index' + ] +} \ No newline at end of file diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 38d8284..12d1dfc 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -3,6 +3,7 @@ import uni from '@dcloudio/vite-plugin-uni' import AutoImport from 'unplugin-auto-import/vite'; import Components from 'unplugin-vue-components/vite'; import { TDesignResolver } from 'unplugin-vue-components/resolvers'; +import path from 'path'; // https://vitejs.dev/config/ @@ -20,10 +21,15 @@ export default defineConfig({ })], }) ], + resolve: { + alias: { + '@': path.resolve(__dirname, './src') + } + }, server: { proxy: { '/api': { - target: 'http://192.168.41.118:9090', + target: 'http://192.168.0.107:9090', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') }