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 @@
+
+
+
+
+
+
+
+
+
+ Trade
+
+
+
+ Deposit
+
+
+
+ Withdraw
+
+
+
+ Transfer
+
+
+
+
+
+
+
+
+ {{stock.symbol}}
+ {{stock.name}}
+ ${{stock.price}}
+
+ {{stock.change >= 0 ? '+' : ''}}{{stock.change}}%
+
+
+
+
+
+
+
+
+
+
+ {{index.name}}
+ {{index.value}}
+
+ {{index.change >= 0 ? '+' : ''}}{{index.change}}%
+
+
+
+
+
+
+
+
+
+
+
+
+ {{news.title}}
+ {{formatTime(news.time)}}
+
+
+
+
+
+
+
+
+
+
\ 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