From d9dffb25377bbfadaac913805e91f21d495b13b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=9E=97?= <2720981056@qq.com> Date: Tue, 5 Aug 2025 20:54:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=81=E8=A3=85request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 16 -- src/api/login.js | 51 +++++ src/main.js | 49 +++-- src/pages.json | 6 + src/pages/home/index.vue | 372 +++++++++++++++++++++++++++++++++++++ src/pages/login/login.vue | 78 ++++---- src/static/lang/enUS.json | 44 ++++- src/static/lang/zh_CN.json | 4 + src/utils/request.js | 134 +++++++++++++ 9 files changed, 682 insertions(+), 72 deletions(-) create mode 100644 src/api/login.js create mode 100644 src/pages/home/index.vue create mode 100644 src/utils/request.js diff --git a/package-lock.json b/package-lock.json index f4db8ab..8af4c0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3812,7 +3812,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -3852,7 +3851,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3873,7 +3871,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3894,7 +3891,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3915,7 +3911,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3936,7 +3931,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3957,7 +3951,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3978,7 +3971,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3999,7 +3991,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4020,7 +4011,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4041,7 +4031,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4062,7 +4051,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4083,7 +4071,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4104,7 +4091,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6100,7 +6086,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, "license": "Apache-2.0", "optional": true, "bin": { @@ -8812,7 +8797,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, "license": "MIT", "optional": true }, diff --git a/src/api/login.js b/src/api/login.js new file mode 100644 index 0000000..ce781f6 --- /dev/null +++ b/src/api/login.js @@ -0,0 +1,51 @@ + + +import { request } from '../utils/request' + +/** + * 用户登录 + * @param {Object} data - 登录数据 {username, password} + * @returns {Promise} + */ +export function login(data) { + return request({ + url: '/user/login', + method: 'POST', + data + }) +} + +/** + * 获取用户信息 + * @returns {Promise} + */ +export function getUserInfo() { + return request({ + url: '/user/info', + method: 'GET' + }) +} + +/** + * 更新用户信息 + * @param {Object} data - 用户信息 + * @returns {Promise} + */ +export function updateUserInfo(data) { + return request({ + url: '/user/info', + method: 'PUT', + data + }) +} + +/** + * 用户注销 + * @returns {Promise} + */ +export function logout() { + return request({ + url: '/user/logout', + method: 'POST' + }) +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index c14dd9f..0eab3d6 100644 --- a/src/main.js +++ b/src/main.js @@ -1,46 +1,47 @@ import { createSSRApp } from 'vue' import App from './App.vue' import { createI18n } from 'vue-i18n' -// 导入语言包 +import { request, http } from '@/utils/request' // 引入封装的request import en from './static/lang/enUS.json' -import cn from './static/lang/zh_CN.json' +import zh from './static/lang/zh_CN.json' export function createApp() { const app = createSSRApp(App) - // 获取系统语言(适配uni-app环境) - const systemInfo = uni.getSystemInfoSync() || {}; - const systemLanguage = systemInfo.language || 'zh-CN'; - let curLang = 'cn'; + // 1. 获取系统语言 + const systemInfo = uni.getSystemInfoSync() || {} + const systemLanguage = systemInfo.language || 'zh-CN' + let curLang = 'zh' - // 语言判断(转换为小写处理) switch (systemLanguage.toLowerCase()) { case 'en': case 'en-us': - curLang = 'en'; - break; + curLang = 'en' + break case 'zh': case 'zh-cn': case 'zh-hans': - curLang = 'cn'; - break; + curLang = 'zh' + break } - // 配置i18n + // 2. 配置i18n const i18n = createI18n({ legacy: false, - locale: curLang, // 使用检测到的系统语言 + locale: curLang, fallbackLocale: 'en', - messages: { - en, // 英文语言包 - cn // 中文语言包 - }, + messages: { en, zh }, missing: (locale, key) => { - console.error(`[i18n] 缺失: '${key}' 在 '${locale}' 语言包中不存在`); - return process.env.NODE_ENV === 'development' ? `[缺失: ${key}]` : ''; + console.error(`[i18n] 缺失: '${key}' 在 '${locale}' 语言包中不存在`) + return process.env.NODE_ENV === 'development' ? `[缺失: ${key}]` : '' } }) + // 3. 挂载request到全局 + app.config.globalProperties.$request = request + app.config.globalProperties.$http = http + + // 4. 使用i18n插件 app.use(i18n) return { @@ -52,5 +53,15 @@ export function createApp() { // 非SSR模式下挂载应用 if (!globalThis.__IS_SSR__) { const { app } = createApp() + + // 全局错误处理 + app.config.errorHandler = (err) => { + console.error('全局错误:', err) + uni.showToast({ + title: '发生错误,请重试', + icon: 'none' + }) + } + app.mount('#app') } \ No newline at end of file diff --git a/src/pages.json b/src/pages.json index 4033843..442e142 100644 --- a/src/pages.json +++ b/src/pages.json @@ -11,6 +11,12 @@ "style": { "navigationBarTitleText": "" } + }, + { + "path": "pages/home/index", + "style": { + "navigationBarTitleText": "" + } } ], "globalStyle": { diff --git a/src/pages/home/index.vue b/src/pages/home/index.vue new file mode 100644 index 0000000..6518431 --- /dev/null +++ b/src/pages/home/index.vue @@ -0,0 +1,372 @@ + + + + + \ No newline at end of file diff --git a/src/pages/login/login.vue b/src/pages/login/login.vue index 6d3675b..fb2a340 100644 --- a/src/pages/login/login.vue +++ b/src/pages/login/login.vue @@ -140,6 +140,11 @@ diff --git a/src/static/lang/enUS.json b/src/static/lang/enUS.json index 634e244..4f7ebe0 100644 --- a/src/static/lang/enUS.json +++ b/src/static/lang/enUS.json @@ -1,5 +1,45 @@ { - "index.Loading": "Loading", - "index.errMsg": "Error" + "index.Loading": "Loading...", + "index.errMsg": "Failed to load", + "login.loginButton": "Login", + "login.usernamePlaceholder": "Please enter username", + "login.idCardLabel": "Last 6 digits of ID card", + "login.passwordPlaceholder": "Please enter password", + "login.passwordLabel": "Password", + "login.appTitle": "European Stock Software", + "login.rememberPassword": "Remember password", + "login.forgotPassword": "Forgot password", + "login.agreeTermsPrefix": "I have read and agree to", + "login.agreeTermsSuffix": "User Agreement", + "login.userAgreement": "User Agreement", + "login.and": "and", + "login.privacyPolicy": "Privacy Policy", + "login.registerButton": "Register", + "login.noAccount": "No account?", + "login.languagechangeclose": "Done", + "login.chooseLanguage": "Select Language", + "login.changelanguage": "Change Language", + "register.chooseLanguage": "Select Language", + "register.languagechangeclose": "Done", + "register.appTitle": "European & American Stock Software", + "register.registerDesc": "Create an account to continue", + "register.idCardLabel": "Last 6 digits of ID card", + "register.idCardPlaceholder": "Please enter last 6 digits of ID card", + "register.passwordLabel": "Password", + "register.passwordPlaceholder": "Please enter password", + "register.confirmPasswordLabel": "Confirm Password", + "register.confirmPasswordPlaceholder": "Please confirm password again", + "register.inviteCodeLabel": "Invitation Code", + "register.inviteCodePlaceholder": "Please enter invitation code", + "register.emailLabel": "Email", + "register.emailPlaceholder": "Please enter email", + "register.agreeTermsPrefix": "I have read and agree to", + "register.userAgreement": "User Agreement", + "register.and": "and", + "register.privacyPolicy": "Privacy Policy", + "register.registerButton": "Register", + "register.hasAccount": "Already have an account?", + "register.loginNow": "Login now", + "register.registerSuccess": "Registration successful" } diff --git a/src/static/lang/zh_CN.json b/src/static/lang/zh_CN.json index de1559f..6ae13ea 100644 --- a/src/static/lang/zh_CN.json +++ b/src/static/lang/zh_CN.json @@ -20,6 +20,10 @@ "login.languagechangeclose": "完成", "login.chooseLanguage": "选择语言", "login.changelanguage": "切换语言", + "login.errors.agreeTermsFirst": "请先同意用户协议和隐私政策", + "login.errors.emptyUsername": "请输入用户名", + "login.errors.invalidIdCard": "请输入正确身份证号码的后六位", + "login.errors.emptyPassword": "请输入密码", "register.chooseLanguage": "选择语言", diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..65acb73 --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,134 @@ +// utils/request.js + +const BASE_URL = process.env.VUE_APP_API_BASE_URL || '/api' +const TOKEN_KEY = 'auth_token' + +/** + * 基础请求方法 + */ +export function request(options) { + // 默认配置 + const defaultOptions = { + url: '', + method: 'GET', + data: {}, + header: { + 'Content-Type': 'application/json' + }, + timeout: 10000, + showLoading: false, + loadingText: '加载中...', + checkAuth: true + } + + // 合并配置 + options = { ...defaultOptions, ...options } + + // 请求拦截 - 处理URL + if (!options.url.startsWith('http')) { + options.url = BASE_URL + options.url + } + + // 请求拦截 - 添加token + if (options.checkAuth) { + const token = uni.getStorageSync(TOKEN_KEY) + if (token) { + options.header.Authorization = `Bearer ${token}` + } + } + + // 显示加载提示 + if (options.showLoading) { + uni.showLoading({ + title: options.loadingText, + mask: true + }) + } + + return new Promise((resolve, reject) => { + uni.request({ + ...options, + success: (res) => { + handleResponse(res, resolve, reject) + }, + fail: (err) => { + handleError(err, reject) + }, + complete: () => { + if (options.showLoading) { + uni.hideLoading() + } + } + }) + }) +} + +// 响应处理函数 +function handleResponse(res, resolve, reject) { + if (res.statusCode === 200) { + resolve(res.data) + } else if (res.statusCode === 401) { + handleUnauthorized() + reject(new Error('未授权')) + } else { + handleHttpError(res.statusCode) + reject(new Error(`HTTP错误: ${res.statusCode}`)) + } +} + +// 错误处理函数 +function handleError(err, reject) { + uni.showToast({ + title: '网络连接错误', + icon: 'none', + duration: 2000 + }) + reject(err) +} + +// HTTP错误处理 +function handleHttpError(statusCode) { + const errorMap = { + 400: '请求参数错误', + 403: '拒绝访问', + 404: '资源不存在', + 500: '服务器错误' + } + uni.showToast({ + title: errorMap[statusCode] || `请求错误: ${statusCode}`, + icon: 'none', + duration: 2000 + }) +} + +// 未授权处理 +function handleUnauthorized() { + uni.removeStorageSync(TOKEN_KEY) + uni.showToast({ + title: '登录已过期', + icon: 'none', + duration: 1500 + }) + setTimeout(() => { + uni.navigateTo({ + url: '/pages/login/login' + }) + }, 1500) +} + +/** + * 快捷方法 + */ +export const http = { + get: (url, params, options) => + request({ url, params, method: 'GET', ...options }), + + post: (url, data, options) => + request({ url, data, method: 'POST', ...options }), + + put: (url, data, options) => + request({ url, data, method: 'PUT', ...options }), + + delete: (url, data, options) => + request({ url, data, method: 'DELETE', ...options }) +} \ No newline at end of file