From 5ac33dcd7fbe512bd2ccbafb1cda64d444a02ffe Mon Sep 17 00:00:00 2001 From: Yuzhiran Dev Date: Sun, 12 Jul 2026 17:43:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8D=8F=E8=AE=AE=E5=8B=BE=E9=80=89?= =?UTF-8?q?=E6=8E=A7=E5=88=B6+news=E8=AF=A6=E6=83=85=E9=A1=B5=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E4=BF=AE=E5=A4=8D+=E6=94=AF=E4=BB=98=E9=A1=B5?= =?UTF-8?q?=E9=87=8D=E5=81=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/index/index.vue | 3 +- client/src/pages/login/login.vue | 8 + client/src/pages/news/news.vue | 29 +- client/src/pages/payment/payment.vue | 494 ++++++++++++++++----------- server/src/utils/mail.js | 4 +- 5 files changed, 325 insertions(+), 213 deletions(-) diff --git a/client/src/pages/index/index.vue b/client/src/pages/index/index.vue index 5457a59..b1bc84f 100644 --- a/client/src/pages/index/index.vue +++ b/client/src/pages/index/index.vue @@ -148,7 +148,8 @@ function onNotify() { } function goNewsDetail(item) { - uni.switchTab({ url: '/pages/trend/trend' }) + uni.setStorageSync('__news_item__', JSON.stringify(item)) + uni.navigateTo({ url: '/pages/news/news' }) } diff --git a/client/src/pages/login/login.vue b/client/src/pages/login/login.vue index 172ac93..baf27fc 100644 --- a/client/src/pages/login/login.vue +++ b/client/src/pages/login/login.vue @@ -133,6 +133,10 @@ const BASE_URL = 'https://wdkj.yuzhiran.com.cn' /** 发送邮箱验证码 */ async function handleSendCode() { + if (!agreed.value) { + uni.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' }) + return + } const email = registerForm.value.email if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { uni.showToast({ title: '请先输入正确的邮箱', icon: 'none' }) @@ -170,6 +174,10 @@ async function handleSendCode() { } const wechatLogin = async () => { + if (!loginAgreed.value) { + uni.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' }) + return + } try { const loginRes = await new Promise((resolve, reject) => { uni.login({ success: resolve, fail: reject }) diff --git a/client/src/pages/news/news.vue b/client/src/pages/news/news.vue index d6605d0..c370f90 100644 --- a/client/src/pages/news/news.vue +++ b/client/src/pages/news/news.vue @@ -198,7 +198,7 @@ onMounted(() => { .nav-back { font-size: 28px; - color: #fff; + color: var(--text-primary); padding: 0 8px; line-height: 1; } @@ -209,7 +209,7 @@ onMounted(() => { color: var(--text-primary); } -.nav-share { font-size: 22px; color: rgba(255,255,255,0.5); } +.nav-share { font-size: 22px; color: var(--text-muted); } .content { flex: 1; @@ -218,18 +218,19 @@ onMounted(() => { // Hero .news-hero { - height: 180px; + height: 160px; display: flex; align-items: center; justify-content: center; border-radius: 0 0 24px 24px; + margin: 0 20px; } -.hero-emoji { font-size: 72px; } +.hero-emoji { font-size: 64px; } // Category .category-tag { - margin: 24px 20px 0; + margin: 20px 20px 0; } .tag-text { @@ -270,19 +271,19 @@ onMounted(() => { .meta-label { font-size: 11px; - color: rgba(255,255,255,0.35); + color: var(--text-tertiary); } .meta-label.hot { font-size: 13px; } -.meta-value { font-size: 12px; color: rgba(255,255,255,0.7); } +.meta-value { font-size: 12px; color: var(--text-secondary); } // Summary .summary-card { margin: 0 20px 20px; padding: 16px; - background: linear-gradient(135deg, rgba(179,136,255,0.08), rgba(77,208,225,0.05)); - border: 1px solid rgba(179,136,255,0.12); + background: linear-gradient(135deg, rgba(99,102,241,0.06), rgba(0,188,212,0.04)); + border: 1px solid rgba(99,102,241,0.1); border-radius: 12px; } @@ -297,7 +298,7 @@ onMounted(() => { .summary-text { font-size: 14px; line-height: 1.7; - color: rgba(255,255,255,0.85); + color: var(--text-primary); } // Body @@ -305,7 +306,7 @@ onMounted(() => { margin: 0 20px 20px; font-size: 14px; line-height: 1.8; - color: rgba(255,255,255,0.7); + color: var(--text-secondary); } // Related tags @@ -316,7 +317,7 @@ onMounted(() => { .related-label { display: block; font-size: 12px; - color: rgba(255,255,255,0.4); + color: var(--text-tertiary); margin-bottom: 10px; } @@ -329,7 +330,7 @@ onMounted(() => { border-radius: 20px; } -.tag-text { font-size: 12px; color: rgba(255,255,255,0.6); } +.tag-item .tag-text { font-size: 12px; color: var(--text-secondary); } // Action bar .action-bar { @@ -351,7 +352,7 @@ onMounted(() => { } .action-icon { font-size: 18px; } -.action-text { font-size: 13px; color: rgba(255,255,255,0.7); } +.action-text { font-size: 13px; color: var(--text-secondary); } .footer-spacer { height: 60px; } diff --git a/client/src/pages/payment/payment.vue b/client/src/pages/payment/payment.vue index 02dd338..dc2d586 100644 --- a/client/src/pages/payment/payment.vue +++ b/client/src/pages/payment/payment.vue @@ -9,72 +9,111 @@ - - - 解锁 AI 维度 Pro - 无限 AI 问答 · 全量知识解锁 · 每日趋势优先推送 - - - - - - Pro - ¥19.9/月 - 推荐 + + + + + + + 解锁 AI 维度 Pro + 无限 AI 问答 · 全量知识 · 趋势优先推送 - - VIP - ¥39.9/月 - 含 Pro 全部权益 - - - - - - {{ item.icon }} - {{ item.text }} - - - - - - 选择套餐 - + + - {{ item.label }} - ¥{{ item.price }} - 省 {{ item.save }} + + Pro + 推荐 + + ¥19.9 + / 月 + + ✓ AI 问答无限次 + ✓ 全量知识解锁 + ✓ 收藏无限容量 + + + + + VIP + 尊享 + + ¥39.9 + / 月 + + ✓ 含 Pro 全部权益 + ✓ 专属客服支持 + ✓ 专属会员标识 + - - - - - - 点击支付即同意《用户协议》和《隐私政策》 - - + + + 选择套餐 + + + {{ item.label }} + ¥{{ item.price }} + 省 {{ item.save }} + + + - - 如有问题请联系客服 · 支持 7 天无理由退款 + + + 权益对比 + + + + {{ item.icon }} + {{ item.text }} + + + + {{ item.proOnly ? 'Pro' : (item.hasPro ? 'Pro+VIP' : 'VIP') }} + + + + + + + + + + + 点击支付即表示同意《用户协议》和《隐私政策》 + + + + + @@ -85,32 +124,28 @@ import { useUserStore } from '@/stores/user' const userStore = useUserStore() -// 方案 const selectedPlan = ref('pro') - -// 套餐时长 -const durations = ref([ - { key: 'pro-monthly', label: 'Pro 月付', price: 19.9 }, - { key: 'pro-quarterly', label: 'Pro 季付', price: 49.9, save: '省 ¥10' }, - { key: 'vip-monthly', label: 'VIP 月付', price: 39.9 }, - { key: 'vip-quarterly', label: 'VIP 季付', price: 99.9, save: '省 ¥20' } -]) - const selectedDuration = ref('pro-monthly') -// 权益 -const benefits = ref([ - { icon: '🤖', text: 'AI 问答无限次' }, - { icon: '📚', text: '全量知识内容解锁' }, - { icon: '📡', text: '每日趋势优先推送' }, - { icon: '⭐', text: '收藏夹无限容量' }, - { icon: '🎁', text: '专属会员标识' }, - { icon: '💬', text: '专属客服支持' } +const durationOptions = computed(() => { + const isPro = selectedPlan.value === 'pro' + return [ + { key: isPro ? 'pro-monthly' : 'vip-monthly', label: '月付', price: isPro ? 19.9 : 39.9 }, + { key: isPro ? 'pro-quarterly' : 'vip-quarterly', label: '季付', price: isPro ? 49.9 : 99.9, save: isPro ? '¥10' : '¥20' } + ] +}) + +const benefitList = ref([ + { icon: '🤖', text: 'AI 问答无限次', proOnly: true, hasPro: true }, + { icon: '📚', text: '全量知识内容解锁', proOnly: true, hasPro: true }, + { icon: '📡', text: '每日趋势优先推送', proOnly: true, hasPro: true }, + { icon: '⭐', text: '收藏夹无限容量', proOnly: true, hasPro: true }, + { icon: '💬', text: '专属客服支持', proOnly: false, hasPro: false }, + { icon: '🎁', text: '专属会员标识', proOnly: false, hasPro: false } ]) -// 当前价格 const currentPrice = computed(() => { - const item = durations.value.find(d => d.key === selectedDuration.value) + const item = durationOptions.value.find(d => d.key === selectedDuration.value) return item ? item.price : 19.9 }) @@ -122,24 +157,14 @@ async function handlePay() { return } - // 找到对应的 productId - const productMap = { - 'pro-monthly': 'pro-monthly', - 'pro-quarterly': 'pro-quarterly', - 'vip-monthly': 'vip-monthly', - 'vip-quarterly': 'vip-quarterly' - } + const productId = selectedDuration.value loading.value = true try { - // 调用后端创建订单 - const data = await paymentApi.createOrder(productMap[selectedDuration.value], userStore.token) - - // 获取微信支付参数 + const data = await paymentApi.createOrder(productId, userStore.token) const payParam = data.payParams || data.wechatParam || data.paymentData if (payParam) { - // 调起微信支付 uni.requestPayment({ provider: 'wxpay', timeStamp: payParam.timeStamp || payParam.timestamp, @@ -154,7 +179,7 @@ async function handlePay() { }, 1500) }, fail: (err) => { - if (err.errMsg.includes('cancel')) { + if (err.errMsg && err.errMsg.includes('cancel')) { uni.showToast({ title: '已取消支付', icon: 'none' }) } else { uni.showToast({ title: '支付失败,请重试', icon: 'none' }) @@ -179,19 +204,20 @@ function goBack() { +.footer-spacer { height: 40px; } + \ No newline at end of file diff --git a/server/src/utils/mail.js b/server/src/utils/mail.js index 5cd539d..953d4a0 100644 --- a/server/src/utils/mail.js +++ b/server/src/utils/mail.js @@ -39,9 +39,9 @@ async function sendVerificationCode(to, code) { } try { await transport.sendMail({ - from: `"AI维度" <${SMTP_FROM}>`, + from: `"宇之然AI维度" <${SMTP_FROM}>`, to, - subject: '【AI维度】邮箱验证码', + subject: '【宇之然AI维度】邮箱验证码', html: `

AI 维度 - 邮箱验证