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 @@
-
-
-
-
-
-
- Pro
- ¥19.9/月
- 推荐
+
+
+
-
- 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 }}
+
+
+
-
-
+
+
+ 权益对比
+
+
+
+ {{ 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 维度 - 邮箱验证