diff --git a/f/web-kboss/src/assets/less/news/news.less b/f/web-kboss/src/assets/less/news/news.less index a70e549..d66c293 100644 --- a/f/web-kboss/src/assets/less/news/news.less +++ b/f/web-kboss/src/assets/less/news/news.less @@ -1,7 +1,10 @@ .news-view-page { position: relative; + width: 100%; + max-width: 100%; + min-width: 0; min-height: 100vh; - overflow-x: hidden; + overflow-x: clip; color: #1f2937; background: radial-gradient(circle at 78% 18%, rgba(236, 72, 153, 0.07) 0%, rgba(236, 72, 153, 0) 32%), @@ -12,13 +15,15 @@ .news-shell { position: relative; z-index: 1; - max-width: 1280px; + box-sizing: border-box; + width: 100%; + max-width: 1400px; margin: 0 auto; padding: 0 24px; } .orb { - position: fixed; + position: absolute; z-index: 0; border-radius: 50%; filter: blur(110px); @@ -196,6 +201,8 @@ .news-featured, .news-item { position: relative; + width: 100%; + max-width: 100%; overflow: hidden; cursor: pointer; background: #fff; @@ -253,11 +260,19 @@ .news-featured-inner { display: grid; - grid-template-columns: 1fr 2fr; - min-height: 180px; + grid-template-columns: minmax(280px, 380px) minmax(0, 1fr); + align-items: stretch; + width: 100%; + min-height: 280px; } - - .news-featured-img, + + .news-featured-img { + position: relative; + overflow: hidden; + width: 100%; + min-height: 280px; + } + .news-item-img { position: relative; overflow: hidden; @@ -280,6 +295,8 @@ display: flex; flex-direction: column; justify-content: center; + min-width: 0; + width: 100%; padding: 24px 40px; } @@ -484,13 +501,22 @@ .news-hero { padding: 120px 0 56px; } - + .hero-title-row { flex-direction: column; gap: 10px; align-items: flex-start; } - + + .news-featured-inner { + grid-template-columns: 1fr; + } + + .news-featured-img { + width: 100%; + min-height: 220px; + } + .filter-tabs { display: flex; border-radius: 20px; @@ -501,16 +527,11 @@ padding: 8px 16px; font-size: 14px; } - - .news-featured-inner, + .news-grid { grid-template-columns: 1fr; } - - .news-featured-img { - height: 220px; - } - + .news-featured-body { padding: 24px; } diff --git a/f/web-kboss/src/i18n/lang/en-US.js b/f/web-kboss/src/i18n/lang/en-US.js index 3514dc2..823fd09 100644 --- a/f/web-kboss/src/i18n/lang/en-US.js +++ b/f/web-kboss/src/i18n/lang/en-US.js @@ -401,5 +401,59 @@ export default { openedDecision: 'The Investment Strategy Agent page has been opened.
Anything else you would like to know?', openedPage: 'The related page has been opened. Anything else you would like to know?' }, + loginDialog: { + welcomeLogin: 'Welcome', + createAccount: 'Create Account', + signIn: 'Sign In', + signUp: 'Sign Up', + signInWithPassword: 'Password', + signInWithCode: 'Verification Code', + enterAccount: 'Enter account', + enterPassword: 'Enter password', + enterMobile: 'Enter mobile number', + enterVerificationCode: 'Enter verification code', + enterAccountName: 'Enter account name', + forgotPassword: 'Forgot password?', + noAccountSignUp: 'No account? Sign Up', + signInNow: 'Sign In', + getVerificationCode: 'Get Verification Code', + agreePrefix: 'I have read and agree to the ', + userAgreement: 'User Agreement', + agreeAnd: ' and ', + privacyPolicy: 'Privacy Policy', + signUpNow: 'Sign Up', + hasAccountSignIn: 'Already have an account? Sign In', + signingIn: 'Signing in...', + signingUp: 'Signing up...', + resendCode: 'Resend {seconds}s', + mobileRequired: 'Enter mobile number', + mobileInvalid: 'Please enter a valid mobile number', + accountRequired: 'Enter account', + passwordRequired: 'Enter password', + codeRequired: 'Enter verification code', + accountNameRequired: 'Enter account name', + agreeRequired: 'Please read and agree to the agreements first', + codeSent: 'Verification code sent', + codeSendFail: 'Failed to get verification code', + loginFail: 'Sign in failed', + loginSuccess: 'Signed in successfully', + registerSuccess: 'Registration successful. Please sign in.', + registerFail: 'Registration failed', + registerRetry: 'Registration failed. Please try again.', + resetPassword: 'Reset Password', + resetPasswordDesc: 'Verify identity via mobile verification code to set a new password', + mobileLabel: 'Mobile Number', + newPasswordLabel: 'New Password', + verificationCodeLabel: 'Verification Code', + enterBoundMobile: 'Enter bound mobile number', + enterNewPassword: 'Enter new password', + cancel: 'Cancel', + confirmReset: 'Confirm Reset', + newPasswordRequired: 'Enter new password', + getCodeFirst: 'Please get the verification code first', + resetSuccess: 'Password reset successfully', + resetFail: 'Password reset failed', + codeSentCheck: 'Verification code sent. Please check your messages.' + }, ...autoMessages } diff --git a/f/web-kboss/src/i18n/lang/zh-CN.js b/f/web-kboss/src/i18n/lang/zh-CN.js index 09ec8bd..4925636 100644 --- a/f/web-kboss/src/i18n/lang/zh-CN.js +++ b/f/web-kboss/src/i18n/lang/zh-CN.js @@ -401,5 +401,59 @@ export default { openedDecision: '已为您打开投策智能体页面 📊
还有其他想了解的吗?', openedPage: '已为您打开相关页面。还有其他想了解的吗?' }, + loginDialog: { + welcomeLogin: '欢迎登录', + createAccount: '创建账号', + signIn: '登录', + signUp: '注册', + signInWithPassword: '密码登录', + signInWithCode: '验证码登录', + enterAccount: '请输入账户', + enterPassword: '请输入密码', + enterMobile: '请输入手机号', + enterVerificationCode: '请输入验证码', + enterAccountName: '请输入账户名', + forgotPassword: '忘记密码?', + noAccountSignUp: '没有账号?去注册', + signInNow: '立即登录', + getVerificationCode: '获取验证码', + agreePrefix: '我已阅读并同意', + userAgreement: '《用户协议》', + agreeAnd: '、', + privacyPolicy: '《隐私政策》', + signUpNow: '立即注册', + hasAccountSignIn: '已有账号?前往登录', + signingIn: '登录中...', + signingUp: '注册中...', + resendCode: '重新发送 {seconds}s', + mobileRequired: '请输入手机号', + mobileInvalid: '请输入正确的手机号', + accountRequired: '请输入账户', + passwordRequired: '请输入密码', + codeRequired: '请输入验证码', + accountNameRequired: '请输入账户名', + agreeRequired: '请先阅读并同意相关协议', + codeSent: '验证码已发送', + codeSendFail: '验证码获取失败', + loginFail: '登录失败', + loginSuccess: '登录成功', + registerSuccess: '注册成功,请登录', + registerFail: '注册失败', + registerRetry: '注册失败,请重试', + resetPassword: '重置密码', + resetPasswordDesc: '通过手机号验证码验证身份后设置新密码', + mobileLabel: '手机号', + newPasswordLabel: '新密码', + verificationCodeLabel: '验证码', + enterBoundMobile: '请输入绑定手机号', + enterNewPassword: '请输入新密码', + cancel: '取消', + confirmReset: '确认重置', + newPasswordRequired: '请输入新密码', + getCodeFirst: '请先获取验证码', + resetSuccess: '密码重置成功', + resetFail: '密码重置失败', + codeSentCheck: '验证码已发送,请注意查收。' + }, ...autoMessages } diff --git a/f/web-kboss/src/main.js b/f/web-kboss/src/main.js index 384c4fb..58e0453 100644 --- a/f/web-kboss/src/main.js +++ b/f/web-kboss/src/main.js @@ -12,6 +12,7 @@ import 'xterm/css/xterm.css' // import 'lib-flexible/flexible' import '@/styles/index.scss' // global css +import '@/assets/less/news/news.less' import globalMixin from '@/mixin/globalMixin'; // 替换为实际的文件路径 diff --git a/f/web-kboss/src/router/index.js b/f/web-kboss/src/router/index.js index 0af589b..8e21726 100644 --- a/f/web-kboss/src/router/index.js +++ b/f/web-kboss/src/router/index.js @@ -1,6 +1,9 @@ import Vue from 'vue' import Router from 'vue-router' import store from '@/store' +import { scheduleHomePageLayoutReset, resetHomePageLayout } from '@/utils/resetHomePageLayout' + +const HOME_ROUTE_RE = /^\/(homePage|ncmatchHome)(\/|$)/ /* Layout */ import Layout from '@/layout' import GpuProduct from '@/views/product/productHome/capitalOnline/productItem/GpuProduct/index.vue' @@ -2618,10 +2621,18 @@ const router = createRouter() // 在beforeRouteLeave导航守卫中清空面包屑状态 router.beforeEach((to, from, next) => { - // 清空面包屑状态的代码 - // store.commit('tagsView/resetBreadcrumbState'); + if (HOME_ROUTE_RE.test(to.path) || HOME_ROUTE_RE.test(from.path)) { + resetHomePageLayout() + } next() }) + +router.afterEach((to) => { + if (!HOME_ROUTE_RE.test(to.path)) return + scheduleHomePageLayoutReset() + window.setTimeout(() => scheduleHomePageLayoutReset(), 900) +}) + window.addEventListener('beforeunload', function() { // 清空面包屑状态的代码 store.commit('tagsView/resetBreadcrumbState') diff --git a/f/web-kboss/src/styles/home-page-shell.scss b/f/web-kboss/src/styles/home-page-shell.scss new file mode 100644 index 0000000..f53027a --- /dev/null +++ b/f/web-kboss/src/styles/home-page-shell.scss @@ -0,0 +1,140 @@ +// 官网 shell:html/body 不滚动,仅 #homeOut 内部纵向滚动,彻底避免 SPA 跳转后 scrollLeft 残留 + +html.home-page-shell-active, +body.home-page-shell-active { + width: 100% !important; + max-width: 100% !important; + height: 100% !important; + overflow: hidden !important; + margin: 0 !important; + padding: 0 !important; +} + +html.home-page-shell-active #app, +body.home-page-shell-active #app { + width: 100% !important; + max-width: 100% !important; + min-width: 0 !important; + height: 100% !important; + overflow: hidden !important; +} + +.home-page-shell { + display: flex; + flex-direction: column; + width: 100%; + max-width: 100%; + min-width: 0; + height: 100vh; + height: 100dvh; + overflow: hidden; + position: relative; + isolation: isolate; +} + +.home-page-shell > #topBox, +.home-page-shell > #topBox.top-nav, +#topBox.top-nav { + flex: 0 0 auto; + min-width: 0 !important; + max-width: 100% !important; + width: 100% !important; +} + +.home-page-shell #homeOut { + flex: 1 1 auto; + width: 100% !important; + max-width: 100% !important; + min-width: 0 !important; + min-height: 0 !important; + overflow-x: hidden !important; + overflow-y: auto !important; + overscroll-behavior-x: none; + margin: 0 !important; + padding: 0 !important; +} + +.home-page-shell .home-route-stage, +.home-page-shell .home-router-view { + width: 100% !important; + max-width: 100% !important; + min-width: 0 !important; + overflow-x: hidden !important; + box-sizing: border-box; +} + +.home-page-shell .home-router-view > * { + width: 100%; + max-width: 100%; + min-width: 0; + box-sizing: border-box; +} + +.home-page-shell .train-page, +.home-page-shell .agent-store-page, +.home-page-shell .jd-homepage, +.home-page-shell .product-service-page, +.home-page-shell .news-view-page, +.home-page-shell .about-page, +.home-page-shell .home-main-page { + overflow-x: hidden; +} + +.home-page-shell .about-page, +.home-page-shell .about-container { + width: 100%; + max-width: 100%; + min-width: 0; + box-sizing: border-box; +} + +.home-page-shell .grid-bg { + width: 100% !important; + max-width: 100% !important; + margin-left: 0 !important; + margin-right: 0 !important; +} + +.home-page-shell .product-service-page.single-product-page { + height: auto !important; + min-height: calc(100vh - 82px); + overflow-y: visible !important; + overflow-x: hidden !important; +} + +.home-page-shell .nav-container { + max-width: 100%; +} + +.home-page-shell .news-shell { + width: 100%; + max-width: 1400px; + margin-left: auto; + margin-right: auto; + box-sizing: border-box; +} + +.home-page-shell .news-featured-inner { + display: grid !important; + grid-template-columns: minmax(280px, 380px) minmax(0, 1fr); + align-items: stretch; + width: 100%; + min-height: 280px; +} + +.home-page-shell .news-featured-body { + width: 100%; + min-width: 0; +} + +.home-page-shell .news-featured, +.home-page-shell .news-item { + width: 100%; + max-width: 100%; +} + +.home-page-shell .footer { + width: 100%; + max-width: 100%; + box-sizing: border-box; +} diff --git a/f/web-kboss/src/utils/resetHomePageLayout.js b/f/web-kboss/src/utils/resetHomePageLayout.js new file mode 100644 index 0000000..4295f12 --- /dev/null +++ b/f/web-kboss/src/utils/resetHomePageLayout.js @@ -0,0 +1,182 @@ +const HOME_SHELL_CLASS = 'home-page-shell-active' +const RESET_TARGETS = [ + '.home-page-shell', + '#homeOut', + '.home-route-stage', + '.home-router-view' +] + +let scrollLockBound = false +let homeOutObserver = null + +function attachHomeOutScrollListener() { + const homeOut = getHomeOut() + if (!homeOut || homeOut.dataset.scrollLockBound === '1') return + homeOut.dataset.scrollLockBound = '1' + homeOut.addEventListener('scroll', lockHomeOutHorizontalScroll, { passive: true }) +} + +export function enableHomePageBodyScroll() { + document.documentElement.classList.add(HOME_SHELL_CLASS) + document.body.classList.add(HOME_SHELL_CLASS) + bindHomeOutScrollLock() + bindHomeOutResizeObserver() + attachHomeOutScrollListener() +} + +export function disableHomePageBodyScroll() { + document.documentElement.classList.remove(HOME_SHELL_CLASS) + document.body.classList.remove(HOME_SHELL_CLASS) + if (homeOutObserver) { + homeOutObserver.disconnect() + homeOutObserver = null + } +} + +function getHomeOut() { + return document.getElementById('homeOut') +} + +function getHomeScroller() { + return getHomeOut() || document.documentElement +} + +function clearInlineLayoutStyles(element) { + if (!element || !element.style) return + element.style.removeProperty('width') + element.style.removeProperty('max-width') + element.style.removeProperty('min-width') + element.style.removeProperty('transform') + element.style.removeProperty('margin-left') + element.style.removeProperty('left') +} + +function resetElementScroll(element, resetVertical = true) { + if (!element) return + element.scrollLeft = 0 + if (resetVertical) { + element.scrollTop = 0 + } +} + +function resetScrollableDescendants(root) { + if (!root || !root.querySelectorAll) return + root.querySelectorAll('*').forEach((element) => { + if (element.scrollLeft) { + element.scrollLeft = 0 + } + }) +} + +function lockHomeOutHorizontalScroll() { + const homeOut = getHomeOut() + if (!homeOut) return + + if (homeOut.scrollLeft !== 0) { + homeOut.scrollLeft = 0 + } + + resetElementScroll(document.documentElement, false) + resetElementScroll(document.body, false) + + if (window.scrollX !== 0) { + window.scrollTo(0, 0) + } +} + +export function resetHomePageLayout(resetVertical = true) { + const homeOut = getHomeOut() + + RESET_TARGETS.forEach((selector) => { + document.querySelectorAll(selector).forEach((element) => { + resetElementScroll(element, resetVertical) + clearInlineLayoutStyles(element) + }) + }) + + if (homeOut) { + resetElementScroll(homeOut, resetVertical) + clearInlineLayoutStyles(homeOut) + resetScrollableDescendants(homeOut) + } + + resetElementScroll(document.documentElement, resetVertical) + resetElementScroll(document.body, resetVertical) + window.scrollTo(0, 0) + lockHomeOutHorizontalScroll() +} + +export function scheduleHomePageLayoutReset(resetVertical = true) { + attachHomeOutScrollListener() + resetHomePageLayout(resetVertical) + window.requestAnimationFrame(() => resetHomePageLayout(resetVertical)) + window.setTimeout(() => resetHomePageLayout(resetVertical), 0) + window.setTimeout(() => resetHomePageLayout(resetVertical), 80) + window.setTimeout(() => resetHomePageLayout(resetVertical), 200) + window.setTimeout(() => resetHomePageLayout(resetVertical), 500) + window.setTimeout(() => resetHomePageLayout(resetVertical), 900) +} + +export function scrollHomeSection(id, offset = 82) { + const homeOut = getHomeOut() + const element = document.getElementById(id) + if (!element) return false + + lockHomeOutHorizontalScroll() + + if (homeOut) { + const top = element.getBoundingClientRect().top - homeOut.getBoundingClientRect().top + homeOut.scrollTop - offset + homeOut.scrollTo({ + left: 0, + top: Math.max(top, 0), + behavior: 'smooth' + }) + return true + } + + const top = element.getBoundingClientRect().top + window.pageYOffset - offset + window.scrollTo({ + left: 0, + top: Math.max(top, 0), + behavior: 'smooth' + }) + return true +} + +export function bindHomeOutScrollLock() { + if (scrollLockBound) return + scrollLockBound = true + + document.addEventListener('scroll', (event) => { + if (!document.body.classList.contains(HOME_SHELL_CLASS)) return + if (event.target === getHomeOut()) { + lockHomeOutHorizontalScroll() + } + }, true) + + window.addEventListener('resize', () => scheduleHomePageLayoutReset(true), { passive: true }) +} + +export function bindHomeOutResizeObserver() { + if (homeOutObserver || typeof ResizeObserver === 'undefined') return + + homeOutObserver = new ResizeObserver(() => { + if (!document.body.classList.contains(HOME_SHELL_CLASS)) return + lockHomeOutHorizontalScroll() + }) + + const observe = () => { + const homeOut = getHomeOut() + if (homeOut) homeOutObserver.observe(homeOut) + } + + observe() + window.setTimeout(observe, 0) +} + +export const bindHomeHorizontalScrollLock = bindHomeOutScrollLock +export const bindHomeOutHorizontalScrollLock = bindHomeOutScrollLock + +export function getHomeScrollContainer() { + return getHomeScroller() +} diff --git a/f/web-kboss/src/views/LoginDialog/LoginDialog.vue b/f/web-kboss/src/views/LoginDialog/LoginDialog.vue index ec5920c..707e64e 100644 --- a/f/web-kboss/src/views/LoginDialog/LoginDialog.vue +++ b/f/web-kboss/src/views/LoginDialog/LoginDialog.vue @@ -13,31 +13,31 @@
-

{{ activeTab === 'login' ? '欢迎登录' : '创建账号' }}

+

{{ activeTab === 'login' ? $t('loginDialog.welcomeLogin') : $t('loginDialog.createAccount') }}

- - + +
- - + +