diff --git a/.gitignore b/.gitignore index 6cf45412..e3a8bcae 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,5 @@ soul-api/soul-api-new # 从宝塔拉取的线上运行目录镜像(含 .env / 二进制,勿提交) _server_live/ Cunkebao +soul-admin/dist +new-soul diff --git a/new-soul/miniprogram/.gitignore b/new-soul/miniprogram/.gitignore deleted file mode 100644 index 14ea590c..00000000 --- a/new-soul/miniprogram/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# Windows -[Dd]esktop.ini -Thumbs.db -$RECYCLE.BIN/ - -# macOS -.DS_Store -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes - -# Node.js -node_modules/ diff --git a/new-soul/miniprogram/README.md b/new-soul/miniprogram/README.md deleted file mode 100644 index 2cc11dbf..00000000 --- a/new-soul/miniprogram/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# Soul创业实验 - 微信小程序 - -> 一场SOUL的创业实验场 - 来自Soul派对房的真实商业故事 - -## 📱 项目简介 - -本项目是《一场SOUL的创业实验场》的微信小程序版本,完整还原了Web端的所有UI界面和功能。 - -## 🎨 设计特点 - -- **主题色**: Soul青色 (#00CED1) -- **设计风格**: 深色主题 + 毛玻璃效果 -- **1:1还原**: 完全复刻Web端的UI设计 - -## 📂 项目结构 - -``` -miniprogram/ -├── app.js # 应用入口 -├── app.json # 应用配置 -├── app.wxss # 全局样式 -├── custom-tab-bar/ # 自定义TabBar组件 -│ ├── index.js -│ ├── index.json -│ ├── index.wxml -│ └── index.wxss -├── pages/ -│ ├── index/ # 首页 -│ ├── chapters/ # 目录页 -│ ├── match/ # 找伙伴页 -│ ├── my/ # 我的页面 -│ ├── read/ # 阅读页 -│ ├── about/ # 关于作者 -│ ├── referral/ # 推广中心 -│ ├── purchases/ # 订单页 -│ └── settings/ # 设置页 -├── utils/ -│ ├── util.js # 工具函数 -│ └── payment.js # 支付工具 -├── assets/ -│ └── icons/ # 图标资源 -├── project.config.json # 项目配置 -└── sitemap.json # 站点地图 -``` - -## 🚀 功能列表 - -### 核心功能 -- ✅ 首页 - 书籍展示、推荐章节、阅读进度 -- ✅ 目录 - 完整章节列表、篇章折叠展开 -- ✅ 找伙伴 - 匹配动画、匹配类型选择 -- ✅ 我的 - 个人信息、订单、推广中心 -- ✅ 阅读 - 付费墙、章节导航、分享功能 - -### 特色功能 -- ✅ 自定义TabBar(中间突出的找伙伴按钮) -- ✅ 阅读进度条 -- ✅ 匹配动画效果 -- ✅ 付费墙与购买流程 -- ✅ 分享海报功能 -- ✅ 推广佣金系统 - -## 🛠 开发指南 - -### 环境要求 -- 微信开发者工具 >= 1.06.2308310 -- 基础库版本 >= 3.3.4 - -### 快速开始 - -1. **下载微信开发者工具** - - 前往 [微信开发者工具下载页面](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html) - -2. **导入项目** - - 打开微信开发者工具 - - 选择"导入项目" - - 项目目录选择 `miniprogram` 文件夹 - - AppID 使用: `wx432c93e275548671` - -3. **编译运行** - - 点击"编译"按钮 - - 在模拟器中预览效果 - -### 真机调试 - -1. 点击工具栏的"预览"按钮 -2. 使用微信扫描二维码 -3. 在真机上测试所有功能 - -## 📝 配置说明 - -### API配置 -在 `app.js` 中修改 `globalData.baseUrl`: - -```javascript -globalData: { - baseUrl: 'https://soul.ckb.fit', // 你的API地址 - // ... -} -``` - -### AppID配置 -在 `project.config.json` 中修改: - -```json -{ - "appid": "你的小程序AppID" -} -``` - -## 🎯 上线发布 - -1. **准备工作** - - 确保所有功能测试通过 - - 检查API接口是否正常 - - 确认支付功能已配置 - -2. **上传代码** - - 在开发者工具中点击"上传" - - 填写版本号和项目备注 - -3. **提交审核** - - 登录[微信公众平台](https://mp.weixin.qq.com) - - 进入"版本管理" - - 提交审核 - -4. **发布上线** - - 审核通过后点击"发布" - -## 🔗 相关链接 - -- **Web版本**: https://soul.ckb.fit -- **作者微信**: 28533368 -- **技术支持**: 存客宝 - -## 📄 版权信息 - -© 2024 卡若. All rights reserved. diff --git a/new-soul/miniprogram/RESTORE-ANALYSIS.md b/new-soul/miniprogram/RESTORE-ANALYSIS.md deleted file mode 100644 index 558a31ff..00000000 --- a/new-soul/miniprogram/RESTORE-ANALYSIS.md +++ /dev/null @@ -1,67 +0,0 @@ -# miniprogram 功能还原分析报告 - -## 一、对比结论 - -| 项目 | miniprogram(甲方) | miniprogram2(你写的) | -|------|-------------------|------------------------| -| 页面分享 | 仅 read、referral 有 | 几乎所有页面都有 | -| scene 解析 | 无 | 有 utils/scene.js | -| 推荐码获取 | 分散(userInfo?.referralCode 等) | 统一 app.getMyReferralCode() | -| 书籍 API | /api/book/all-chapters | /api/miniprogram/book/all-chapters | -| 特有页面 | vip、member-detail | scan、profile-edit | - -## 二、已完成的还原项 - -### 1. 基础能力(app.js + utils/scene.js) - -- **新增** `utils/scene.js`:扫码 scene 参数编解码,支持 `mid`、`id`、`ref` -- **app.js**: - - 引入 `parseScene`,`handleReferralCode` 支持 `options.scene` 解析 - - 新增 `getMyReferralCode()`:统一获取邀请码 - - 新增 `getSectionMid(sectionId)`:根据 id 查 mid - - `loadBookData` 改为 `/api/miniprogram/book/all-chapters` - -### 2. 页面分享(onShareAppMessage) - -已为以下页面补充分享,路径统一带 `ref` 参数: - -- index、chapters、match、my -- read、referral(原有,已统一用 getMyReferralCode) -- search、settings、purchases、privacy -- withdraw-records、addresses、addresses/edit -- agreement、about、vip、member-detail - -### 3. read.js 分享逻辑与 mid 支持 - -- 使用 `app.getMyReferralCode()` 替代 `userInfo?.referralCode || wx.getStorageSync('referralCode')` -- **mid 支持**:onLoad 支持 `options.scene`、`options.mid`;mid 有值无 id 时从 bookData 或 `/api/miniprogram/book/chapter/by-mid/:mid` 解析 id -- 分享 path 优先用 `mid=`(扫码/海报闭环),无则用 `id=`;API 返回 `res.mid` 时写入 `sectionMid` - -### 4. API 路径修正 - -- `app.loadBookData`:`/api/book/all-chapters` → `/api/miniprogram/book/all-chapters` -- `index.loadBookData`、`loadFeaturedFromServer`、`loadLatestChapters`:同上 -- `chapters.loadDailyChapters`:同上 -- **VIP 接口**:`/api/vip/*` → `/api/miniprogram/vip/*`(vip.js、my.js、index.js、member-detail.js) - -## 三、已处理项 - -- **vip 相关接口**:已改为 `/api/miniprogram/vip/*`(members、status、profile),符合项目边界。**后端需在 soul-api 的 miniprogram 组下挂对应路由**,可复用现有 handler。 -- **页面结构**:保留 vip、member-detail,未引入 scan、profile-edit - -## 四、后端已补全(soul-api) - -已在 miniprogram 组下新增以下路由: - -| 路径 | 方法 | 用途 | -|------|------|------| -| `/api/miniprogram/vip/status` | GET | 查询用户 VIP 状态(按 fullbook/vip 订单判断) | -| `/api/miniprogram/vip/profile` | GET/POST | 获取/更新 VIP 资料(映射 users 表 nickname/phone) | -| `/api/miniprogram/vip/members` | GET | VIP 会员列表(无 id)或单个(?id=) | -| `/api/miniprogram/users` | GET | 用户列表(?limit=)或单个(?id=),首页超级个体、会员详情回退 | - -## 五、后续建议 - -1. **soul-api 路由**:确认 `/api/miniprogram/book/all-chapters` 已注册;VIP 接口见「四、后端待办」。 -2. **referral.js**:已统一使用 `app.getMyReferralCode()` 作为回退。 -3. **read.js mid 支持**:已完成。若 soul-api 未提供 `/api/miniprogram/book/chapter/by-mid/:mid`,扫码带 mid 时需依赖 bookData 已加载完成;建议后端补充 by-mid 接口。 diff --git a/new-soul/miniprogram/app.js b/new-soul/miniprogram/app.js deleted file mode 100644 index e6522742..00000000 --- a/new-soul/miniprogram/app.js +++ /dev/null @@ -1,750 +0,0 @@ -/** - * Soul创业派对 - 小程序入口 - * 开发: 卡若 - */ - -const { parseScene } = require('./utils/scene.js') - -const DEFAULT_BASE_URL = 'https://soulapi.quwanzhi.com' -const DEFAULT_APP_ID = 'wxb8bbb2b10dec74aa' -const DEFAULT_MCH_ID = '1318592501' -const DEFAULT_WITHDRAW_TMPL_ID = 'u3MbZGPRkrZIk-I7QdpwzFxnO_CeQPaCWF2FkiIablE' - -function getRuntimeBootstrapConfig() { - try { - const extCfg = wx.getExtConfigSync ? (wx.getExtConfigSync() || {}) : {} - return { - baseUrl: extCfg.apiBaseUrl || wx.getStorageSync('apiBaseUrl') || DEFAULT_BASE_URL, - appId: extCfg.appId || DEFAULT_APP_ID, - mchId: extCfg.mchId || DEFAULT_MCH_ID, - withdrawSubscribeTmplId: extCfg.withdrawSubscribeTmplId || DEFAULT_WITHDRAW_TMPL_ID - } - } catch (_) { - return { - baseUrl: DEFAULT_BASE_URL, - appId: DEFAULT_APP_ID, - mchId: DEFAULT_MCH_ID, - withdrawSubscribeTmplId: DEFAULT_WITHDRAW_TMPL_ID - } - } -} - -const bootstrapConfig = getRuntimeBootstrapConfig() - -App({ - globalData: { - // 运行配置:优先外部配置/缓存,其次默认值 - baseUrl: bootstrapConfig.baseUrl, - appId: bootstrapConfig.appId, - - // 订阅消息:用户点击「申请提现」→「立即提现」时会先弹出订阅授权窗 - withdrawSubscribeTmplId: bootstrapConfig.withdrawSubscribeTmplId, - - // 微信支付配置 - mchId: bootstrapConfig.mchId, - - // 用户信息 - userInfo: null, - openId: null, // 微信openId,支付必需 - isLoggedIn: false, - - // 书籍数据 - bookData: null, - totalSections: 0, - supportWechat: '', - - // 购买记录 - purchasedSections: [], - hasFullBook: false, - // VIP 会员(365天,包含增值版免费;与 hasFullBook=9.9 买断不同) - isVip: false, - vipExpireDate: '', - - // 已读章节(仅统计有权限打开过的章节,用于首页「已读/待读」) - readSectionIds: [], - - // 推荐绑定 - pendingReferralCode: null, // 待绑定的推荐码 - - // 主题配置 - theme: { - brandColor: '#00CED1', - brandSecondary: '#20B2AA', - goldColor: '#FFD700', - bgColor: '#000000', - cardBg: '#1c1c1e' - }, - - // 系统信息 - systemInfo: null, - statusBarHeight: 44, - navBarHeight: 88, - - // TabBar相关 - currentTab: 0, - - // 是否处于「单页模式」(如朋友圈文章里的单页预览) - // 用于在受限环境下给出引导文案,提示用户点击底部「前往小程序」进入完整体验 - isSinglePageMode: false, - - // 更新检测:上次检测时间戳,避免频繁请求 - lastUpdateCheck: 0 - }, - - onLaunch(options) { - this.globalData.readSectionIds = wx.getStorageSync('readSectionIds') || [] - // 获取系统信息 - this.getSystemInfo() - - // 场景值兜底:1154 为「朋友圈单页模式」进入 - try { - const launchOpts = wx.getLaunchOptionsSync ? wx.getLaunchOptionsSync() : null - if (launchOpts && launchOpts.scene === 1154) { - this.globalData.isSinglePageMode = true - } - } catch (e) { - console.warn('[App] 读取 LaunchOptions 失败:', e) - } - - // 检查登录状态 - this.checkLoginStatus() - this.loadRuntimeConfig() - - // 加载书籍数据 - this.loadBookData() - - // 检查更新 - this.checkUpdate() - - // 处理分享参数(推荐码绑定) - this.handleReferralCode(options) - }, - - // 小程序显示时:处理分享参数、检测更新(从后台切回时) - onShow(options) { - this.handleReferralCode(options) - this.checkUpdate() - }, - - // 处理推荐码绑定:官方以 options.scene 接收扫码参数(可同时带 mid/id + ref),与 utils/scene 解析闭环 - handleReferralCode(options) { - const query = options?.query || {} - let refCode = query.ref || query.referralCode - const sceneStr = (options && (typeof options.scene === 'string' ? options.scene : '')) || '' - if (sceneStr) { - const parsed = parseScene(sceneStr) - if (parsed.mid) this.globalData.initialSectionMid = parsed.mid - if (parsed.id) this.globalData.initialSectionId = parsed.id - if (parsed.ref) refCode = parsed.ref - } - if (refCode) { - console.log('[App] 检测到推荐码:', refCode) - - // 立即记录访问(不需要登录,用于统计"通过链接进的人数") - this.recordReferralVisit(refCode) - - // 保存待绑定的推荐码(不再在前端做"只能绑定一次"的限制,让后端根据30天规则判断续期/抢夺) - this.globalData.pendingReferralCode = refCode - wx.setStorageSync('pendingReferralCode', refCode) - // 同步写入 referral_code,供章节/找伙伴支付时传给后端,订单会记录 referrer_id 与 referral_code - wx.setStorageSync('referral_code', refCode) - - // 如果已登录,立即尝试绑定,由 /api/miniprogram/referral/bind 按 30 天规则决定 new / renew / takeover - if (this.globalData.isLoggedIn && this.globalData.userInfo) { - this.bindReferralCode(refCode) - } - } - }, - - // 记录推荐访问(不需要登录,用于统计) - async recordReferralVisit(refCode) { - try { - // 获取openId(如果有) - const openId = this.globalData.openId || wx.getStorageSync('openId') || '' - const userId = this.globalData.userInfo?.id || '' - - await this.request('/api/miniprogram/referral/visit', { - method: 'POST', - data: { - referralCode: refCode, - visitorOpenId: openId, - visitorId: userId, - source: 'miniprogram', - page: getCurrentPages()[getCurrentPages().length - 1]?.route || '' - }, - silent: true - }) - console.log('[App] 记录推荐访问成功') - } catch (e) { - console.log('[App] 记录推荐访问失败:', e.message) - // 忽略错误,不影响用户体验 - } - }, - - // 绑定推荐码到用户(自己的推荐码不请求接口,避免 400 与控制台报错) - async bindReferralCode(refCode) { - try { - const userId = this.globalData.userInfo?.id - if (!userId || !refCode) return - - const myCode = this.getMyReferralCode() - if (myCode && this._normalizeReferralCode(refCode) === this._normalizeReferralCode(myCode)) { - console.log('[App] 跳过绑定:不能使用自己的推荐码') - this.globalData.pendingReferralCode = null - wx.removeStorageSync('pendingReferralCode') - return - } - - console.log('[App] 绑定推荐码:', refCode, '到用户:', userId) - - const res = await this.request('/api/miniprogram/referral/bind', { - method: 'POST', - data: { - userId, - referralCode: refCode - }, - silent: true - }) - - if (res.success) { - console.log('[App] 推荐码绑定成功') - wx.setStorageSync('boundReferralCode', refCode) - this.globalData.pendingReferralCode = null - wx.removeStorageSync('pendingReferralCode') - } - } catch (e) { - const msg = (e && e.message) ? String(e.message) : '' - if (msg.indexOf('不能使用自己的推荐码') !== -1) { - console.log('[App] 跳过绑定:不能使用自己的推荐码') - this.globalData.pendingReferralCode = null - wx.removeStorageSync('pendingReferralCode') - } else { - console.error('[App] 绑定推荐码失败:', e) - } - } - }, - - // 推荐码归一化后比较(忽略大小写、短横线等) - _normalizeReferralCode(code) { - if (!code || typeof code !== 'string') return '' - return code.replace(/[\s\-_]/g, '').toUpperCase().trim() - }, - - // 判断用户资料是否完善(昵称 + 头像) - _isProfileIncomplete(user) { - if (!user) return true - const nickname = (user.nickname || '').trim() - const avatar = (user.avatar || '').trim() - const isDefaultNickname = !nickname || nickname === '微信用户' - const noAvatar = !avatar - return isDefaultNickname || noAvatar - }, - - // 登录后若资料未完善,引导跳转到资料编辑页 - _ensureProfileCompletedAfterLogin(user) { - try { - if (!user || !this._isProfileIncomplete(user)) return - const pages = getCurrentPages() - const current = pages[pages.length - 1] - // 避免在资料页内重复跳转 - if (current && current.route === 'pages/profile-edit/profile-edit') return - wx.showToast({ title: '请先完善头像和昵称', icon: 'none', duration: 2000 }) - wx.navigateTo({ url: '/pages/profile-edit/profile-edit' }) - } catch (e) { - console.warn('[App] 跳转资料编辑页失败:', e) - } - }, - - // 根据业务 id 从 bookData 查 mid(用于跳转) - getSectionMid(sectionId) { - const list = this.globalData.bookData || [] - const ch = list.find(c => c.id === sectionId) - return ch?.mid || 0 - }, - - // 获取当前用户的邀请码(用于分享带 ref,未登录返回空字符串) - getMyReferralCode() { - const user = this.globalData.userInfo - if (!user) return '' - if (user.referralCode) return user.referralCode - if (user.id) return 'SOUL' + String(user.id).toUpperCase().slice(-6) - return '' - }, - - /** - * 自定义导航栏「返回」:有上一页则返回,否则跳转首页(解决从分享进入时点返回无效的问题) - */ - goBackOrToHome() { - const pages = getCurrentPages() - if (pages.length <= 1) { - wx.switchTab({ url: '/pages/index/index' }) - } else { - wx.navigateBack() - } - }, - - // 获取系统信息 - getSystemInfo() { - try { - const systemInfo = wx.getSystemInfoSync() - this.globalData.systemInfo = systemInfo - this.globalData.statusBarHeight = systemInfo.statusBarHeight || 44 - - // 微信在单页模式下会在 systemInfo.mode 标记 singlePage - if (systemInfo.mode === 'singlePage') { - this.globalData.isSinglePageMode = true - } - - // 计算导航栏高度 - const menuButton = wx.getMenuButtonBoundingClientRect() - if (menuButton) { - this.globalData.navBarHeight = (menuButton.top - systemInfo.statusBarHeight) * 2 + menuButton.height + systemInfo.statusBarHeight - } - } catch (e) { - console.error('获取系统信息失败:', e) - } - }, - - /** - * 若当前处于朋友圈等「单页模式」,在尝试登录/购买前给用户友好提示, - * 引导用户点击底部「前往小程序」进入完整小程序再操作。 - * 返回 false 表示应中断当前操作。 - */ - ensureFullAppForAuth() { - // 每次调用时再做一次兜底检测,避免全局标记遗漏 - try { - const sys = wx.getSystemInfoSync() - if (sys && sys.mode === 'singlePage') { - this.globalData.isSinglePageMode = true - } - } catch (e) { - console.warn('[App] ensureFullAppForAuth getSystemInfoSync error:', e) - } - - if (!this.globalData.isSinglePageMode) return true - - wx.showModal({ - title: '请前往完整小程序', - content: '当前为朋友圈单页,仅支持部分浏览。如需登录和解锁内容,请点击底部「前往小程序」后再操作。', - showCancel: false, - confirmText: '我知道了', - }) - return false - }, - - // 检查登录状态 - checkLoginStatus() { - try { - const userInfo = wx.getStorageSync('userInfo') - const token = wx.getStorageSync('token') - - if (userInfo && token) { - this.globalData.userInfo = userInfo - this.globalData.isLoggedIn = true - this.globalData.purchasedSections = userInfo.purchasedSections || [] - this.globalData.hasFullBook = userInfo.hasFullBook || false - this.globalData.isVip = userInfo.isVip || false - this.globalData.vipExpireDate = userInfo.vipExpireDate || '' - } - } catch (e) { - console.error('检查登录状态失败:', e) - } - }, - - async loadRuntimeConfig() { - try { - const res = await this.request({ url: '/api/miniprogram/config', silent: true, timeout: 5000 }) - const mpConfig = res?.mpConfig || {} - this.globalData.baseUrl = mpConfig.apiDomain || this.globalData.baseUrl - this.globalData.appId = mpConfig.appId || this.globalData.appId - this.globalData.mchId = mpConfig.mchId || this.globalData.mchId - this.globalData.withdrawSubscribeTmplId = mpConfig.withdrawSubscribeTmplId || this.globalData.withdrawSubscribeTmplId - this.globalData.supportWechat = mpConfig.supportWechat || mpConfig.customerWechat || mpConfig.serviceWechat || '' - try { - wx.setStorageSync('apiBaseUrl', this.globalData.baseUrl) - } catch (_) {} - } catch (e) { - console.warn('[App] 加载运行配置失败,继续使用默认配置:', e) - } - }, - - // 加载书籍数据 - async loadBookData() { - try { - // 先从缓存加载 - const cachedData = wx.getStorageSync('bookData') - if (cachedData) { - this.globalData.bookData = cachedData - } - - // 从服务器获取最新数据 - const res = await this.request('/api/miniprogram/book/all-chapters') - if (res && (res.data || res.chapters)) { - const chapters = res.data || res.chapters || [] - this.globalData.bookData = chapters - this.globalData.totalSections = res.total || chapters.length || 0 - wx.setStorageSync('bookData', chapters) - } - } catch (e) { - console.error('加载书籍数据失败:', e) - } - }, - - /** - * 小程序更新检测(基于 wx.getUpdateManager) - * - 启动时检测;从后台切回前台时也检测(间隔至少 5 分钟,避免频繁请求) - */ - checkUpdate() { - try { - if (!wx.canIUse('getUpdateManager')) return - const now = Date.now() - const lastCheck = this.globalData.lastUpdateCheck || 0 - if (lastCheck && now - lastCheck < 5 * 60 * 1000) return // 5 分钟内不重复检测 - this.globalData.lastUpdateCheck = now - - const updateManager = wx.getUpdateManager() - updateManager.onCheckForUpdate((res) => { - if (res.hasUpdate) { - console.log('[App] 发现新版本,正在下载...') - } - }) - updateManager.onUpdateReady(() => { - wx.showModal({ - title: '更新提示', - content: '新版本已准备好,重启后即可使用', - confirmText: '立即重启', - cancelText: '稍后', - success: (res) => { - if (res.confirm) { - updateManager.applyUpdate() - } - } - }) - }) - updateManager.onUpdateFailed(() => { - wx.showToast({ - title: '更新失败,请稍后重试', - icon: 'none', - duration: 2500 - }) - }) - } catch (e) { - console.warn('[App] checkUpdate failed:', e) - } - }, - - /** - * 从 soul-api 返回体中取错误提示文案(兼容 message / error 字段) - */ - _getApiErrorMsg(data, defaultMsg = '请求失败') { - if (!data || typeof data !== 'object') return defaultMsg - const msg = data.message || data.error - return (msg && String(msg).trim()) ? String(msg).trim() : defaultMsg - }, - - /** - * 统一请求方法。接口失败时会弹窗提示(与 soul-api 返回的 message/error 一致)。 - * @param {string|object} urlOrOptions - 接口路径,或 { url, method, data, header, silent } - * @param {object} options - { method, data, header, silent } - * @param {boolean} options.silent - 为 true 时不弹窗,仅 reject(用于静默请求如访问统计) - */ - request(urlOrOptions, options = {}) { - let url - if (typeof urlOrOptions === 'string') { - url = urlOrOptions - } else if (urlOrOptions && typeof urlOrOptions === 'object' && urlOrOptions.url) { - url = urlOrOptions.url - options = { ...urlOrOptions, url: undefined } - } else { - url = '' - } - const silent = !!options.silent - const showError = (msg) => { - if (!silent && msg) { - wx.showToast({ title: msg, icon: 'none', duration: 2500 }) - } - } - - return new Promise((resolve, reject) => { - const token = wx.getStorageSync('token') - - wx.request({ - url: this.globalData.baseUrl + url, - method: options.method || 'GET', - data: options.data || {}, - timeout: options.timeout || 15000, - header: { - 'Content-Type': 'application/json', - 'Authorization': token ? `Bearer ${token}` : '', - ...options.header - }, - success: (res) => { - const data = res.data - if (res.statusCode === 200) { - // 业务失败:success === false,soul-api 用 message 或 error 返回原因 - if (data && data.success === false) { - const msg = this._getApiErrorMsg(data, '操作失败') - // 登录态不一致:本地有 token/userInfo,但后端查不到该用户 - // 典型原因:切换环境(baseUrl)、换库/清库、用户被删除、token 与用户不匹配 - if (msg && (msg.includes('用户不存在') || msg.toLowerCase().includes('user not found'))) { - this.logout() - } - showError(msg) - reject(new Error(msg)) - return - } - resolve(data) - return - } - if (res.statusCode === 401) { - this.logout() - showError('未授权,请重新登录') - reject(new Error('未授权')) - return - } - // 4xx/5xx:优先用返回体的 message/error - const msg = this._getApiErrorMsg(data, res.statusCode >= 500 ? '服务器异常,请稍后重试' : '请求失败') - showError(msg) - reject(new Error(msg)) - }, - fail: (err) => { - const msg = (err && err.errMsg) ? (err.errMsg.indexOf('timeout') !== -1 ? '请求超时,请重试' : '网络异常,请重试') : '网络异常,请重试' - showError(msg) - reject(new Error(msg)) - } - }) - }) - }, - - // 登录方法 - 获取openId用于支付(加固错误处理,避免审核报“登录报错”) - async login() { - if (!this.ensureFullAppForAuth()) { - return null - } - try { - const loginRes = await new Promise((resolve, reject) => { - wx.login({ success: resolve, fail: reject }) - }) - if (!loginRes || !loginRes.code) { - console.warn('[App] wx.login 未返回 code') - wx.showToast({ title: '获取登录态失败,请重试', icon: 'none' }) - return null - } - try { - const res = await this.request('/api/miniprogram/login', { - method: 'POST', - data: { code: loginRes.code } - }) - - if (res.success && res.data) { - // 保存openId - if (res.data.openId) { - this.globalData.openId = res.data.openId - wx.setStorageSync('openId', res.data.openId) - console.log('[App] 获取openId成功') - } - - // 保存用户信息 - if (res.data.user) { - const user = res.data.user - this.globalData.userInfo = user - this.globalData.isLoggedIn = true - this.globalData.purchasedSections = user.purchasedSections || [] - this.globalData.hasFullBook = user.hasFullBook || false - - wx.setStorageSync('userInfo', user) - wx.setStorageSync('token', res.data.token || '') - - // 登录成功后,检查待绑定的推荐码并执行绑定 - const pendingRef = wx.getStorageSync('pendingReferralCode') || this.globalData.pendingReferralCode - if (pendingRef) { - console.log('[App] 登录后自动绑定推荐码:', pendingRef) - this.bindReferralCode(pendingRef) - } - - // 登录后引导完善资料 - this._ensureProfileCompletedAfterLogin(user) - } - - return res.data - } - } catch (apiError) { - console.log('[App] API登录失败:', apiError.message) - // 不使用模拟登录,提示用户网络问题 - wx.showToast({ title: '网络异常,请重试', icon: 'none' }) - return null - } - - return null - } catch (e) { - console.error('[App] 登录失败:', e) - wx.showToast({ title: '登录失败,请重试', icon: 'none' }) - return null - } - }, - - // 获取openId (支付必需) - async getOpenId() { - if (!this.ensureFullAppForAuth()) { - return null - } - // 先检查缓存 - const cachedOpenId = wx.getStorageSync('openId') - if (cachedOpenId) { - this.globalData.openId = cachedOpenId - return cachedOpenId - } - - // 没有缓存则登录获取 - try { - const loginRes = await new Promise((resolve, reject) => { - wx.login({ success: resolve, fail: reject }) - }) - - const res = await this.request('/api/miniprogram/login', { - method: 'POST', - data: { code: loginRes.code } - }) - - if (res.success && res.data?.openId) { - this.globalData.openId = res.data.openId - wx.setStorageSync('openId', res.data.openId) - // 接口同时返回 user 时视为登录,补全登录态并从登录开始绑定推荐码 - if (res.data.user) { - const user = res.data.user - this.globalData.userInfo = user - this.globalData.isLoggedIn = true - this.globalData.purchasedSections = user.purchasedSections || [] - this.globalData.hasFullBook = user.hasFullBook || false - wx.setStorageSync('userInfo', user) - wx.setStorageSync('token', res.data.token || '') - const pendingRef = wx.getStorageSync('pendingReferralCode') || this.globalData.pendingReferralCode - if (pendingRef) { - console.log('[App] getOpenId 登录后自动绑定推荐码:', pendingRef) - this.bindReferralCode(pendingRef) - } - - // 登录后引导完善资料 - this._ensureProfileCompletedAfterLogin(user) - } - return res.data.openId - } - } catch (e) { - console.error('[App] 获取openId失败:', e) - } - - return null - }, - - // 手机号登录:需同时传 wx.login 的 code 与 getPhoneNumber 的 phoneCode - async loginWithPhone(phoneCode) { - if (!this.ensureFullAppForAuth()) { - return null - } - try { - const loginRes = await new Promise((resolve, reject) => { - wx.login({ success: resolve, fail: reject }) - }) - if (!loginRes.code) { - wx.showToast({ title: '获取登录态失败', icon: 'none' }) - return null - } - const res = await this.request('/api/miniprogram/phone-login', { - method: 'POST', - data: { code: loginRes.code, phoneCode } - }) - - if (res.success && res.data) { - const user = res.data.user - this.globalData.userInfo = user - this.globalData.isLoggedIn = true - this.globalData.purchasedSections = user.purchasedSections || [] - this.globalData.hasFullBook = user.hasFullBook || false - - wx.setStorageSync('userInfo', user) - wx.setStorageSync('token', res.data.token) - - // 登录成功后绑定推荐码 - const pendingRef = wx.getStorageSync('pendingReferralCode') || this.globalData.pendingReferralCode - if (pendingRef) { - console.log('[App] 手机号登录后自动绑定推荐码:', pendingRef) - this.bindReferralCode(pendingRef) - } - - // 登录后引导完善资料 - this._ensureProfileCompletedAfterLogin(user) - - return res.data - } - } catch (e) { - console.log('[App] 手机号登录失败:', e) - wx.showToast({ title: '登录失败,请重试', icon: 'none' }) - } - - return null - }, - - // 退出登录 - logout() { - this.globalData.userInfo = null - this.globalData.isLoggedIn = false - this.globalData.purchasedSections = [] - this.globalData.hasFullBook = false - - wx.removeStorageSync('userInfo') - wx.removeStorageSync('token') - }, - - // 检查是否已购买章节 - hasPurchased(sectionId) { - if (this.globalData.hasFullBook) return true - return this.globalData.purchasedSections.includes(sectionId) - }, - - // 标记章节为已读(仅在有权限打开时由阅读页调用,用于首页已读/待读统计) - markSectionAsRead(sectionId) { - if (!sectionId) return - const list = this.globalData.readSectionIds || [] - if (list.includes(sectionId)) return - list.push(sectionId) - this.globalData.readSectionIds = list - wx.setStorageSync('readSectionIds', list) - }, - - // 已读章节数(用于首页展示) - getReadCount() { - return (this.globalData.readSectionIds || []).length - }, - - // 获取章节总数 - getTotalSections() { - return this.globalData.totalSections - }, - - // 切换TabBar - switchTab(index) { - this.globalData.currentTab = index - }, - - // 显示Toast - showToast(title, icon = 'none') { - wx.showToast({ - title, - icon, - duration: 2000 - }) - }, - - // 显示Loading - showLoading(title = '加载中...') { - wx.showLoading({ - title, - mask: true - }) - }, - - // 隐藏Loading - hideLoading() { - wx.hideLoading() - } -}) diff --git a/new-soul/miniprogram/app.json b/new-soul/miniprogram/app.json deleted file mode 100644 index b3746d6f..00000000 --- a/new-soul/miniprogram/app.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "pages": [ - "pages/chapters/chapters", - "pages/index/index", - "pages/match/match", - "pages/my/my", - "pages/read/read", - "pages/link-preview/link-preview", - "pages/about/about", - "pages/agreement/agreement", - "pages/privacy/privacy", - "pages/referral/referral", - "pages/purchases/purchases", - "pages/settings/settings", - "pages/search/search", - "pages/addresses/addresses", - "pages/addresses/edit", - "pages/withdraw-records/withdraw-records", - "pages/vip/vip", - "pages/member-detail/member-detail", - "pages/mentors/mentors", - "pages/mentor-detail/mentor-detail", - "pages/profile-show/profile-show", - "pages/profile-edit/profile-edit", - "pages/wallet/wallet" - ], - "window": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#000000", - "navigationBarTitleText": "Soul创业派对", - "navigationBarTextStyle": "white", - "backgroundColor": "#000000", - "navigationStyle": "custom" - }, - "tabBar": { - "custom": true, - "color": "#8e8e93", - "selectedColor": "#00CED1", - "backgroundColor": "#1c1c1e", - "borderStyle": "black", - "list": [ - { - "pagePath": "pages/index/index", - "text": "首页" - }, - { - "pagePath": "pages/chapters/chapters", - "text": "目录" - }, - { - "pagePath": "pages/match/match", - "text": "找伙伴" - }, - { - "pagePath": "pages/my/my", - "text": "我的" - } - ] - }, - "usingComponents": { - "icon": "/components/icon/icon" - }, - "navigateToMiniProgramAppIdList": [ - "wx6489c26045912fe1", - "wx3d15ed02e98b04e3" - ], - "__usePrivacyCheck__": true, - "lazyCodeLoading": "requiredComponents", - "style": "v2", - "sitemapLocation": "sitemap.json" -} \ No newline at end of file diff --git a/new-soul/miniprogram/app.wxss b/new-soul/miniprogram/app.wxss deleted file mode 100644 index 9ce22a06..00000000 --- a/new-soul/miniprogram/app.wxss +++ /dev/null @@ -1,606 +0,0 @@ -/** - * Soul创业实验 - 全局样式 - * 主题色: #00CED1 (Soul青色) - * 开发: 卡若 - */ - -/* ===== CSS 变量系统 ===== */ -page { - /* 品牌色 */ - --app-brand: #00CED1; - --app-brand-light: rgba(0, 206, 209, 0.1); - --app-brand-dark: #20B2AA; - - /* 背景色 */ - --app-bg-primary: #000000; - --app-bg-secondary: #1c1c1e; - --app-bg-tertiary: #2c2c2e; - - /* 文字色 */ - --app-text-primary: #ffffff; - --app-text-secondary: rgba(255, 255, 255, 0.7); - --app-text-tertiary: rgba(255, 255, 255, 0.4); - - /* 分隔线 */ - --app-separator: rgba(255, 255, 255, 0.05); - - /* iOS 系统色 */ - --ios-indigo: #5856D6; - --ios-green: #30d158; - --ios-red: #FF3B30; - --ios-orange: #FF9500; - --ios-yellow: #FFD700; - - /* 金色 */ - --gold: #FFD700; - --gold-light: #FFA500; - - /* 粉色 */ - --pink: #E91E63; - - /* 紫色 */ - --purple: #7B61FF; -} - -/* ===== 页面基础样式 ===== */ -page { - background-color: var(--app-bg-primary); - color: var(--app-text-primary); - font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', 'PingFang SC', 'Microsoft YaHei', sans-serif; - font-size: 28rpx; - line-height: 1.5; - -webkit-font-smoothing: antialiased; -} - -/* ===== 全局容器 ===== */ -.container { - min-height: 100vh; - padding: 0; - background: #000000; - padding-bottom: env(safe-area-inset-bottom); -} - -/* ===== 品牌色系 ===== */ -.brand-color { - color: #00CED1; -} - -.brand-bg { - background-color: #00CED1; -} - -.brand-gradient { - background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); -} - -.gold-color { - color: #FFD700; -} - -.gold-bg { - background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); -} - -/* ===== 文字渐变 ===== */ -.gradient-text { - background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.gold-gradient-text { - background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -/* ===== 按钮样式 ===== */ -.btn-primary { - background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); - color: #ffffff; - border: none; - border-radius: 48rpx; - padding: 28rpx 48rpx; - font-size: 32rpx; - font-weight: 600; - box-shadow: 0 8rpx 24rpx rgba(0, 206, 209, 0.3); - display: flex; - align-items: center; - justify-content: center; -} - -.btn-primary::after { - border: none; -} - -.btn-primary:active { - opacity: 0.85; - transform: scale(0.98); -} - -.btn-secondary { - background: rgba(0, 206, 209, 0.1); - color: #00CED1; - border: 2rpx solid rgba(0, 206, 209, 0.3); - border-radius: 48rpx; - padding: 28rpx 48rpx; - font-size: 32rpx; - font-weight: 500; -} - -.btn-secondary::after { - border: none; -} - -.btn-secondary:active { - background: rgba(0, 206, 209, 0.2); -} - -.btn-ghost { - background: rgba(255, 255, 255, 0.05); - color: #ffffff; - border: 2rpx solid rgba(255, 255, 255, 0.1); - border-radius: 48rpx; - padding: 28rpx 48rpx; - font-size: 32rpx; -} - -.btn-ghost::after { - border: none; -} - -.btn-ghost:active { - background: rgba(255, 255, 255, 0.1); -} - -.btn-gold { - background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); - color: #000000; - border: none; - border-radius: 48rpx; - padding: 28rpx 48rpx; - font-size: 32rpx; - font-weight: 600; - box-shadow: 0 8rpx 24rpx rgba(255, 215, 0, 0.3); -} - -.btn-gold::after { - border: none; -} - -/* ===== 卡片样式 ===== */ -.card { - background: rgba(28, 28, 30, 0.9); - border-radius: 32rpx; - padding: 32rpx; - margin: 24rpx 32rpx; - border: 2rpx solid rgba(255, 255, 255, 0.05); -} - -.card-light { - background: rgba(44, 44, 46, 0.8); - border-radius: 24rpx; - padding: 24rpx; - border: 2rpx solid rgba(255, 255, 255, 0.08); -} - -.card-gradient { - background: linear-gradient(135deg, rgba(28, 28, 30, 1) 0%, rgba(44, 44, 46, 1) 100%); - border-radius: 32rpx; - padding: 32rpx; - border: 2rpx solid rgba(0, 206, 209, 0.2); -} - -.card-brand { - background: linear-gradient(135deg, rgba(0, 206, 209, 0.1) 0%, rgba(32, 178, 170, 0.05) 100%); - border-radius: 32rpx; - padding: 32rpx; - border: 2rpx solid rgba(0, 206, 209, 0.2); -} - -/* ===== 输入框样式 ===== */ -.input-ios { - background: rgba(0, 0, 0, 0.3); - border: 2rpx solid rgba(255, 255, 255, 0.1); - border-radius: 24rpx; - padding: 28rpx 32rpx; - font-size: 32rpx; - color: #ffffff; -} - -.input-ios:focus { - border-color: rgba(0, 206, 209, 0.5); -} - -.input-ios-placeholder { - color: rgba(255, 255, 255, 0.3); -} - -/* ===== 列表项样式 ===== */ -.list-item { - display: flex; - align-items: center; - justify-content: space-between; - padding: 28rpx 32rpx; - background: rgba(28, 28, 30, 0.9); - border-bottom: 1rpx solid rgba(255, 255, 255, 0.05); -} - -.list-item:first-child { - border-radius: 24rpx 24rpx 0 0; -} - -.list-item:last-child { - border-radius: 0 0 24rpx 24rpx; - border-bottom: none; -} - -.list-item:only-child { - border-radius: 24rpx; -} - -.list-item:active { - background: rgba(44, 44, 46, 1); -} - -/* ===== 标签样式 ===== */ -.tag { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 8rpx 20rpx; - min-width: 80rpx; - border-radius: 8rpx; - font-size: 22rpx; - font-weight: 500; - box-sizing: border-box; - text-align: center; -} - -.tag-brand { - background: rgba(0, 206, 209, 0.1); - color: #00CED1; -} - -.tag-gold { - background: rgba(255, 215, 0, 0.1); - color: #FFD700; -} - -.tag-pink { - background: rgba(233, 30, 99, 0.1); - color: #E91E63; -} - -.tag-purple { - background: rgba(123, 97, 255, 0.1); - color: #7B61FF; -} - -.tag-free { - background: rgba(0, 206, 209, 0.1); - color: #00CED1; -} - -/* ===== 分隔线 ===== */ -.divider { - height: 1rpx; - background: rgba(255, 255, 255, 0.05); - margin: 24rpx 0; -} - -.divider-vertical { - width: 2rpx; - height: 48rpx; - background: rgba(255, 255, 255, 0.1); -} - -/* ===== 骨架屏动画 ===== */ -.skeleton { - background: linear-gradient(90deg, - rgba(28, 28, 30, 1) 25%, - rgba(44, 44, 46, 1) 50%, - rgba(28, 28, 30, 1) 75% - ); - background-size: 200% 100%; - animation: skeleton-loading 1.5s ease-in-out infinite; - border-radius: 8rpx; -} - -@keyframes skeleton-loading { - 0% { - background-position: 200% 0; - } - 100% { - background-position: -200% 0; - } -} - -/* ===== 页面过渡动画 ===== */ -.page-transition { - animation: fadeIn 0.3s ease-out; -} - -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(20rpx); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* ===== 弹窗动画 ===== */ -.modal-overlay { - animation: modalOverlayIn 0.25s ease-out; -} - -.modal-content { - animation: modalContentIn 0.3s cubic-bezier(0.32, 0.72, 0, 1); -} - -@keyframes modalOverlayIn { - from { opacity: 0; } - to { opacity: 1; } -} - -@keyframes modalContentIn { - from { - opacity: 0; - transform: scale(0.95) translateY(20rpx); - } - to { - opacity: 1; - transform: scale(1) translateY(0); - } -} - -/* ===== 脉动动画 ===== */ -.pulse { - animation: pulse 2s ease-in-out infinite; -} - -@keyframes pulse { - 0%, 100% { - transform: scale(1); - opacity: 1; - } - 50% { - transform: scale(1.05); - opacity: 0.8; - } -} - -/* ===== 发光效果 ===== */ -.glow { - box-shadow: 0 0 40rpx rgba(0, 206, 209, 0.3); -} - -.glow-gold { - box-shadow: 0 0 40rpx rgba(255, 215, 0, 0.3); -} - -/* ===== 文字样式 ===== */ -.text-xs { - font-size: 22rpx; -} - -.text-sm { - font-size: 26rpx; -} - -.text-base { - font-size: 28rpx; -} - -.text-lg { - font-size: 32rpx; -} - -.text-xl { - font-size: 36rpx; -} - -.text-2xl { - font-size: 44rpx; -} - -.text-3xl { - font-size: 56rpx; -} - -.text-white { - color: #ffffff; -} - -.text-gray { - color: rgba(255, 255, 255, 0.6); -} - -.text-muted { - color: rgba(255, 255, 255, 0.4); -} - -.text-center { - text-align: center; -} - -.font-medium { - font-weight: 500; -} - -.font-semibold { - font-weight: 600; -} - -.font-bold { - font-weight: 700; -} - -/* ===== Flex布局 ===== */ -.flex { - display: flex; -} - -.flex-col { - flex-direction: column; -} - -.items-center { - align-items: center; -} - -.justify-center { - justify-content: center; -} - -.justify-between { - justify-content: space-between; -} - -.justify-around { - justify-content: space-around; -} - -.flex-1 { - flex: 1; -} - -.gap-1 { - gap: 8rpx; -} - -.gap-2 { - gap: 16rpx; -} - -.gap-3 { - gap: 24rpx; -} - -.gap-4 { - gap: 32rpx; -} - -/* ===== 间距 ===== */ -.p-2 { padding: 16rpx; } -.p-3 { padding: 24rpx; } -.p-4 { padding: 32rpx; } -.p-5 { padding: 40rpx; } - -.px-4 { padding-left: 32rpx; padding-right: 32rpx; } -.py-2 { padding-top: 16rpx; padding-bottom: 16rpx; } -.py-3 { padding-top: 24rpx; padding-bottom: 24rpx; } - -.m-4 { margin: 32rpx; } -.mx-4 { margin-left: 32rpx; margin-right: 32rpx; } -.my-3 { margin-top: 24rpx; margin-bottom: 24rpx; } -.mb-2 { margin-bottom: 16rpx; } -.mb-3 { margin-bottom: 24rpx; } -.mb-4 { margin-bottom: 32rpx; } -.mt-4 { margin-top: 32rpx; } - -/* ===== 圆角 ===== */ -.rounded { border-radius: 8rpx; } -.rounded-lg { border-radius: 16rpx; } -.rounded-xl { border-radius: 24rpx; } -.rounded-2xl { border-radius: 32rpx; } -.rounded-full { border-radius: 50%; } - -/* ===== 安全区域 ===== */ -.safe-bottom { - padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx); -} - -.pb-tabbar { - padding-bottom: 200rpx; -} - -/* ===== 头部导航占位 ===== */ -.nav-placeholder { - height: calc(88rpx + env(safe-area-inset-top, 44rpx)); -} - -/* ===== 隐藏滚动条 ===== */ -::-webkit-scrollbar { - display: none; - width: 0; - height: 0; -} - -/* ===== 触摸反馈 ===== */ -.touch-feedback { - transition: all 0.15s ease; -} - -.touch-feedback:active { - opacity: 0.7; - transform: scale(0.98); -} - -/* ===== 进度条 ===== */ -.progress-bar { - height: 8rpx; - background: rgba(44, 44, 46, 1); - border-radius: 4rpx; - overflow: hidden; -} - -.progress-fill { - height: 100%; - background: linear-gradient(90deg, #00CED1 0%, #20B2AA 100%); - border-radius: 4rpx; - transition: width 0.3s ease; -} - -/* ===== 头像样式 ===== */ -.avatar { - width: 80rpx; - height: 80rpx; - border-radius: 50%; - background: linear-gradient(135deg, rgba(0, 206, 209, 0.2) 0%, rgba(32, 178, 170, 0.1) 100%); - display: flex; - align-items: center; - justify-content: center; - color: #00CED1; - font-weight: 700; - font-size: 32rpx; - border: 4rpx solid rgba(0, 206, 209, 0.3); -} - -.avatar-lg { - width: 120rpx; - height: 120rpx; - font-size: 48rpx; -} - -/* ===== 图标容器 ===== */ -.icon-box { - width: 64rpx; - height: 64rpx; - border-radius: 16rpx; - display: flex; - align-items: center; - justify-content: center; -} - -.icon-box-brand { - background: linear-gradient(135deg, rgba(0, 206, 209, 0.2) 0%, rgba(32, 178, 170, 0.1) 100%); -} - -.icon-box-gold { - background: linear-gradient(135deg, rgba(255, 215, 0, 0.2) 0%, rgba(255, 165, 0, 0.1) 100%); -} - -/* ===== 渐变背景 ===== */ -.bg-gradient-dark { - background: linear-gradient(180deg, #000000 0%, #1a1a1a 100%); -} - -.bg-gradient-brand { - background: linear-gradient(135deg, rgba(0, 206, 209, 0.1) 0%, transparent 100%); -} diff --git a/new-soul/miniprogram/assets/icons/alert-circle.svg b/new-soul/miniprogram/assets/icons/alert-circle.svg deleted file mode 100644 index f5a441f3..00000000 --- a/new-soul/miniprogram/assets/icons/alert-circle.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/new-soul/miniprogram/assets/icons/arrow-right.svg b/new-soul/miniprogram/assets/icons/arrow-right.svg deleted file mode 100644 index 1dc64d3f..00000000 --- a/new-soul/miniprogram/assets/icons/arrow-right.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/bell.svg b/new-soul/miniprogram/assets/icons/bell.svg deleted file mode 100644 index 0e7e405b..00000000 --- a/new-soul/miniprogram/assets/icons/bell.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/book-arrow-teal.svg b/new-soul/miniprogram/assets/icons/book-arrow-teal.svg deleted file mode 100644 index 6a861630..00000000 --- a/new-soul/miniprogram/assets/icons/book-arrow-teal.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/new-soul/miniprogram/assets/icons/book-arrow.svg b/new-soul/miniprogram/assets/icons/book-arrow.svg deleted file mode 100644 index 2b1320d0..00000000 --- a/new-soul/miniprogram/assets/icons/book-arrow.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/new-soul/miniprogram/assets/icons/book-open-teal.svg b/new-soul/miniprogram/assets/icons/book-open-teal.svg deleted file mode 100644 index 482f4093..00000000 --- a/new-soul/miniprogram/assets/icons/book-open-teal.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/book-open.svg b/new-soul/miniprogram/assets/icons/book-open.svg deleted file mode 100644 index d833e86b..00000000 --- a/new-soul/miniprogram/assets/icons/book-open.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/book.svg b/new-soul/miniprogram/assets/icons/book.svg deleted file mode 100644 index 93579576..00000000 --- a/new-soul/miniprogram/assets/icons/book.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/chevron-left.svg b/new-soul/miniprogram/assets/icons/chevron-left.svg deleted file mode 100644 index e406b2b9..00000000 --- a/new-soul/miniprogram/assets/icons/chevron-left.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/new-soul/miniprogram/assets/icons/clock-teal.svg b/new-soul/miniprogram/assets/icons/clock-teal.svg deleted file mode 100644 index 96a928e3..00000000 --- a/new-soul/miniprogram/assets/icons/clock-teal.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/clock.svg b/new-soul/miniprogram/assets/icons/clock.svg deleted file mode 100644 index 547f24a7..00000000 --- a/new-soul/miniprogram/assets/icons/clock.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/edit-gray.svg b/new-soul/miniprogram/assets/icons/edit-gray.svg deleted file mode 100644 index 4d821839..00000000 --- a/new-soul/miniprogram/assets/icons/edit-gray.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/eye-off.svg b/new-soul/miniprogram/assets/icons/eye-off.svg deleted file mode 100644 index 05b73282..00000000 --- a/new-soul/miniprogram/assets/icons/eye-off.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/new-soul/miniprogram/assets/icons/eye-teal.svg b/new-soul/miniprogram/assets/icons/eye-teal.svg deleted file mode 100644 index cdd62e60..00000000 --- a/new-soul/miniprogram/assets/icons/eye-teal.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/eye.svg b/new-soul/miniprogram/assets/icons/eye.svg deleted file mode 100644 index 10ff508d..00000000 --- a/new-soul/miniprogram/assets/icons/eye.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/folder-teal.svg b/new-soul/miniprogram/assets/icons/folder-teal.svg deleted file mode 100644 index 28003510..00000000 --- a/new-soul/miniprogram/assets/icons/folder-teal.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/new-soul/miniprogram/assets/icons/folder.svg b/new-soul/miniprogram/assets/icons/folder.svg deleted file mode 100644 index 5e5b7042..00000000 --- a/new-soul/miniprogram/assets/icons/folder.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/new-soul/miniprogram/assets/icons/gift.svg b/new-soul/miniprogram/assets/icons/gift.svg deleted file mode 100644 index 66ac806c..00000000 --- a/new-soul/miniprogram/assets/icons/gift.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/new-soul/miniprogram/assets/icons/home-active.png b/new-soul/miniprogram/assets/icons/home-active.png deleted file mode 100644 index b6090d87..00000000 Binary files a/new-soul/miniprogram/assets/icons/home-active.png and /dev/null differ diff --git a/new-soul/miniprogram/assets/icons/home.png b/new-soul/miniprogram/assets/icons/home.png deleted file mode 100644 index 0ffba614..00000000 Binary files a/new-soul/miniprogram/assets/icons/home.png and /dev/null differ diff --git a/new-soul/miniprogram/assets/icons/home.svg b/new-soul/miniprogram/assets/icons/home.svg deleted file mode 100644 index 76244091..00000000 --- a/new-soul/miniprogram/assets/icons/home.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/image.svg b/new-soul/miniprogram/assets/icons/image.svg deleted file mode 100644 index 50ed9e6d..00000000 --- a/new-soul/miniprogram/assets/icons/image.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/new-soul/miniprogram/assets/icons/info-blue.svg b/new-soul/miniprogram/assets/icons/info-blue.svg deleted file mode 100644 index 0f5bb1d2..00000000 --- a/new-soul/miniprogram/assets/icons/info-blue.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/new-soul/miniprogram/assets/icons/info.svg b/new-soul/miniprogram/assets/icons/info.svg deleted file mode 100644 index 11d0f224..00000000 --- a/new-soul/miniprogram/assets/icons/info.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/new-soul/miniprogram/assets/icons/list.svg b/new-soul/miniprogram/assets/icons/list.svg deleted file mode 100644 index 688326aa..00000000 --- a/new-soul/miniprogram/assets/icons/list.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/new-soul/miniprogram/assets/icons/match-active.png b/new-soul/miniprogram/assets/icons/match-active.png deleted file mode 100644 index da62b436..00000000 Binary files a/new-soul/miniprogram/assets/icons/match-active.png and /dev/null differ diff --git a/new-soul/miniprogram/assets/icons/match.png b/new-soul/miniprogram/assets/icons/match.png deleted file mode 100644 index b15582e3..00000000 Binary files a/new-soul/miniprogram/assets/icons/match.png and /dev/null differ diff --git a/new-soul/miniprogram/assets/icons/message-circle.svg b/new-soul/miniprogram/assets/icons/message-circle.svg deleted file mode 100644 index 037560e9..00000000 --- a/new-soul/miniprogram/assets/icons/message-circle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/new-soul/miniprogram/assets/icons/my-active.png b/new-soul/miniprogram/assets/icons/my-active.png deleted file mode 100644 index da62b436..00000000 Binary files a/new-soul/miniprogram/assets/icons/my-active.png and /dev/null differ diff --git a/new-soul/miniprogram/assets/icons/my.png b/new-soul/miniprogram/assets/icons/my.png deleted file mode 100644 index b15582e3..00000000 Binary files a/new-soul/miniprogram/assets/icons/my.png and /dev/null differ diff --git a/new-soul/miniprogram/assets/icons/partners.svg b/new-soul/miniprogram/assets/icons/partners.svg deleted file mode 100644 index 80668312..00000000 --- a/new-soul/miniprogram/assets/icons/partners.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - diff --git a/new-soul/miniprogram/assets/icons/settings-gray.svg b/new-soul/miniprogram/assets/icons/settings-gray.svg deleted file mode 100644 index d7098fc1..00000000 --- a/new-soul/miniprogram/assets/icons/settings-gray.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/settings.svg b/new-soul/miniprogram/assets/icons/settings.svg deleted file mode 100644 index c7006ea8..00000000 --- a/new-soul/miniprogram/assets/icons/settings.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/share.svg b/new-soul/miniprogram/assets/icons/share.svg deleted file mode 100644 index 93179fc2..00000000 --- a/new-soul/miniprogram/assets/icons/share.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/new-soul/miniprogram/assets/icons/sparkles.svg b/new-soul/miniprogram/assets/icons/sparkles.svg deleted file mode 100644 index e2a4461f..00000000 --- a/new-soul/miniprogram/assets/icons/sparkles.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/new-soul/miniprogram/assets/icons/user-edit-gray.svg b/new-soul/miniprogram/assets/icons/user-edit-gray.svg deleted file mode 100644 index 884c3651..00000000 --- a/new-soul/miniprogram/assets/icons/user-edit-gray.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/user.svg b/new-soul/miniprogram/assets/icons/user.svg deleted file mode 100644 index 8b190427..00000000 --- a/new-soul/miniprogram/assets/icons/user.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/icons/users-teal.svg b/new-soul/miniprogram/assets/icons/users-teal.svg deleted file mode 100644 index ed97706f..00000000 --- a/new-soul/miniprogram/assets/icons/users-teal.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/new-soul/miniprogram/assets/icons/users.svg b/new-soul/miniprogram/assets/icons/users.svg deleted file mode 100644 index 4816094b..00000000 --- a/new-soul/miniprogram/assets/icons/users.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/new-soul/miniprogram/assets/icons/wallet.svg b/new-soul/miniprogram/assets/icons/wallet.svg deleted file mode 100644 index 6d431e54..00000000 --- a/new-soul/miniprogram/assets/icons/wallet.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/new-soul/miniprogram/assets/images/author-avatar.png b/new-soul/miniprogram/assets/images/author-avatar.png deleted file mode 100644 index c02ae73f..00000000 Binary files a/new-soul/miniprogram/assets/images/author-avatar.png and /dev/null differ diff --git a/new-soul/miniprogram/components/icon/README.md b/new-soul/miniprogram/components/icon/README.md deleted file mode 100644 index 34e394c8..00000000 --- a/new-soul/miniprogram/components/icon/README.md +++ /dev/null @@ -1,175 +0,0 @@ -# Icon 图标组件 - -SVG 图标组件,参考 lucide-react 实现,用于在小程序中使用矢量图标。 - -**技术实现**: 使用 Base64 编码的 SVG + image 组件(小程序不支持直接使用 SVG 标签) - ---- - -## 使用方法 - -### 1. 在页面 JSON 中引入组件 - -```json -{ - "usingComponents": { - "icon": "/components/icon/icon" - } -} -``` - -### 2. 在 WXML 中使用 - -```xml - - - - - - - - - - - - - - - - - -``` - ---- - -## 属性说明 - -| 属性 | 类型 | 默认值 | 说明 | -|-----|------|--------|-----| -| name | String | 'share' | 图标名称 | -| size | Number | 48 | 图标大小(rpx) | -| color | String | 'currentColor' | 图标颜色 | -| customClass | String | '' | 自定义类名 | -| customStyle | String | '' | 自定义样式 | - ---- - -## 可用图标 - -| 图标名称 | 说明 | 对应 lucide-react | -|---------|------|-------------------| -| `share` | 分享 | `` | -| `arrow-up-right` | 右上箭头 | `` | -| `chevron-left` | 左箭头 | `` | -| `search` | 搜索 | `` | -| `heart` | 心形 | `` | - ---- - -## 添加新图标 - -在 `icon.js` 的 `getSvgPath` 方法中添加新图标: - -```javascript -getSvgPath(name) { - const svgMap = { - 'new-icon': '', - // ... 其他图标 - } - return svgMap[name] || '' -} -``` - -**获取 SVG 代码**: 访问 [lucide.dev](https://lucide.dev) 搜索图标,复制 SVG 内容。 -**注意**: 颜色使用 `COLOR` 占位符,组件会自动替换。 - ---- - -## 样式定制 - -### 1. 使用 customClass - -```xml - -``` - -```css -.my-icon-class { - opacity: 0.8; -} -``` - -### 2. 使用 customStyle - -```xml - -``` - ---- - -## 技术说明 - -### 为什么使用 Base64 + image? - -1. **矢量图标**:任意缩放不失真 -2. **灵活着色**:通过 `COLOR` 占位符动态改变颜色 -3. **轻量级**:无需加载字体文件或外部图片 -4. **兼容性**:小程序不支持直接使用 SVG 标签,image 组件支持 Base64 SVG - -### 为什么不用字体图标? - -小程序对字体文件有限制,Base64 编码字体文件会增加包体积,SVG 图标更轻量。 - -### 与 lucide-react 的对应关系 - -- **lucide-react**: React 组件库,使用 SVG -- **本组件**: 小程序自定义组件,也使用 SVG -- **SVG path 数据**: 完全相同,从 lucide 官网复制 - ---- - -## 示例 - -### 悬浮分享按钮 - -```xml - -``` - -```css -.fab-share { - position: fixed; - right: 32rpx; - bottom: calc(120rpx + env(safe-area-inset-bottom)); - width: 96rpx; - height: 96rpx; - border-radius: 50%; - background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); - display: flex; - align-items: center; - justify-content: center; -} -``` - ---- - -## 扩展图标库 - -可以继续添加更多 lucide-react 图标: - -- `star` - 星星 -- `wallet` - 钱包 -- `gift` - 礼物 -- `info` - 信息 -- `settings` - 设置 -- `user` - 用户 -- `book-open` - 打开的书 -- `eye` - 眼睛 -- `clock` - 时钟 -- `users` - 用户组 - ---- - -**图标组件创建完成!** 🎉 diff --git a/new-soul/miniprogram/components/icon/icon.js b/new-soul/miniprogram/components/icon/icon.js deleted file mode 100644 index b2dec23f..00000000 --- a/new-soul/miniprogram/components/icon/icon.js +++ /dev/null @@ -1,83 +0,0 @@ -// components/icon/icon.js -Component({ - properties: { - // 图标名称 - name: { - type: String, - value: 'share', - observer: 'updateIcon' - }, - // 图标大小(rpx) - size: { - type: Number, - value: 48 - }, - // 图标颜色 - color: { - type: String, - value: '#ffffff', - observer: 'updateIcon' - }, - // 自定义类名 - customClass: { - type: String, - value: '' - }, - // 自定义样式 - customStyle: { - type: String, - value: '' - } - }, - - data: { - svgData: '' - }, - - lifetimes: { - attached() { - this.updateIcon() - } - }, - - methods: { - // SVG 图标数据映射 - getSvgPath(name) { - const svgMap = { - 'share': '', - - 'arrow-up-right': '', - - 'chevron-left': '', - - 'search': '', - - 'heart': '' - } - - return svgMap[name] || '' - }, - - // 更新图标 - updateIcon() { - const { name, color } = this.data - let svgString = this.getSvgPath(name) - - if (svgString) { - // 替换颜色占位符 - svgString = svgString.replace(/COLOR/g, color) - - // 转换为 Base64 Data URL - const svgData = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}` - - this.setData({ - svgData: svgData - }) - } else { - this.setData({ - svgData: '' - }) - } - } - } -}) diff --git a/new-soul/miniprogram/components/icon/icon.json b/new-soul/miniprogram/components/icon/icon.json deleted file mode 100644 index a89ef4db..00000000 --- a/new-soul/miniprogram/components/icon/icon.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "component": true, - "usingComponents": {} -} diff --git a/new-soul/miniprogram/components/icon/icon.wxml b/new-soul/miniprogram/components/icon/icon.wxml deleted file mode 100644 index b1c29a25..00000000 --- a/new-soul/miniprogram/components/icon/icon.wxml +++ /dev/null @@ -1,5 +0,0 @@ - - - - {{name}} - diff --git a/new-soul/miniprogram/components/icon/icon.wxss b/new-soul/miniprogram/components/icon/icon.wxss deleted file mode 100644 index d12d2a0a..00000000 --- a/new-soul/miniprogram/components/icon/icon.wxss +++ /dev/null @@ -1,18 +0,0 @@ -/* components/icon/icon.wxss */ -.icon { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.icon-image { - display: block; - width: 100%; - height: 100%; -} - -.icon-text { - font-size: 24rpx; - color: currentColor; -} diff --git a/new-soul/miniprogram/custom-tab-bar/index.js b/new-soul/miniprogram/custom-tab-bar/index.js deleted file mode 100644 index 4acd9546..00000000 --- a/new-soul/miniprogram/custom-tab-bar/index.js +++ /dev/null @@ -1,153 +0,0 @@ -/** - * Soul创业实验 - 自定义TabBar组件 - * 根据后台配置动态显示/隐藏"找伙伴"按钮 - */ - -console.log('[TabBar] ===== 组件文件开始加载 =====') - -const app = getApp() -console.log('[TabBar] App 对象:', app) - -Component({ - data: { - selected: 0, - color: '#8e8e93', - selectedColor: '#00CED1', - matchEnabled: false, // 找伙伴功能开关,默认关闭 - list: [ - { - pagePath: '/pages/index/index', - text: '首页', - iconType: 'home' - }, - { - pagePath: '/pages/chapters/chapters', - text: '目录', - iconType: 'list' - }, - { - pagePath: '/pages/match/match', - text: '找伙伴', - iconType: 'match', - isSpecial: true - }, - { - pagePath: '/pages/my/my', - text: '我的', - iconType: 'user' - } - ] - }, - - lifetimes: { - attached() { - console.log('[TabBar] Component attached 生命周期触发') - this.loadFeatureConfig() - }, - ready() { - console.log('[TabBar] Component ready 生命周期触发') - // 如果 attached 中没有成功加载,在 ready 中再次尝试 - if (this.data.matchEnabled === undefined || this.data.matchEnabled === null) { - console.log('[TabBar] 在 ready 中重新加载配置') - this.loadFeatureConfig() - } - } - }, - - // 页面加载时也调用(兼容性更好) - attached() { - console.log('[TabBar] attached() 方法触发') - this.loadFeatureConfig() - }, - - methods: { - // 加载功能配置 - async loadFeatureConfig() { - try { - console.log('[TabBar] 开始加载功能配置...') - console.log('[TabBar] API地址:', app.globalData.baseUrl + '/api/miniprogram/config') - - // app.request 的第一个参数是 url 字符串,第二个参数是 options 对象 - const res = await app.request('/api/miniprogram/config', { - method: 'GET' - }) - - - // 兼容两种返回格式 - let matchEnabled = false - - if (res && res.success && res.features) { - console.log('[TabBar] features配置:', JSON.stringify(res.features)) - matchEnabled = res.features.matchEnabled === true - console.log('[TabBar] matchEnabled值:', matchEnabled) - } else if (res && res.configs && res.configs.feature_config) { - // 备用格式:从 configs.feature_config 读取 - console.log('[TabBar] 使用备用格式,从configs读取') - matchEnabled = res.configs.feature_config.matchEnabled === true - console.log('[TabBar] matchEnabled值:', matchEnabled) - } else { - console.log('[TabBar] ⚠️ 未找到features配置,使用默认值false') - console.log('[TabBar] res对象keys:', Object.keys(res || {})) - } - - this.setData({ matchEnabled }, () => { - console.log('[TabBar] ✅ matchEnabled已设置为:', this.data.matchEnabled) - // 配置加载完成后,根据当前路由设置选中状态 - this.updateSelected() - }) - - // 如果当前在找伙伴页面,但功能已关闭,跳转到首页 - if (!matchEnabled) { - const pages = getCurrentPages() - const currentPage = pages[pages.length - 1] - if (currentPage && currentPage.route === 'pages/match/match') { - console.log('[TabBar] 找伙伴功能已关闭,从match页面跳转到首页') - wx.switchTab({ url: '/pages/index/index' }) - } - } - } catch (error) { - console.log('[TabBar] ❌ 加载功能配置失败:', error) - console.log('[TabBar] 错误详情:', error.message || error) - // 默认关闭找伙伴功能 - this.setData({ matchEnabled: false }, () => { - this.updateSelected() - }) - } - }, - - // 根据当前路由更新选中状态 - updateSelected() { - const pages = getCurrentPages() - if (pages.length === 0) return - - const currentPage = pages[pages.length - 1] - const route = currentPage.route - - let selected = 0 - const { matchEnabled } = this.data - - // 根据路由匹配对应的索引 - if (route === 'pages/index/index') { - selected = 0 - } else if (route === 'pages/chapters/chapters') { - selected = 1 - } else if (route === 'pages/match/match') { - selected = 2 - } else if (route === 'pages/my/my') { - selected = matchEnabled ? 3 : 2 - } - - this.setData({ selected }) - }, - - switchTab(e) { - const data = e.currentTarget.dataset - const url = data.path - const index = data.index - - if (this.data.selected === index) return - - wx.switchTab({ url }) - } - } -}) diff --git a/new-soul/miniprogram/custom-tab-bar/index.json b/new-soul/miniprogram/custom-tab-bar/index.json deleted file mode 100644 index 467ce294..00000000 --- a/new-soul/miniprogram/custom-tab-bar/index.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "component": true -} diff --git a/new-soul/miniprogram/custom-tab-bar/index.wxml b/new-soul/miniprogram/custom-tab-bar/index.wxml deleted file mode 100644 index 73369b2a..00000000 --- a/new-soul/miniprogram/custom-tab-bar/index.wxml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - {{list[0].text}} - - - - - - - - {{list[1].text}} - - - - - - - - {{list[2].text}} - - - - - - - - {{list[3].text}} - - diff --git a/new-soul/miniprogram/custom-tab-bar/index.wxss b/new-soul/miniprogram/custom-tab-bar/index.wxss deleted file mode 100644 index 98036655..00000000 --- a/new-soul/miniprogram/custom-tab-bar/index.wxss +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Soul创业实验 - 自定义TabBar样式 - * 实现中间突出的"找伙伴"按钮 - */ - -.tab-bar { - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 100rpx; - background: rgba(28, 28, 30, 0.95); - backdrop-filter: blur(40rpx); - -webkit-backdrop-filter: blur(40rpx); - display: flex; - align-items: flex-end; - padding-bottom: env(safe-area-inset-bottom); - z-index: 999; -} - -/* 三个tab布局(找伙伴功能关闭时) */ -.tab-bar-three .tab-bar-item { - flex: 1; -} - -/* 四个tab布局(找伙伴功能开启时) */ -.tab-bar-four .tab-bar-item { - flex: 1; -} - -.tab-bar-border { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 1rpx; - background: rgba(255, 255, 255, 0.05); -} - -.tab-bar-item { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 10rpx 0 16rpx; -} - -.icon-wrapper { - width: 48rpx; - height: 48rpx; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 4rpx; -} - -.icon { - width: 44rpx; - height: 44rpx; - display: flex; - align-items: center; - justify-content: center; -} - -.tab-bar-text { - font-size: 22rpx; - line-height: 1; -} - -/* ===== SVG 图标样式 ===== */ -.tab-icon { - width: 48rpx; - height: 48rpx; - display: block; - filter: brightness(0) saturate(100%) invert(60%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(95%) contrast(85%); -} - -.tab-icon.icon-active { - filter: brightness(0) saturate(100%) invert(72%) sepia(54%) saturate(2933%) hue-rotate(134deg) brightness(101%) contrast(101%); -} - - -/* ===== 找伙伴 - 中间特殊按钮 ===== */ -.special-item { - position: relative; - margin-top: -32rpx; -} - -.special-button { - width: 112rpx; - height: 112rpx; - border-radius: 50%; - background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 8rpx 32rpx rgba(0, 206, 209, 0.4); - margin-bottom: 4rpx; - transition: all 0.2s ease; -} - -.special-button:active { - transform: scale(0.95); -} - -.special-active { - box-shadow: 0 8rpx 40rpx rgba(0, 206, 209, 0.6); -} - -.special-text { - margin-top: 4rpx; -} - -/* ===== 找伙伴特殊按钮图标 ===== */ -.special-icon { - width: 80rpx; - height: 80rpx; - display: block; - filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(100%) contrast(100%); -} diff --git a/new-soul/miniprogram/pages/about/about.js b/new-soul/miniprogram/pages/about/about.js deleted file mode 100644 index af04d83d..00000000 --- a/new-soul/miniprogram/pages/about/about.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Soul创业派对 - 关于作者页 - * 开发: 卡若 - */ -const app = getApp() - -Page({ - data: { - statusBarHeight: 44, - authorLoading: true, - author: { - name: '卡若', - avatar: 'K', - avatarImg: '/assets/images/author-avatar.png', - title: '', - bio: '', - stats: [], - highlights: [] - }, - bookInfo: { - title: '一场Soul的创业实验', - totalChapters: 62, - parts: [ - { name: '真实的人', chapters: 10 }, - { name: '真实的行业', chapters: 15 }, - { name: '真实的错误', chapters: 9 }, - { name: '真实的赚钱', chapters: 20 }, - { name: '真实的社会', chapters: 9 } - ], - price: 9.9 - } - }, - - onLoad() { - wx.showShareMenu({ withShareTimeline: true }) - this.setData({ - statusBarHeight: app.globalData.statusBarHeight - }) - this.loadAuthor() - this.loadBookStats() - }, - - async loadAuthor() { - this.setData({ authorLoading: true }) - try { - const res = await app.request({ url: '/api/miniprogram/about/author', silent: true }) - if (res?.success && res.data) { - const d = res.data - let avatarImg = d.avatarImg || '' - if (avatarImg && !avatarImg.startsWith('http')) { - const base = (app.globalData.baseUrl || '').replace(/\/$/, '') - avatarImg = base ? base + (avatarImg.startsWith('/') ? avatarImg : '/' + avatarImg) : avatarImg - } - this.setData({ - author: { - name: d.name || '卡若', - avatar: d.avatar || 'K', - avatarImg: avatarImg || '/assets/images/author-avatar.png', - title: d.title || '', - bio: d.bio || '', - stats: Array.isArray(d.stats) ? d.stats : [ - { label: '商业案例', value: '62' }, - { label: '连续直播', value: '365天' }, - { label: '派对分享', value: '1000+' } - ], - highlights: Array.isArray(d.highlights) ? d.highlights : [] - }, - authorLoading: false - }) - } else { - this.setData({ authorLoading: false }) - } - } catch (e) { - console.log('[About] 加载作者配置失败,使用默认') - this.setData({ authorLoading: false }) - } - }, - - // 加载书籍统计(合并到作者统计第一项「商业案例」) - async loadBookStats() { - try { - const res = await app.request({ url: '/api/miniprogram/book/stats', silent: true }) - if (res?.success && res.data) { - const total = res.data?.totalChapters || 62 - this.setData({ 'bookInfo.totalChapters': total }) - const stats = this.data.author?.stats || [] - const idx = stats.findIndex((s) => s && (s.label === '商业案例' || s.label === '章节')) - if (idx >= 0 && stats[idx]) { - const next = [...stats] - next[idx] = { ...stats[idx], value: String(total) } - this.setData({ 'author.stats': next }) - } else if (stats.length === 0) { - this.setData({ - 'author.stats': [ - { label: '商业案例', value: String(total) }, - { label: '连续直播', value: '365天' }, - { label: '派对分享', value: '1000+' } - ] - }) - } - } - } catch (e) { - console.log('[About] 加载书籍统计失败,使用默认值') - } - }, - - // 联系方式功能已禁用 - copyWechat() { - wx.showToast({ title: '请在派对房联系作者', icon: 'none' }) - }, - - callPhone() { - wx.showToast({ title: '请在派对房联系作者', icon: 'none' }) - }, - - // 返回 - goBack() { - getApp().goBackOrToHome() - }, - - onShareAppMessage() { - const ref = app.getMyReferralCode() - return { - title: 'Soul创业派对 - 关于', - path: ref ? `/pages/about/about?ref=${ref}` : '/pages/about/about' - } - }, - - onShareTimeline() { - const ref = app.getMyReferralCode() - return { title: 'Soul创业派对 - 关于', query: ref ? `ref=${ref}` : '' } - } -}) diff --git a/new-soul/miniprogram/pages/about/about.json b/new-soul/miniprogram/pages/about/about.json deleted file mode 100644 index e90e9960..00000000 --- a/new-soul/miniprogram/pages/about/about.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "usingComponents": {}, - "navigationStyle": "custom" -} diff --git a/new-soul/miniprogram/pages/about/about.wxml b/new-soul/miniprogram/pages/about/about.wxml deleted file mode 100644 index 5966329f..00000000 --- a/new-soul/miniprogram/pages/about/about.wxml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - 关于作者 - - - - - - 加载中... - - - - - {{author.avatar}} - - {{author.name}} - {{author.title}} - {{author.bio}} - - - - - {{item.value}} - {{item.label}} - - - - - - - - {{item}} - - - - - - - {{bookInfo.title}} - - - {{bookInfo.totalChapters}} - 篇章节 - - - 5 - 大篇章 - - - ¥{{bookInfo.price}} - 全书价格 - - - - - {{item.name}} - {{item.chapters}}节 - - - - - - - 联系作者 - - - - Soul派对房 - 每天早上6-9点开播 - - - - 在Soul App搜索"创业实验"或"卡若",加入派对房直接交流 - - - - diff --git a/new-soul/miniprogram/pages/about/about.wxss b/new-soul/miniprogram/pages/about/about.wxss deleted file mode 100644 index 06ad5a00..00000000 --- a/new-soul/miniprogram/pages/about/about.wxss +++ /dev/null @@ -1,43 +0,0 @@ -.page { min-height: 100vh; background: #000; } -.nav-bar { position: fixed; top: 0; left: 0; right: 0; z-index: 100; background: rgba(0,0,0,0.9); backdrop-filter: blur(40rpx); display: flex; align-items: center; justify-content: space-between; padding: 0 32rpx; height: 88rpx; } -.nav-back { width: 72rpx; height: 72rpx; background: #1c1c1e; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 32rpx; color: #fff; } -.nav-title { font-size: 36rpx; font-weight: 600; color: #00CED1; } -.nav-placeholder { width: 72rpx; } -.content { padding: 32rpx; } -.loading-row { text-align: center; color: rgba(255,255,255,0.6); font-size: 28rpx; padding: 48rpx 0; } -.author-card { background: linear-gradient(135deg, #1c1c1e 0%, #2c2c2e 100%); border-radius: 32rpx; padding: 48rpx; text-align: center; margin-bottom: 24rpx; border: 2rpx solid rgba(0,206,209,0.2); } -.author-avatar-wrap { width: 160rpx; height: 160rpx; margin: 0 auto 24rpx; overflow: hidden; border-radius: 50%; border: 4rpx solid rgba(0,206,209,0.3); flex-shrink: 0; } -.author-avatar-img { width: 100%; height: 100%; display: block; } -.author-avatar { width: 100%; height: 100%; border-radius: 50%; background: linear-gradient(135deg, #00CED1, #20B2AA); display: flex; align-items: center; justify-content: center; font-size: 64rpx; color: #fff; font-weight: 700; } -.author-name { font-size: 40rpx; font-weight: 700; color: #fff; display: block; margin-bottom: 8rpx; } -.author-title { font-size: 26rpx; color: #00CED1; display: block; margin-bottom: 24rpx; } -.author-bio { font-size: 26rpx; color: rgba(255,255,255,0.7); line-height: 1.8; display: block; margin-bottom: 32rpx; } -.stats-row { display: flex; justify-content: space-around; padding-top: 32rpx; border-top: 2rpx solid rgba(255,255,255,0.1); } -.stat-item { text-align: center; } -.stat-value { font-size: 36rpx; font-weight: 700; color: #00CED1; display: block; } -.stat-label { font-size: 22rpx; color: rgba(255,255,255,0.5); } -.contact-card { background: #1c1c1e; border-radius: 32rpx; padding: 32rpx; } -.card-title { font-size: 28rpx; font-weight: 600; color: #fff; display: block; margin-bottom: 24rpx; } -.contact-item { display: flex; align-items: center; gap: 24rpx; padding: 24rpx; background: rgba(255,255,255,0.05); border-radius: 16rpx; margin-bottom: 16rpx; } -.contact-item:last-child { margin-bottom: 0; } -.contact-icon { font-size: 40rpx; } -.contact-info { flex: 1; } -.contact-label { font-size: 22rpx; color: rgba(255,255,255,0.5); display: block; } -.contact-value { font-size: 28rpx; color: #fff; } -.contact-btn { padding: 12rpx 24rpx; background: rgba(0,206,209,0.2); color: #00CED1; font-size: 24rpx; border-radius: 16rpx; } - -/* 亮点标签 */ -.highlights { display: flex; flex-wrap: wrap; gap: 16rpx; margin-top: 32rpx; padding-top: 24rpx; border-top: 2rpx solid rgba(255,255,255,0.1); justify-content: center; } -.highlight-tag { display: flex; align-items: center; gap: 8rpx; padding: 12rpx 24rpx; background: rgba(0,206,209,0.15); border-radius: 24rpx; font-size: 24rpx; color: rgba(255,255,255,0.8); } -.tag-icon { color: #00CED1; font-size: 22rpx; } - -/* 书籍信息卡片 */ -.book-info-card { background: #1c1c1e; border-radius: 32rpx; padding: 32rpx; margin-bottom: 24rpx; } -.book-stats { display: flex; justify-content: space-around; padding: 24rpx 0; margin: 16rpx 0; background: rgba(0,0,0,0.3); border-radius: 16rpx; } -.book-stat { text-align: center; } -.book-stat-value { font-size: 36rpx; font-weight: 700; color: #FFD700; display: block; } -.book-stat-label { font-size: 22rpx; color: rgba(255,255,255,0.5); } -.parts-list { display: flex; flex-wrap: wrap; gap: 12rpx; margin-top: 16rpx; } -.part-item { display: flex; align-items: center; gap: 8rpx; padding: 12rpx 20rpx; background: rgba(255,255,255,0.05); border-radius: 12rpx; } -.part-name { font-size: 24rpx; color: rgba(255,255,255,0.8); } -.part-chapters { font-size: 22rpx; color: #00CED1; } diff --git a/new-soul/miniprogram/pages/addresses/addresses.js b/new-soul/miniprogram/pages/addresses/addresses.js deleted file mode 100644 index 0dbd7f7e..00000000 --- a/new-soul/miniprogram/pages/addresses/addresses.js +++ /dev/null @@ -1,137 +0,0 @@ -/** - * 收货地址列表页 - * 参考 Next.js: app/view/my/addresses/page.tsx - */ - -const app = getApp() - -Page({ - data: { - statusBarHeight: 44, - isLoggedIn: false, - addressList: [], - loading: true - }, - - onLoad() { - wx.showShareMenu({ withShareTimeline: true }) - this.setData({ - statusBarHeight: app.globalData.statusBarHeight || 44 - }) - this.checkLogin() - }, - - onShow() { - if (this.data.isLoggedIn) { - this.loadAddresses() - } - }, - - // 检查登录状态 - checkLogin() { - const isLoggedIn = app.globalData.isLoggedIn - const userId = app.globalData.userInfo?.id - - if (!isLoggedIn || !userId) { - wx.showModal({ - title: '需要登录', - content: '请先登录后再管理收货地址', - confirmText: '去登录', - success: (res) => { - if (res.confirm) { - wx.switchTab({ url: '/pages/my/my' }) - } else { - getApp().goBackOrToHome() - } - } - }) - return - } - - this.setData({ isLoggedIn: true }) - this.loadAddresses() - }, - - // 加载地址列表 - async loadAddresses() { - const userId = app.globalData.userInfo?.id - if (!userId) return - - this.setData({ loading: true }) - - try { - const res = await app.request(`/api/miniprogram/user/addresses?userId=${userId}`) - if (res.success && res.list) { - this.setData({ - addressList: res.list, - loading: false - }) - } else { - this.setData({ addressList: [], loading: false }) - } - } catch (e) { - console.error('加载地址列表失败:', e) - this.setData({ loading: false }) - wx.showToast({ title: '加载失败', icon: 'none' }) - } - }, - - // 编辑地址 - editAddress(e) { - const id = e.currentTarget.dataset.id - wx.navigateTo({ url: `/pages/addresses/edit?id=${id}` }) - }, - - // 删除地址 - deleteAddress(e) { - const id = e.currentTarget.dataset.id - - wx.showModal({ - title: '确认删除', - content: '确定要删除该收货地址吗?', - confirmColor: '#FF3B30', - success: async (res) => { - if (res.confirm) { - try { - const result = await app.request(`/api/miniprogram/user/addresses/${id}`, { - method: 'DELETE' - }) - - if (result.success) { - wx.showToast({ title: '删除成功', icon: 'success' }) - this.loadAddresses() - } else { - wx.showToast({ title: result.message || '删除失败', icon: 'none' }) - } - } catch (e) { - console.error('删除地址失败:', e) - wx.showToast({ title: '删除失败', icon: 'none' }) - } - } - } - }) - }, - - // 新增地址 - addAddress() { - wx.navigateTo({ url: '/pages/addresses/edit' }) - }, - - // 返回 - goBack() { - getApp().goBackOrToHome() - }, - - onShareAppMessage() { - const ref = app.getMyReferralCode() - return { - title: 'Soul创业派对 - 地址管理', - path: ref ? `/pages/addresses/addresses?ref=${ref}` : '/pages/addresses/addresses' - } - }, - - onShareTimeline() { - const ref = app.getMyReferralCode() - return { title: 'Soul创业派对 - 地址管理', query: ref ? `ref=${ref}` : '' } - } -}) diff --git a/new-soul/miniprogram/pages/addresses/addresses.json b/new-soul/miniprogram/pages/addresses/addresses.json deleted file mode 100644 index 2e45b65e..00000000 --- a/new-soul/miniprogram/pages/addresses/addresses.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "usingComponents": {}, - "navigationStyle": "custom", - "enablePullDownRefresh": false -} diff --git a/new-soul/miniprogram/pages/addresses/addresses.wxml b/new-soul/miniprogram/pages/addresses/addresses.wxml deleted file mode 100644 index ba84223a..00000000 --- a/new-soul/miniprogram/pages/addresses/addresses.wxml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - 收货地址 - - - - - - - - 加载中... - - - - - - 暂无收货地址 - 点击下方按钮添加 - - - - - - - {{item.name}} - {{item.phone}} - 默认 - - {{item.fullAddress}} - - - ✏️ - 编辑 - - - 🗑️ - 删除 - - - - - - - - - 新增收货地址 - - - diff --git a/new-soul/miniprogram/pages/addresses/addresses.wxss b/new-soul/miniprogram/pages/addresses/addresses.wxss deleted file mode 100644 index 9ff21637..00000000 --- a/new-soul/miniprogram/pages/addresses/addresses.wxss +++ /dev/null @@ -1,217 +0,0 @@ -/** - * 收货地址列表页样式 - */ - -.page { - min-height: 100vh; - background: #000000; - padding-bottom: 200rpx; -} - -/* ===== 导航栏 ===== */ -.nav-bar { - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 100; - background: rgba(0, 0, 0, 0.9); - backdrop-filter: blur(40rpx); - border-bottom: 1rpx solid rgba(255, 255, 255, 0.05); -} - -.nav-bar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 32rpx; - height: 88rpx; -} - -.nav-back { - width: 64rpx; - height: 64rpx; - border-radius: 50%; - background: rgba(255, 255, 255, 0.1); - display: flex; - align-items: center; - justify-content: center; -} - -.nav-back:active { - background: rgba(255, 255, 255, 0.15); -} - -.back-icon { - font-size: 48rpx; - color: #ffffff; - line-height: 1; -} - -.nav-title { - flex: 1; - text-align: center; - font-size: 36rpx; - font-weight: 600; - color: #ffffff; -} - -.nav-placeholder { - width: 64rpx; -} - -/* ===== 内容区 ===== */ -.content { - padding: 32rpx; -} - -/* ===== 加载状态 ===== */ -.loading-state { - padding: 240rpx 0; - text-align: center; -} - -.loading-text { - font-size: 28rpx; - color: rgba(255, 255, 255, 0.4); -} - -/* ===== 空状态 ===== */ -.empty-state { - padding: 240rpx 0; - text-align: center; - display: flex; - flex-direction: column; - align-items: center; -} - -.empty-icon { - font-size: 96rpx; - margin-bottom: 24rpx; - opacity: 0.3; -} - -.empty-text { - font-size: 28rpx; - color: rgba(255, 255, 255, 0.6); - margin-bottom: 16rpx; -} - -.empty-tip { - font-size: 24rpx; - color: rgba(255, 255, 255, 0.4); -} - -/* ===== 地址列表 ===== */ -.address-list { - margin-bottom: 24rpx; -} - -.address-card { - background: #1c1c1e; - border-radius: 24rpx; - border: 2rpx solid rgba(255, 255, 255, 0.05); - padding: 32rpx; - margin-bottom: 24rpx; -} - -/* 地址头部 */ -.address-header { - display: flex; - align-items: center; - gap: 16rpx; - margin-bottom: 16rpx; -} - -.receiver-name { - font-size: 32rpx; - font-weight: 600; - color: #ffffff; -} - -.receiver-phone { - font-size: 28rpx; - color: rgba(255, 255, 255, 0.5); -} - -.default-tag { - font-size: 22rpx; - color: #00CED1; - background: rgba(0, 206, 209, 0.2); - padding: 6rpx 16rpx; - border-radius: 8rpx; - margin-left: auto; -} - -/* 地址文本 */ -.address-text { - font-size: 28rpx; - color: rgba(255, 255, 255, 0.6); - line-height: 1.6; - display: block; - margin-bottom: 24rpx; - padding-bottom: 24rpx; - border-bottom: 2rpx solid rgba(255, 255, 255, 0.05); -} - -/* 操作按钮 */ -.address-actions { - display: flex; - justify-content: flex-end; - gap: 32rpx; -} - -.action-btn { - display: flex; - align-items: center; - gap: 8rpx; - padding: 8rpx 0; -} - -.action-btn:active { - opacity: 0.6; -} - -.edit-btn { - color: #00CED1; -} - -.delete-btn { - color: #FF3B30; -} - -.action-icon { - font-size: 28rpx; -} - -.action-text { - font-size: 28rpx; -} - -/* ===== 新增按钮 ===== */ -.add-btn { - display: flex; - align-items: center; - justify-content: center; - gap: 16rpx; - padding: 32rpx; - background: #00CED1; - border-radius: 24rpx; - font-weight: 600; - margin-top: 48rpx; -} - -.add-btn:active { - opacity: 0.8; - transform: scale(0.98); -} - -.add-icon { - font-size: 36rpx; - color: #000000; -} - -.add-text { - font-size: 32rpx; - color: #000000; -} diff --git a/new-soul/miniprogram/pages/addresses/edit.js b/new-soul/miniprogram/pages/addresses/edit.js deleted file mode 100644 index a7d6925e..00000000 --- a/new-soul/miniprogram/pages/addresses/edit.js +++ /dev/null @@ -1,215 +0,0 @@ -/** - * 地址编辑页(新增/编辑) - * 参考 Next.js: app/view/my/addresses/[id]/page.tsx - */ - -const app = getApp() - -Page({ - data: { - statusBarHeight: 44, - isEdit: false, // 是否为编辑模式 - addressId: null, - - // 表单数据 - name: '', - phone: '', - province: '', - city: '', - district: '', - detail: '', - isDefault: false, - - // 地区选择器 - region: [], - - saving: false - }, - - onLoad(options) { - wx.showShareMenu({ withShareTimeline: true }) - this.setData({ - statusBarHeight: app.globalData.statusBarHeight || 44 - }) - - // 如果有 id 参数,则为编辑模式 - if (options.id) { - this.setData({ - isEdit: true, - addressId: options.id - }) - this.loadAddress(options.id) - } - }, - - // 加载地址详情(编辑模式) - async loadAddress(id) { - wx.showLoading({ title: '加载中...', mask: true }) - - try { - const res = await app.request(`/api/miniprogram/user/addresses/${id}`) - if (res.success && res.data) { - const addr = res.data - this.setData({ - name: addr.name || '', - phone: addr.phone || '', - province: addr.province || '', - city: addr.city || '', - district: addr.district || '', - detail: addr.detail || '', - isDefault: addr.isDefault || false, - region: [addr.province, addr.city, addr.district] - }) - } else { - wx.showToast({ title: '加载失败', icon: 'none' }) - } - } catch (e) { - console.error('加载地址详情失败:', e) - wx.showToast({ title: '加载失败', icon: 'none' }) - } finally { - wx.hideLoading() - } - }, - - // 表单输入 - onNameInput(e) { - this.setData({ name: e.detail.value }) - }, - - onPhoneInput(e) { - this.setData({ phone: e.detail.value.replace(/\D/g, '').slice(0, 11) }) - }, - - onDetailInput(e) { - this.setData({ detail: e.detail.value }) - }, - - // 地区选择 - onRegionChange(e) { - const region = e.detail.value - this.setData({ - region, - province: region[0], - city: region[1], - district: region[2] - }) - }, - - // 切换默认地址 - onDefaultChange(e) { - this.setData({ isDefault: e.detail.value }) - }, - - // 表单验证 - validateForm() { - const { name, phone, province, city, district, detail } = this.data - - if (!name || name.trim().length === 0) { - wx.showToast({ title: '请输入收货人姓名', icon: 'none' }) - return false - } - - if (!phone || phone.length !== 11) { - wx.showToast({ title: '请输入正确的手机号', icon: 'none' }) - return false - } - - if (!province || !city || !district) { - wx.showToast({ title: '请选择省市区', icon: 'none' }) - return false - } - - if (!detail || detail.trim().length === 0) { - wx.showToast({ title: '请输入详细地址', icon: 'none' }) - return false - } - - return true - }, - - // 保存地址 - async saveAddress() { - if (!this.validateForm()) return - if (this.data.saving) return - - this.setData({ saving: true }) - wx.showLoading({ title: '保存中...', mask: true }) - - const { isEdit, addressId, name, phone, province, city, district, detail, isDefault } = this.data - const userId = app.globalData.userInfo?.id - - if (!userId) { - wx.hideLoading() - wx.showToast({ title: '请先登录', icon: 'none' }) - this.setData({ saving: false }) - return - } - - const addressData = { - userId, - name, - phone, - province, - city, - district, - detail, - fullAddress: `${province}${city}${district}${detail}`, - isDefault - } - - try { - let res - if (isEdit) { - // 编辑模式 - PUT 请求 - res = await app.request(`/api/miniprogram/user/addresses/${addressId}`, { - method: 'PUT', - data: addressData - }) - } else { - // 新增模式 - POST 请求 - res = await app.request('/api/miniprogram/user/addresses', { - method: 'POST', - data: addressData - }) - } - - if (res.success) { - wx.hideLoading() - wx.showToast({ - title: isEdit ? '保存成功' : '添加成功', - icon: 'success' - }) - setTimeout(() => { - getApp().goBackOrToHome() - }, 1500) - } else { - wx.hideLoading() - wx.showToast({ title: res.message || '保存失败', icon: 'none' }) - this.setData({ saving: false }) - } - } catch (e) { - console.error('保存地址失败:', e) - wx.hideLoading() - wx.showToast({ title: '保存失败', icon: 'none' }) - this.setData({ saving: false }) - } - }, - - // 返回 - goBack() { - getApp().goBackOrToHome() - }, - - onShareAppMessage() { - const ref = app.getMyReferralCode() - return { - title: 'Soul创业派对 - 编辑地址', - path: ref ? `/pages/addresses/edit?ref=${ref}` : '/pages/addresses/edit' - } - }, - - onShareTimeline() { - const ref = app.getMyReferralCode() - return { title: 'Soul创业派对 - 编辑地址', query: ref ? `ref=${ref}` : '' } - } -}) diff --git a/new-soul/miniprogram/pages/addresses/edit.json b/new-soul/miniprogram/pages/addresses/edit.json deleted file mode 100644 index 2e45b65e..00000000 --- a/new-soul/miniprogram/pages/addresses/edit.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "usingComponents": {}, - "navigationStyle": "custom", - "enablePullDownRefresh": false -} diff --git a/new-soul/miniprogram/pages/addresses/edit.wxml b/new-soul/miniprogram/pages/addresses/edit.wxml deleted file mode 100644 index c5429207..00000000 --- a/new-soul/miniprogram/pages/addresses/edit.wxml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - {{isEdit ? '编辑地址' : '新增地址'}} - - - - - - - - - - 👤 - 收货人 - - - - - - - - 📱 - 手机号 - - - - - - - - 📍 - 所在地区 - - - - {{province || city || district ? province + ' ' + city + ' ' + district : '请选择省市区'}} - - - - - - - - 🏠 - 详细地址 - -