From 1dd4fa3f41aaef8abc2025f106cfe7ae1ba75225 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=8E=8B=E5=AE=8F=E8=B1=AA?= <2443753184@qq.com>
Date: Thu, 3 Sep 2026 18:57:47 +0800
Subject: [PATCH] =?UTF-8?q?feat(home):=20=E5=AE=9E=E7=8E=B0=E6=B8=B8?=
=?UTF-8?q?=E5=AE=A2=E6=A8=A1=E5=BC=8F=E4=B8=8E=E7=99=BB=E5=BD=95=E6=B5=81?=
=?UTF-8?q?=E7=A8=8B=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 添加游客模式,展示公共内容无需强制登录
- 实现游客模块展示打卡、计划、关于我们等功能介绍
- 添加产品介绍页面显示学习成长工具详情
- 优化登录流程,添加用户协议和隐私政策同意选项
- 更新角色标签将老师改为管理员,学员改为成员
- 添加注销账号功能替代退出登录
- 实现webview页面域名白名单安全验证
- 添加隐私政策和用户协议页面
- 优化页面跳转逻辑和错误提示信息
- 统一项目名称从明缘进阶场改为明缘云道场
---
app.json | 35 ++++++--
pages/checkin/checkin.wxml | 2 +-
pages/home/home.js | 99 +++++++++++++++++++++--
pages/home/home.wxml | 17 +++-
pages/home/home.wxss | 52 ++++++++++++
pages/plan-submit/plan-submit.js | 3 +-
pages/plan/plan.js | 3 +-
pages/privacy/privacy.js | 18 +++++
pages/privacy/privacy.json | 4 +
pages/privacy/privacy.wxml | 133 +++++++++++++++++++++++++++++++
pages/privacy/privacy.wxss | 40 ++++++++++
pages/profile/profile.js | 78 +++++++++++++-----
pages/profile/profile.wxml | 22 +++--
pages/profile/profile.wxss | 47 ++++++++++-
pages/webview/webview.js | 47 ++++++++++-
pages/webview/webview.wxml | 9 ++-
pages/webview/webview.wxss | 30 +++++++
project.config.json | 2 +-
sitemap.json | 2 +-
utils/auth.js | 2 +-
20 files changed, 588 insertions(+), 57 deletions(-)
create mode 100644 pages/privacy/privacy.js
create mode 100644 pages/privacy/privacy.json
create mode 100644 pages/privacy/privacy.wxml
create mode 100644 pages/privacy/privacy.wxss
diff --git a/app.json b/app.json
index c95aaf4..fa5e273 100644
--- a/app.json
+++ b/app.json
@@ -5,12 +5,13 @@
"pages/plan/plan",
"pages/plan-submit/plan-submit",
"pages/profile/profile",
- "pages/webview/webview"
+ "pages/webview/webview",
+ "pages/privacy/privacy"
],
"window": {
"navigationBarBackgroundColor": "#2C1810",
"navigationBarTextStyle": "white",
- "navigationBarTitleText": "明缘进阶场",
+ "navigationBarTitleText": "明缘云道场",
"backgroundColor": "#FDFBF7",
"backgroundTextStyle": "dark"
},
@@ -20,11 +21,31 @@
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
- { "pagePath": "pages/home/home", "text": "首页", "iconPath": "assets/tabbar/home.png", "selectedIconPath": "assets/tabbar/home-active.png" },
- { "pagePath": "pages/checkin/checkin", "text": "打卡", "iconPath": "assets/tabbar/checkin.png", "selectedIconPath": "assets/tabbar/checkin-active.png" },
- { "pagePath": "pages/plan/plan", "text": "计划", "iconPath": "assets/tabbar/plan.png", "selectedIconPath": "assets/tabbar/plan-active.png" },
- { "pagePath": "pages/profile/profile", "text": "我的", "iconPath": "assets/tabbar/profile.png", "selectedIconPath": "assets/tabbar/profile-active.png" }
+ {
+ "pagePath": "pages/home/home",
+ "text": "首页",
+ "iconPath": "assets/tabbar/home.png",
+ "selectedIconPath": "assets/tabbar/home-active.png"
+ },
+ {
+ "pagePath": "pages/checkin/checkin",
+ "text": "打卡",
+ "iconPath": "assets/tabbar/checkin.png",
+ "selectedIconPath": "assets/tabbar/checkin-active.png"
+ },
+ {
+ "pagePath": "pages/plan/plan",
+ "text": "计划",
+ "iconPath": "assets/tabbar/plan.png",
+ "selectedIconPath": "assets/tabbar/plan-active.png"
+ },
+ {
+ "pagePath": "pages/profile/profile",
+ "text": "我的",
+ "iconPath": "assets/tabbar/profile.png",
+ "selectedIconPath": "assets/tabbar/profile-active.png"
+ }
]
},
"sitemapLocation": "sitemap.json"
-}
\ No newline at end of file
+}
diff --git a/pages/checkin/checkin.wxml b/pages/checkin/checkin.wxml
index a40fa6d..6e121e9 100644
--- a/pages/checkin/checkin.wxml
+++ b/pages/checkin/checkin.wxml
@@ -72,7 +72,7 @@
👥
- 暂无小组,请联系老师分配
+ 暂无小组,请联系管理员分配
📭
diff --git a/pages/home/home.js b/pages/home/home.js
index 7dc3dc0..83f08eb 100644
--- a/pages/home/home.js
+++ b/pages/home/home.js
@@ -16,6 +16,7 @@ Page({
displayName: '',
encouragement: '',
modules: [],
+ introData: null,
loading: true,
error: '',
skeletonItems: [0, 1, 2, 3, 4, 5, 6, 7, 8]
@@ -27,12 +28,32 @@ Page({
if (!silent) {
this.setData({ loading: true, error: '' });
}
+ const token = auth.getToken();
+ if (!token) {
+ // 游客模式:展示公开内容,不强制登录
+ this.setData({
+ loading: false,
+ error: '',
+ greeting: '欢迎来到明缘云道场',
+ displayName: '游客',
+ encouragement: '登录后即可打卡、提交计划',
+ modules: this.getGuestModules(),
+ introData: this.getIntroData()
+ });
+ return Promise.resolve();
+ }
return auth.ensureLogin()
.then((token) => {
if (!token) {
- // 新用户未绑定手机号,引导去「我的」完成绑定,避免无 token 请求受保护接口导致 401
- this.setData({ loading: false, error: '请先完成微信绑定后再进入' });
- setTimeout(() => wx.switchTab({ url: '/pages/profile/profile' }), 500);
+ this.setData({
+ loading: false,
+ error: '',
+ greeting: '欢迎来到明缘云道场',
+ displayName: '游客',
+ encouragement: '登录后即可打卡、提交计划',
+ modules: this.getGuestModules(),
+ introData: this.getIntroData()
+ });
return;
}
return api.request({ url: '/api/v1/pages/home' });
@@ -45,7 +66,8 @@ Page({
greeting: res.greeting || '',
displayName: res.display_name || '',
encouragement: res.encouragement || '',
- modules: (res.modules || []).filter((m) => m.visible)
+ modules: (res.modules || []).filter((m) => m.visible),
+ introData: null
});
})
.catch((err) => {
@@ -53,6 +75,42 @@ Page({
});
},
+ getGuestModules() {
+ return [
+ { id: 'checkin', icon: '📋', label: '打卡介绍', desc: '每日打卡记录', visible: true, url: '', guest: true },
+ { id: 'plan', icon: '📝', label: '计划介绍', desc: '周/月/年计划', visible: true, url: '', guest: true },
+ { id: 'about', icon: 'ℹ️', label: '关于我们', desc: '了解明缘云道场', visible: true, url: '', guest: true }
+ ];
+ },
+
+ getIntroData() {
+ return {
+ title: '产品介绍',
+ sections: [
+ {
+ icon: '📚',
+ heading: '学习成长工具',
+ text: '明缘云道场是一款专注于个人成长的效率工具,通过每周打卡与计划管理,帮助你养成良好的学习习惯,实现持续进步。好好学习,天天向上。'
+ },
+ {
+ icon: '✅',
+ heading: '周打卡',
+ text: '每周打卡,支持多种状态记录(正常、迟到、请假、早退、不参加讨论等)。查看小组打卡情况,与同学们互相监督、共同进步。'
+ },
+ {
+ icon: '📝',
+ heading: '计划管理',
+ text: '提供周计划、月计划、年计划三级管理,支持文字与图片上传。清晰追踪每个周期的目标完成情况,让成长有迹可循。'
+ },
+ {
+ icon: '👥',
+ heading: '小组共学',
+ text: '加入学习小组,查看组员的打卡与计划完成情况。在集体的氛围中保持学习动力,与志同道合的伙伴一起成长。'
+ }
+ ]
+ };
+ },
+
onPullDownRefresh() {
this.loadHome(true).then(() => {
wx.stopPullDownRefresh();
@@ -63,12 +121,37 @@ Page({
this.loadHome();
},
+ goLogin() {
+ wx.switchTab({ url: '/pages/profile/profile' });
+ },
+
onModuleTap(e) {
const url = e.currentTarget.dataset.url;
- if (!url) return;
const token = auth.getToken();
- const sep = url.indexOf('?') >= 0 ? '&' : '?';
- const target = url + sep + 'token=' + encodeURIComponent(token);
- wx.navigateTo({ url: '/pages/webview/webview?url=' + encodeURIComponent(target) });
+ // 游客模式:引导登录
+ if (!token) {
+ wx.showModal({
+ title: '登录提示',
+ content: '登录后使用此功能,是否前往登录?',
+ confirmText: '去登录',
+ confirmColor: '#C67B30',
+ success: (res) => {
+ if (res.confirm) {
+ wx.switchTab({ url: '/pages/profile/profile' });
+ }
+ }
+ });
+ return;
+ }
+ if (!url) return;
+
+ // 通过 webview redirect 接口:后端验证 token 后设置 HttpOnly cookie,再 302 到目标页
+ // H5 页面内的同域请求会自动携带 cookie,H5 端零改动
+ const redirectUrl = api.BASE_URL + '/api/v1/webview/redirect'
+ + '?token=' + encodeURIComponent(token)
+ + '&target=' + encodeURIComponent(url);
+ wx.navigateTo({ url: '/pages/webview/webview?url=' + encodeURIComponent(redirectUrl) });
}
});
+
+
diff --git a/pages/home/home.wxml b/pages/home/home.wxml
index 15b9a71..9caca05 100644
--- a/pages/home/home.wxml
+++ b/pages/home/home.wxml
@@ -15,6 +15,9 @@
{{greeting}}
{{displayName || '欢迎回来'}}
{{encouragement}}
+
+ 登录账号解锁完整功能 ›
+
@@ -37,6 +40,18 @@
+
+
+ {{introData.title}}
+
+ {{item.icon}}
+
+ {{item.heading}}
+ {{item.text}}
+
+
+
+
暂无功能入口
-
\ No newline at end of file
+
diff --git a/pages/home/home.wxss b/pages/home/home.wxss
index df47d66..183c863 100644
--- a/pages/home/home.wxss
+++ b/pages/home/home.wxss
@@ -153,4 +153,56 @@
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
+}
+.hero-login-tip {
+ margin-top: 24rpx;
+ display: inline-block;
+ padding: 12rpx 28rpx;
+ background: rgba(198, 123, 48, 0.25);
+ border: 1rpx solid rgba(227, 179, 124, 0.4);
+ border-radius: 999rpx;
+ color: #E3B37C;
+ font-size: 24rpx;
+}
+/* ---- intro section ---- */
+.intro-section {
+ margin-top: 40rpx;
+}
+.intro-title {
+ font-size: 32rpx;
+ font-weight: 700;
+ color: #2C1810;
+ margin-bottom: 20rpx;
+ padding-left: 4rpx;
+}
+.intro-card {
+ display: flex;
+ align-items: flex-start;
+ background: #fff;
+ border-radius: 16rpx;
+ padding: 28rpx 24rpx;
+ margin-bottom: 16rpx;
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.03);
+}
+.intro-icon {
+ font-size: 40rpx;
+ margin-right: 20rpx;
+ flex-shrink: 0;
+ line-height: 1;
+ padding-top: 2rpx;
+}
+.intro-body {
+ flex: 1;
+ min-width: 0;
+}
+.intro-heading {
+ font-size: 28rpx;
+ font-weight: 700;
+ color: #C67B30;
+ margin-bottom: 10rpx;
+}
+.intro-text {
+ font-size: 25rpx;
+ color: #5A4A3A;
+ line-height: 1.8;
}
\ No newline at end of file
diff --git a/pages/plan-submit/plan-submit.js b/pages/plan-submit/plan-submit.js
index 7880aa8..ec949d7 100644
--- a/pages/plan-submit/plan-submit.js
+++ b/pages/plan-submit/plan-submit.js
@@ -5,7 +5,6 @@ const MAX_IMAGES = 4;
const MAX_IMAGE_SIZE = 1024 * 1024; // 超过 1MB 才压缩
const COMPRESS_LEVELS = [80, 60, 45]; // 逐级降低质量,直到满足大小限制
const ALLOWED_IMAGE_EXT = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
-const IMAGE_PLACEHOLDER_URL = 'https://picsum.photos/200/200';
const TYPE_LABELS = { weekly: '周计划', monthly: '月计划', yearly: '年计划' };
function errDetail(err) {
@@ -136,7 +135,7 @@ Page({
if (/^https?:\/\//i.test(path)) return path;
const parts = String(path).replace(/^attachments\//, '').split('/');
if (parts.length < 4) {
- return IMAGE_PLACEHOLDER_URL;
+ return '';
}
return api.STATIC_BASE_URL + '/clock/static/plan/' + parts.slice(0, 4).map(encodeURIComponent).join('/');
},
diff --git a/pages/plan/plan.js b/pages/plan/plan.js
index 606b28a..09fb809 100644
--- a/pages/plan/plan.js
+++ b/pages/plan/plan.js
@@ -27,7 +27,8 @@ Page({
onShow() {
auth.ensureLogin().then((token) => {
if (!token) {
- wx.switchTab({ url: '/pages/profile/profile' });
+ wx.showToast({ title: '请先登录', icon: 'none' });
+ setTimeout(() => wx.switchTab({ url: '/pages/profile/profile' }), 500);
return;
}
wx.removeStorageSync('plan_overview_dirty');
diff --git a/pages/privacy/privacy.js b/pages/privacy/privacy.js
new file mode 100644
index 0000000..46ee0a5
--- /dev/null
+++ b/pages/privacy/privacy.js
@@ -0,0 +1,18 @@
+const TITLES = {
+ privacy: '隐私政策',
+ agreement: '用户协议'
+};
+
+Page({
+ data: {
+ type: 'privacy',
+ title: '隐私政策'
+ },
+
+ onLoad(options) {
+ const type = options.type || 'privacy';
+ const title = TITLES[type] || '隐私政策';
+ this.setData({ type, title });
+ wx.setNavigationBarTitle({ title });
+ }
+});
diff --git a/pages/privacy/privacy.json b/pages/privacy/privacy.json
new file mode 100644
index 0000000..66faf26
--- /dev/null
+++ b/pages/privacy/privacy.json
@@ -0,0 +1,4 @@
+{
+ "navigationBarTitleText": "隐私政策",
+ "usingComponents": {}
+}
diff --git a/pages/privacy/privacy.wxml b/pages/privacy/privacy.wxml
new file mode 100644
index 0000000..4da95fe
--- /dev/null
+++ b/pages/privacy/privacy.wxml
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+ 一、信息收集范围
+
+ 为了向你提供打卡、计划管理等服务,我们会收集以下信息:
+
+ 1. 手机号:用于账号注册与登录,验证你的身份;
+ 2. 头像与昵称:用于个人资料展示;
+ 3. 你主动提交的打卡记录、计划内容及附件图片;
+ 4. 设备信息与日志数据:用于排查故障、优化服务。
+
+
+
+ 二、信息使用目的
+ 我们收集的信息仅用于以下目的:
+ 1. 提供打卡、计划管理、小组统计等核心功能;
+ 2. 账号安全验证与异常登录保护;
+ 3. 改进产品体验与服务质量。
+
+
+
+ 三、信息存储与安全
+
+ 你的个人信息存储于境内服务器,我们采取合理的技术措施保护你的信息安全,包括加密传输、访问控制等。
+
+
+
+
+ 四、第三方共享
+
+ 我们不会向第三方出售或出租你的个人信息。仅在以下情况下可能共享:
+
+ 1. 获得你的明确同意;
+ 2. 法律法规要求或司法机关依法定程序要求;
+ 3. 为完成服务所必需的合作方(如云存储服务),且签订了保密协议。
+
+
+
+ 五、你的权利
+ 你有权访问、更正、删除你的个人信息,以及注销账号。你可以通过以下方式行使权利:
+ 1. 在「我的」页面中查看和修改个人资料;
+ 2. 在「我的」页面底部申请注销账号;
+ 3. 联系客服协助处理。
+
+
+
+ 六、未成年人保护
+
+ 若你是未满 14 周岁的未成年人,请在监护人陪同下阅读本政策,并在监护人同意的情况下使用我们的服务。
+
+
+
+
+ 七、联系方式
+ 如有任何疑问或投诉,请通过以下方式联系我们:
+ 客服邮箱:[此处填写客服邮箱]
+
+
+
+ 八、政策更新
+
+ 我们可能会适时更新本隐私政策,更新后的政策将在本页面公布。重大变更会通过小程序内通知等方式告知你。
+
+
+
+
+
+
+
+ 一、服务说明
+
+ 明缘云道场小程序(以下简称"本小程序")为用户提供打卡记录、计划管理、小组统计等学习辅助服务。使用本小程序即表示你同意本协议的全部条款。
+
+
+
+
+ 二、账号注册与使用
+ 1. 你需通过手机号验证注册账号,并确保所提供信息真实准确;
+ 2. 你应妥善保管账号信息,对账号下的所有行为负责;
+ 3. 如发现账号异常,请及时联系客服处理。
+
+
+
+ 三、用户行为规范
+ 你在使用本服务时,不得从事以下行为:
+ 1. 发布违法、违规、侵犯他人权益的内容;
+ 2. 恶意刷量、作弊、伪造打卡记录;
+ 3. 干扰或破坏本服务的正常运行;
+ 4. 未经授权访问他人账号或数据。
+
+
+
+ 四、内容与知识产权
+
+ 你上传的内容(包括文字、图片等)的知识产权归你所有。你授予本小程序为提供服务所必需的使用权限。
+
+
+
+
+ 五、服务变更与终止
+
+ 我们可能根据业务需要调整或终止部分服务,并会提前通知用户。如因你违反本协议,我们有权暂停或终止对你的服务。
+
+
+
+
+ 六、免责声明
+
+ 因不可抗力、系统故障、网络原因等不可归责于我方的事由导致服务中断或数据丢失的,我们不承担责任,但会尽力协助恢复。
+
+
+
+
+ 七、协议修改
+
+ 我们可能根据需要修改本协议,修改后的协议将在本页面公布。继续使用服务即视为同意修改后的协议。
+
+
+
+
+ 八、联系方式
+ 如有疑问,请联系客服:
+ 客服邮箱:[此处填写客服邮箱]
+
+
+
+
+
+
diff --git a/pages/privacy/privacy.wxss b/pages/privacy/privacy.wxss
new file mode 100644
index 0000000..9df7c19
--- /dev/null
+++ b/pages/privacy/privacy.wxss
@@ -0,0 +1,40 @@
+.page {
+ min-height: 100vh;
+ background: #FDFBF7;
+ box-sizing: border-box;
+}
+
+.content {
+ height: 100vh;
+ padding: 32rpx;
+ box-sizing: border-box;
+}
+
+.section {
+ background: #fff;
+ border-radius: 16rpx;
+ padding: 28rpx 24rpx;
+ margin-bottom: 20rpx;
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.03);
+}
+
+.section-title {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #2C1810;
+ margin-bottom: 16rpx;
+}
+
+.section-text {
+ font-size: 26rpx;
+ color: #5A4A3A;
+ line-height: 1.8;
+ margin-bottom: 8rpx;
+}
+
+.footer {
+ text-align: center;
+ color: #B6A996;
+ font-size: 22rpx;
+ padding: 40rpx 0 60rpx;
+}
diff --git a/pages/profile/profile.js b/pages/profile/profile.js
index 83b9d5c..55e2f69 100644
--- a/pages/profile/profile.js
+++ b/pages/profile/profile.js
@@ -2,15 +2,15 @@ const api = require('../../utils/api');
const auth = require('../../utils/auth');
const ROLE_LABELS = {
- student: '学员',
+ student: '成员',
member: '成员',
- teacher: '老师',
+ teacher: '管理员',
leader: '组长',
'group_leader': '组长',
admin: '管理员'
};
const LOGIN_TYPE_LABELS = {
- wechat: '微信',
+ wechat: '微信授权',
phone: '手机号',
admin: '管理员'
};
@@ -27,11 +27,15 @@ Page({
roleLabel: '',
loginTypeLabel: '',
classGroups: [],
- avatarUploading: false
+ avatarUploading: false,
+ privacyAgreed: false
},
onShow() {
- this.setData({ phoneError: '' });
+ this.setData({
+ phoneError: '',
+ privacyAgreed: !!wx.getStorageSync('privacy_agreed')
+ });
this.loadPage();
},
@@ -114,16 +118,17 @@ Page({
showPhoneLogin() {
this.setData({
view: 'phoneLogin',
- phoneLoading: false
+ phoneLoading: false,
+ privacyAgreed: !!wx.getStorageSync('privacy_agreed')
});
},
roleLabel(role) {
- return ROLE_LABELS[role] || role || '学员';
+ return ROLE_LABELS[role] || role || '成员';
},
loginTypeLabel(type) {
- return LOGIN_TYPE_LABELS[type] || type || '微信';
+ return LOGIN_TYPE_LABELS[type] || type || '手机号';
},
fullUrl(rel) {
@@ -138,7 +143,6 @@ Page({
onChooseAvatar(e) {
const path = e.detail && e.detail.avatarUrl;
- console.log('[avatar] chooseAvatar ->', path);
if (!path) {
wx.showToast({ title: '未选择头像', icon: 'none' });
return;
@@ -150,7 +154,6 @@ Page({
name: 'file',
header: { Authorization: 'Bearer ' + auth.getToken() },
success: (res) => {
- console.log('[avatar] upload success', res.statusCode, res.data);
let data = {};
try {
data = JSON.parse(res.data);
@@ -170,8 +173,6 @@ Page({
}
},
fail: (err) => {
- console.error('[avatar] upload fail', err);
- console.error('[avatar] filePath', path);
wx.showToast({ title: '上传失败', icon: 'none' });
},
complete: () => {
@@ -184,6 +185,10 @@ Page({
if (this.data.phoneLoading) {
return;
}
+ if (!this.data.privacyAgreed) {
+ wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none', duration: 2000 });
+ return;
+ }
const phoneCode = e.detail && e.detail.code;
if (!phoneCode) {
const message = '未授权手机号,请点击上方按钮重试';
@@ -205,19 +210,48 @@ Page({
this.loadPage();
},
- logout() {
+ togglePrivacy() {
+ const agreed = !this.data.privacyAgreed;
+ this.setData({ privacyAgreed: agreed });
+ if (agreed) {
+ wx.setStorageSync('privacy_agreed', true);
+ } else {
+ wx.removeStorageSync('privacy_agreed');
+ }
+ },
+
+ openPrivacy(e) {
+ const type = e.currentTarget.dataset.type || 'privacy';
+ wx.navigateTo({ url: '/pages/privacy/privacy?type=' + type });
+ },
+
+ deleteAccount() {
wx.showModal({
- title: '退出登录',
- content: '确定要退出当前账号吗?',
- confirmText: '退出',
+ title: '注销账号',
+ content: '确定要注销账号吗?注销后将清除本机登录信息,需要重新登录。',
+ confirmText: '注销',
confirmColor: '#c0392b',
success: (res) => {
- if (!res.confirm) {
- return;
- }
- api.request({ url: '/api/v1/auth/logout', method: 'POST' }).catch(() => {});
- auth.clearToken();
- wx.reLaunch({ url: '/pages/home/home' });
+ if (!res.confirm) return;
+ wx.showModal({
+ title: '再次确认',
+ content: '注销后本机登录状态将被清除,你可以使用手机号重新登录。确定继续吗?',
+ confirmText: '确认注销',
+ confirmColor: '#c0392b',
+ success: (res2) => {
+ if (!res2.confirm) return;
+ // 仅清除前端登录信息
+ try {
+ api.request({ url: '/api/v1/auth/logout', method: 'POST' }).catch(() => {});
+ } catch (e) {}
+ auth.clearToken();
+ wx.removeStorageSync('privacy_agreed');
+ wx.showToast({ title: '已注销', icon: 'success' });
+ setTimeout(() => {
+ wx.reLaunch({ url: '/pages/home/home' });
+ }, 1000);
+ }
+ });
}
});
}
diff --git a/pages/profile/profile.wxml b/pages/profile/profile.wxml
index e2c0798..1d187c1 100644
--- a/pages/profile/profile.wxml
+++ b/pages/profile/profile.wxml
@@ -20,8 +20,8 @@
👤
- 微信手机号一键登录
- 未找到你的账号,请使用微信手机号登录。手机号仅用于账号绑定,不会公开展示。
+ 手机号快捷登录
+ 未找到你的账号,请使用手机号登录。手机号仅用于账号绑定,不会公开展示。
+ >{{phoneLoading ? '登录中...' : '手机号快捷登录'}}
+
+
+ ✓
+
+
+ 我已阅读并同意
+ 《用户协议》
+ 和
+ 《隐私政策》
+
+
{{phoneError}}
@@ -91,7 +102,7 @@
- 班级分组
+ 小组分组
{{item.period || item.class_code}}
{{item.group}} · {{item.role}}
@@ -99,7 +110,8 @@
-
+
+
\ No newline at end of file
diff --git a/pages/profile/profile.wxss b/pages/profile/profile.wxss
index d7ccdfa..50e15ec 100644
--- a/pages/profile/profile.wxss
+++ b/pages/profile/profile.wxss
@@ -186,9 +186,52 @@ button::after { border: none; }
margin-top: 48rpx;
padding-top: 24rpx;
}
-.btn-logout {
+/* ---- privacy row ---- */
+.privacy-row {
+ display: flex;
+ align-items: flex-start;
+ margin-top: 28rpx;
+ text-align: left;
+}
+.checkbox {
+ width: 32rpx;
+ height: 32rpx;
+ border: 2rpx solid #D8C7B4;
+ border-radius: 6rpx;
+ margin-right: 14rpx;
+ margin-top: 2rpx;
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #fff;
+}
+.checkbox.checked {
+ background: #C67B30;
+ border-color: #C67B30;
+}
+.check-icon {
+ color: #fff;
+ font-size: 22rpx;
+ line-height: 1;
+ font-weight: 700;
+}
+.privacy-text {
+ flex: 1;
+ font-size: 24rpx;
+ color: #8B7A6A;
+ line-height: 1.6;
+}
+.privacy-text .link {
+ color: #C67B30;
+}
+
+/* ---- delete account ---- */
+.btn-delete {
background: #fff;
color: #c0392b;
border: 1rpx solid #f0b4ae;
border-radius: 12rpx;
-}
\ No newline at end of file
+ margin-bottom: 20rpx;
+}
+/* ---- profile name edit ---- */
diff --git a/pages/webview/webview.js b/pages/webview/webview.js
index 2cc3ba1..19347f9 100644
--- a/pages/webview/webview.js
+++ b/pages/webview/webview.js
@@ -1,8 +1,47 @@
+const api = require('../../utils/api');
+
+// 允许加载的域名白名单
+const ALLOWED_HOSTS = ['m.muguaclub.cn', 'muguaclub.cn'];
+
+function isAllowedUrl(url) {
+ if (!url) return false;
+ try {
+ // 简单解析 hostname
+ const match = url.match(/^https?:\/\/([^/:?#]+)/i);
+ if (!match) return false;
+ const host = match[1].toLowerCase();
+ return ALLOWED_HOSTS.some((h) => host === h || host.endsWith('.' + h));
+ } catch (e) {
+ return false;
+ }
+}
+
Page({
- data: { url: '' },
+ data: {
+ url: '',
+ invalid: false
+ },
onLoad(options) {
- if (options.url) {
- this.setData({ url: decodeURIComponent(options.url) });
+ if (!options.url) {
+ this.setData({ invalid: true });
+ return;
+ }
+ const url = decodeURIComponent(options.url);
+ if (!isAllowedUrl(url)) {
+ console.warn('[webview] blocked url:', url);
+ this.setData({ invalid: true, url: '' });
+ return;
+ }
+ this.setData({ url, invalid: false });
+ },
+
+ onRetry() {
+ if (this.data.url) {
+ // 触发重新加载
+ this.setData({ url: '' });
+ setTimeout(() => {
+ this.setData({ url: this.data._url || '' });
+ }, 50);
}
}
-});
\ No newline at end of file
+});
diff --git a/pages/webview/webview.wxml b/pages/webview/webview.wxml
index 4839609..d3329f6 100644
--- a/pages/webview/webview.wxml
+++ b/pages/webview/webview.wxml
@@ -1 +1,8 @@
-
\ No newline at end of file
+
+
+
+ !
+ 无法加载该页面
+ 该页面不在允许访问的域名范围内
+
+
diff --git a/pages/webview/webview.wxss b/pages/webview/webview.wxss
index e69de29..53b1c58 100644
--- a/pages/webview/webview.wxss
+++ b/pages/webview/webview.wxss
@@ -0,0 +1,30 @@
+.page {
+ min-height: 100vh;
+ background: #FDFBF7;
+}
+
+.error-page {
+ padding-top: 200rpx;
+ text-align: center;
+}
+.error-icon {
+ width: 120rpx;
+ height: 120rpx;
+ line-height: 120rpx;
+ margin: 0 auto 32rpx;
+ border-radius: 50%;
+ background: #fdecea;
+ color: #c0392b;
+ font-size: 64rpx;
+ font-weight: 700;
+}
+.error-title {
+ color: #2C1810;
+ font-size: 32rpx;
+ font-weight: 700;
+ margin-bottom: 16rpx;
+}
+.error-desc {
+ color: #8B7A6A;
+ font-size: 26rpx;
+}
diff --git a/project.config.json b/project.config.json
index ac3e7f3..e5dff91 100644
--- a/project.config.json
+++ b/project.config.json
@@ -1,5 +1,5 @@
{
- "description": "明缘进阶场",
+ "description": "明缘云道场",
"packOptions": {
"ignore": []
},
diff --git a/sitemap.json b/sitemap.json
index 726488b..5652cad 100644
--- a/sitemap.json
+++ b/sitemap.json
@@ -1,5 +1,5 @@
{
- "desc": "明缘进阶场小程序",
+ "desc": "明缘云道场小程序",
"rules": [
{ "action": "allow", "page": "*" }
]
diff --git a/utils/auth.js b/utils/auth.js
index ff2c615..4deb415 100644
--- a/utils/auth.js
+++ b/utils/auth.js
@@ -22,7 +22,7 @@ function wxLogin(retries) {
if (res && res.code) {
resolve(res.code);
} else {
- reject(new Error((res && res.errMsg) || '微信登录失败'));
+ reject(new Error((res && res.errMsg) || '登录失败'));
}
},
fail: reject