From ed53811e3c6be123e55e56545dcc80644faeff12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=9E=97?= <2720981056@qq.com> Date: Thu, 7 Aug 2025 19:10:38 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E2=80=9C=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E2=80=9D=E5=9B=BD=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 30 ++-- package.json | 2 + src/pages.json | 5 + src/pages/home/index.vue | 163 +++++++++++--------- src/pages/more/index.vue | 295 ++++++++++++++++++++++++++++++++----- src/static/lang/enUS.json | 67 ++++++++- src/static/lang/zh_CN.json | 35 ++++- 7 files changed, 470 insertions(+), 127 deletions(-) diff --git a/package-lock.json b/package-lock.json index e6adbb2..33f9ab1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,9 @@ "@dcloudio/uni-mp-xhs": "3.0.0-4070520250711001", "@dcloudio/uni-quickapp-webview": "3.0.0-4070520250711001", "@dcloudio/uni-ui": "^1.5.10", + "@qiun/ucharts": "^2.5.0-20230101", "echarts": "^6.0.0", + "mpvue-echarts": "^1.0.0", "vue": "^3.4.21", "vue-i18n": "^9.14.5" }, @@ -3877,7 +3879,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, @@ -3917,7 +3918,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3938,7 +3938,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3959,7 +3958,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3980,7 +3978,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4001,7 +3998,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4022,7 +4018,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4043,7 +4038,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4064,7 +4058,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4085,7 +4078,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4106,7 +4098,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4127,7 +4118,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4148,7 +4138,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4169,7 +4158,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4183,6 +4171,12 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@qiun/ucharts": { + "version": "2.5.0-20230101", + "resolved": "https://registry.npmjs.org/@qiun/ucharts/-/ucharts-2.5.0-20230101.tgz", + "integrity": "sha512-C7ccBgfPuGF6dxTRuMW0NPPMSCf1k/kh3I9zkRVBc5PaivudX/rPL+jd2Wty6gn5ya5L3Ob+YmYe09V5xw66Cw==", + "license": "Apache" + }, "node_modules/@rollup/pluginutils": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", @@ -6446,7 +6440,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": { @@ -9619,6 +9612,12 @@ "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==", "license": "MIT" }, + "node_modules/mpvue-echarts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mpvue-echarts/-/mpvue-echarts-1.0.0.tgz", + "integrity": "sha512-tY73yPqfB3KvU5o5vMxOjqknJI+Z+s/dk2l6Uw/yo3Hz0NgDPqa8t2z6H+6e4AWqLu2TODjjOys2IUMq5/YOGQ==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -9679,7 +9678,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/package.json b/package.json index bdc6383..6278963 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,9 @@ "@dcloudio/uni-mp-xhs": "3.0.0-4070520250711001", "@dcloudio/uni-quickapp-webview": "3.0.0-4070520250711001", "@dcloudio/uni-ui": "^1.5.10", + "@qiun/ucharts": "^2.5.0-20230101", "echarts": "^6.0.0", + "mpvue-echarts": "^1.0.0", "vue": "^3.4.21", "vue-i18n": "^9.14.5" }, diff --git a/src/pages.json b/src/pages.json index a6650e7..3d0411a 100644 --- a/src/pages.json +++ b/src/pages.json @@ -1,4 +1,9 @@ { + + + "easycom": { + "^qiun-(.*)": "@qiun/ucharts/components/$1/$1.vue" + }, "pages": [ { "path": "pages/login/login", diff --git a/src/pages/home/index.vue b/src/pages/home/index.vue index 08ab690..764c733 100644 --- a/src/pages/home/index.vue +++ b/src/pages/home/index.vue @@ -65,9 +65,7 @@ - - {{index.name}} {{index.value}} @@ -76,13 +74,15 @@ - @@ -171,13 +171,23 @@ export default { time: "2023-06-15T07:15:00Z" } ], - charts: [], // 存储图表实例 - canvasElements: [] // 存储canvas元素 + charts: [], + systemInfo: null, + dpr: 1 } }, + onLoad() { + uni.getSystemInfo({ + success: (res) => { + this.systemInfo = res; + this.dpr = res.pixelRatio; + } + }); + }, onReady() { - // 页面初次渲染完成后初始化可见的图表 - this.initVisibleCharts(); + setTimeout(() => { + this.initCharts(); + }, 500); }, methods: { formatNumber(num) { @@ -209,37 +219,50 @@ export default { url: `/pages/news/detail?title=${encodeURIComponent(news.title)}` }); }, - // 保存canvas初始化信息 - onCanvasInit(index) { - return (canvas, width, height) => { - this.canvasElements[index] = { canvas, width, height }; - // 如果是当前显示的图表,立即初始化 - if (index === 0) { // 默认显示第一个 - this.initChart(index); - } - }; - }, - // 初始化指定索引的图表 - initChart(index) { - if (!this.canvasElements[index]) return; - - const { canvas, width, height } = this.canvasElements[index]; - const chart = echarts.init(canvas, null, { - width: width, - height: height + initCharts() { + this.marketIndices.forEach((_, index) => { + this.initChart(index); }); - canvas.setChart(chart); - - // 获取当前指数的历史数据 + }, + initChart(index) { + const query = uni.createSelectorQuery().in(this); + query.select(`#index-chart-${index}`) + .fields({ node: true, size: true }) + .exec((res) => { + if (!res[0] || !res[0].node) { + setTimeout(() => this.initChart(index), 100); + return; + } + + const canvas = res[0].node; + const width = res[0].width; + const height = res[0].height; + + canvas.width = width * this.dpr; + canvas.height = height * this.dpr; + canvas.style.width = `${width}px`; + canvas.style.height = `${height}px`; + + const chart = echarts.init(canvas, null, { + width: width, + height: height, + devicePixelRatio: this.dpr + }); + + const option = this.getChartOption(index); + chart.setOption(option); + + this.charts[index] = chart; + canvas.setChart(chart); + }); + }, + getChartOption(index) { const indexData = this.marketIndices[index]; - - // 设置图表配置 - const option = { + return { + animation: false, tooltip: { trigger: 'axis', - axisPointer: { - type: 'line' - } + axisPointer: { type: 'line' } }, grid: { left: '0%', @@ -280,39 +303,44 @@ export default { symbol: 'none' }] }; - - chart.setOption(option); - this.charts[index] = chart; - - return chart; }, - // 初始化可见的图表 - initVisibleCharts() { - // 初始化第一个图表(默认显示的) - this.initChart(0); + touchStart(e) { + const chart = this.getChartFromEvent(e); + chart && chart.dispatchAction({ + type: 'showTip', + seriesIndex: 0, + dataIndex: 0 + }); + }, + touchMove(e) { + const chart = this.getChartFromEvent(e); + chart && chart.dispatchAction({ + type: 'hideTip' + }); + }, + touchEnd(e) { + const chart = this.getChartFromEvent(e); + chart && chart.dispatchAction({ + type: 'hideTip' + }); + }, + getChartFromEvent(e) { + const canvasId = e.currentTarget.id; + const index = parseInt(canvasId.split('-')[2]); + return this.charts[index]; }, - // 轮播图切换时处理 handleSwiperChange(e) { const current = e.detail.current; - // 确保图表在切换时已初始化并重新绘制 - if (!this.charts[current]) { - // 如果图表尚未初始化,则初始化它 - this.initChart(current); - } else { - // 否则重新调整大小 + if (this.charts[current]) { this.charts[current].resize(); } } }, onUnload() { - // 页面卸载时销毁图表实例,释放资源 this.charts.forEach(chart => { - if (chart) { - chart.dispose(); - } + chart && chart.dispose(); }); this.charts = []; - this.canvasElements = []; } } @@ -322,7 +350,7 @@ export default { padding: 20rpx; background-color: #f5f5f5; min-height: 100vh; - padding-bottom: 120rpx; /* 给底部导航留空间 */ + padding-bottom: 120rpx; } .user-header { @@ -361,8 +389,8 @@ export default { flex-direction: column; } -.label{ - margin-top: 20rpx; +.label { + margin-top: 20rpx; } .total-assets { @@ -462,10 +490,9 @@ export default { display: block; } -/* 市场指数左右布局样式 */ .indices-swiper { width: 100%; - height: 300rpx; /* 调整高度适应左右布局 */ + height: 300rpx; margin-bottom: 20rpx; } @@ -477,19 +504,18 @@ export default { height: 100%; } -/* 左右布局容器 */ .index-content { display: flex; height: 100%; + width: 100%; } -/* 左侧数据区域 - 占30%宽度 */ .index-data { - flex: 0 0 30%; + flex: 0 0 28%; /* 减少左侧数据区域宽度 */ display: flex; flex-direction: column; justify-content: center; - padding-right: 20rpx; + padding-right: 15rpx; /* 减少右侧内边距 */ border-right: 1px solid #f0f0f0; } @@ -509,16 +535,17 @@ export default { font-size: 30rpx; } -/* 右侧图表区域 - 占70%宽度 */ .chart-container { - flex: 0 0 70%; - padding-left: 20rpx; + flex: 1; /* 使用flex:1而不是固定百分比,让图表占满剩余空间 */ + padding-left: 15rpx; /* 减少左侧内边距 */ position: relative; + height: 100%; /* 确保高度充满容器 */ } .index-chart { width: 100%; height: 100%; + display: block; } .news-list { diff --git a/src/pages/more/index.vue b/src/pages/more/index.vue index 6c6928b..eafdd31 100644 --- a/src/pages/more/index.vue +++ b/src/pages/more/index.vue @@ -2,33 +2,33 @@ - 设置 + {{ $t('more.setting.title') }} - + - + - 我的银行卡 + {{ $t('more.bankcard') }} - {{userInfo.bankCardCount}}张 + {{userInfo.bankCardCount}} @@ -37,44 +37,84 @@ - 实名认证 + {{ $t('more.authentication') }} - {{authStatusText[userInfo.authStatus] || '未认证'}} + {{authStatusText[userInfo.authStatus] || $t('more.not_authenticated')}} - - + + - - 语言设置 + + {{ $t('more.changePassword') }} - {{languageText[userInfo.language] || '简体中文'}} - - + + - - 系统设置 + + {{ $t('more.customerService') }} + + + + + + {{ $t('more.languagesettings') }} + + + {{currentLanguageText}} + + + - 退出登录 + {{ $t('more.logout')}} + + + + + + {{$t('more.selectlanguage')}} + + + {{ text }} + + + + + + + @@ -82,29 +122,65 @@ export default { data() { return { + showLanguageModal: false, userInfo: { avatar: '/static/avatar.jpg', nickname: '张三', phone: '13800138000', bankCardCount: 2, authStatus: 1, // 0-未认证 1-已认证 2-认证中 3-认证失败 - language: 'zh-CN', + language: 'zh', isLogin: true }, authStatusText: { - 0: '未认证', - 1: '已认证', - 2: '认证中', - 3: '认证失败' + 0: this.$t('more.not_authenticated'), + 1: this.$t('more.authenticated'), + 2: this.$t('more.authenticating'), + 3: this.$t('more.auth_failed') }, - languageText: { - 'zh-CN': '简体中文', - 'en-US': 'English', - 'zh-TW': '繁體中文' + languageOptions: { + 'zh': 'Chinese', + 'en': 'English', } } + },onShow() { + this.setTabBarI18n(); + }, + computed: { + currentLanguageText() { + return this.languageOptions[this.userInfo.language] || $t('more.language') + } }, methods: { + + setTabBarI18n() { + const locale = this.$i18n.locale; + const tabBarTexts = { + zh: ['首页', '基金', '股票', '资产', '更多'], + en: ['Home', 'Market', 'Trade', 'Assets', 'More'] + }; + + uni.setTabBarItem({ + index: 0, + text: this.$t('tabBar.index') + }); + uni.setTabBarItem({ + index: 1, + text: this.$t('tabBar.market') + }); + uni.setTabBarItem({ + index: 2, + text: this.$t('tabBar.trade') + }); + uni.setTabBarItem({ + index: 3, + text: this.$t('tabBar.assets') + }); + uni.setTabBarItem({ + index: 4, + text: this.$t('tabBar.more') + }); + }, // 隐藏手机号中间四位 hidePhone(phone) { return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') @@ -117,16 +193,23 @@ export default { }) }, + // 联系客服 + contactCustomerService() { + //跳转客服页面 + // uni.navigateTo({ + // url: '/pages/customerService/index' + // }); + }, + // 退出登录 handleLogout() { uni.showModal({ - title: '提示', - content: '确定要退出登录吗?', + title: this.$t('common.tip'), + content: this.$t('more.confirmLogout'), success: (res) => { if (res.confirm) { - // 这里调用退出登录接口 uni.showLoading({ - title: '正在退出...' + title: this.$t('common.loggingOut') }) // 模拟退出登录 @@ -136,11 +219,11 @@ export default { this.userInfo.nickname = '' this.userInfo.phone = '' uni.showToast({ - title: '退出成功', + title: this.$t('common.logoutSuccess'), icon: 'success' }) - // 跳转到登录页或其他页面 + // 跳转到登录页 uni.reLaunch({ url: '/pages/login/login' }) @@ -148,6 +231,26 @@ export default { } } }) + }, + + // 更改语言 + handleLanguageChange(lang) { + this.userInfo.language = lang + this.$i18n.locale = lang; + this.showLanguageModal = false + + this.setTabBarI18n(); + + uni.showToast({ + title: `${this.$t('more.languageChanged')}${this.languageOptions[lang]}`, + icon: 'none' + }) + + // 实际项目中这里可以调用API保存语言偏好 + // this.saveLanguagePreference(lang); + + // 如果需要国际化,可以在这里触发语言更新 + this.$i18n.locale = lang; } } } @@ -156,7 +259,7 @@ export default { \ No newline at end of file diff --git a/src/static/lang/enUS.json b/src/static/lang/enUS.json index 7dfd9c6..b73856b 100644 --- a/src/static/lang/enUS.json +++ b/src/static/lang/enUS.json @@ -1,4 +1,7 @@ { + // Login + "index.Loading": "Loading...", + "index.errMsg": "Failed to load", "login.loginButton": "Login", "login.usernamePlaceholder": "Please enter username", "login.idCardLabel": "Last 6 digits of ID card", @@ -7,7 +10,7 @@ "login.appTitle": "European Stock Software", "login.rememberPassword": "Remember password", "login.forgotPassword": "Forgot password", - "login.agreeTermsPrefix": "I have read and agree to", + "login.agreeTermsPrefix": "I have read and agree to the", "login.agreeTermsSuffix": "User Agreement", "login.userAgreement": "User Agreement", "login.and": "and", @@ -17,27 +20,79 @@ "login.languagechangeclose": "Done", "login.chooseLanguage": "Select Language", "login.changelanguage": "Change Language", + "login.errors.agreeTermsFirst": "Please agree to the User Agreement and Privacy Policy first", + "login.errors.emptyUsername": "Please enter username", + "login.errors.invalidIdCard": "Please enter the last 6 digits of your ID card correctly", + "login.errors.emptyPassword": "Please enter password", + // Registration "register.chooseLanguage": "Select Language", "register.languagechangeclose": "Done", "register.appTitle": "European 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.idCardPlaceholder": "Please enter the last 6 digits of ID card", + "register.errors.emptyIdCard": "Please enter ID card number", "register.passwordLabel": "Password", + "register.passwordTip": "Password must be at least 6 characters", "register.passwordPlaceholder": "Please enter password", "register.confirmPasswordLabel": "Confirm Password", - "register.confirmPasswordPlaceholder": "Please confirm password again", + "register.confirmPasswordPlaceholder": "Please enter 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.errors.emailRequired": "Email cannot be empty", + "register.idCardLast6Error": "Please enter correct ID card number", + "register.errors.invalidPassword": "Password must be at least 8 characters with both letters and numbers", + "register.errors.emptyPassword": "Password cannot be empty", + "register.errors.confirmPasswordRequired": "Please enter password again", + "register.errors.invalidEmail": "Please enter a valid email", + "register.errors.passwordMismatch": "Passwords do not match", + "register.errors.invalidIdCard": "Please enter correct ID card number", + "register.errors.agreeTermsFirst": "Please read and agree to the User Agreement and Privacy Policy first", + "register.registerProcessing": "Registering...", + "register.agreeTermsPrefix": "I have read and agree to the", "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" -} + "register.registerSuccess": "Registration successful", + + // Home + "home.welcome": "Welcome", + "home.totalAssets": "Total Assets", + + // Settings + "more.setting.title": "Settings", + "more.nologin": "Not logged in", + "more.clicklogin": "Click to login", + "more.bankcard": "Bank Cards", + "more.authentication": "Real-name Authentication", + "more.not_authenticated": "Not authenticated", + "more.authenticated": "Authenticated", + "more.authenticating": "Authenticating", + "more.auth_failed": "Authentication failed", + "more.changePassword": "Change Password", + "more.customerService": "Customer Service", + "more.languagesettings": "Language Settings", + "more.logout": "Logout", + "more.selectlanguage": "Select Language", + "more.languageChanged": "Language changed to", + "more.close": "Close", + "more.confirmLogout": "Are you sure you want to logout?", + + // Common + "common.tip": "Tip", + "common.loggingOut": "Logging out...", + "common.logoutSuccess": "Logout successful", + + // TabBar + "tabBar.index": "Home", + "tabBar.market": "Funds", + "tabBar.trade": "Stocks", + "tabBar.assets": "Assets", + "tabBar.more": "More" +} \ No newline at end of file diff --git a/src/static/lang/zh_CN.json b/src/static/lang/zh_CN.json index 2480fe5..b5b74eb 100644 --- a/src/static/lang/zh_CN.json +++ b/src/static/lang/zh_CN.json @@ -67,7 +67,40 @@ //首页 "home.welcome":"欢迎", - "home.totalAssets":"总资产" + "home.totalAssets":"总资产", + + + + //设置 + "more.setting.title":"设置", + "more.nologin":"未登录", + "more.clicklogin":"点击登录", + "more.bankcard":"银行卡", + "more.authentication":"实名认证", + "more.not_authenticated":"未认证", + "more.authenticated":"已认证", + "more.authenticating":"认证中", + "more.auth_failed":"认证失败", + "more.changePassword":"修改密码", + "more.customerService":"在线客服", + "more.languagesettings":"语言设置", + "more.logout":"退出登录", + "more.selectlanguage":"选择语言", + "more.languageChanged":"语言已切换成", + "more.close":"关闭", + "more.confirmLogout":"确定要退出登录吗?", + + "common.tip":"提示", + "common.loggingOut":"正在退出登录...", + "common.logoutSuccess":"退出登录成功", + + "tabBar.index":"首页", + "tabBar.market":"基金", + "tabBar.trade":"股票", + "tabBar.assets":"资产" , + "tabBar.more":"更多" + + } \ No newline at end of file