feat: 更新小程序代码 - 2026-02-02
111
README.md
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
# 中老年人陪伴咨询小程序
|
||||||
|
|
||||||
|
基于 React 版本转换的微信小程序,保持样式和功能完全一致。
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
miniprogram/
|
||||||
|
├── app.js # 小程序入口
|
||||||
|
├── app.json # 全局配置
|
||||||
|
├── app.wxss # 全局样式
|
||||||
|
├── project.config.json # 项目配置
|
||||||
|
├── sitemap.json # 站点地图
|
||||||
|
├── images/ # 图标资源
|
||||||
|
│ ├── icon-*.svg # 页面图标
|
||||||
|
│ └── tab-*.png # TabBar 图标(需手动添加)
|
||||||
|
└── pages/
|
||||||
|
├── index/ # 首页 - 遇见(卡片滑动匹配)
|
||||||
|
├── square/ # 广场 - 社交动态
|
||||||
|
├── chat/ # 消息 - 倾听师列表
|
||||||
|
├── chat-detail/ # 聊天详情
|
||||||
|
└── profile/ # 我的 - 个人中心
|
||||||
|
```
|
||||||
|
|
||||||
|
## 功能说明
|
||||||
|
|
||||||
|
### 1. 首页(遇见)
|
||||||
|
- 好友故事横向滚动列表
|
||||||
|
- 卡片堆叠展示用户资料
|
||||||
|
- 左右滑动切换(左滑跳过,右滑喜欢)
|
||||||
|
- 喜欢、语音、选择操作按钮
|
||||||
|
- VIP 解锁弹窗
|
||||||
|
|
||||||
|
### 2. 广场
|
||||||
|
- 社交动态列表
|
||||||
|
- 发布动态(文字+图片)
|
||||||
|
- 点赞、评论功能
|
||||||
|
- 图片预览
|
||||||
|
|
||||||
|
### 3. 消息(倾听师)
|
||||||
|
- 倾听师列表展示
|
||||||
|
- 搜索和筛选功能
|
||||||
|
- 倾听师详情页
|
||||||
|
- 立即咨询功能
|
||||||
|
|
||||||
|
### 4. 聊天详情
|
||||||
|
- 实时聊天界面
|
||||||
|
- 文字/语音输入切换
|
||||||
|
- 表情面板
|
||||||
|
- 自动回复模拟
|
||||||
|
|
||||||
|
### 5. 我的
|
||||||
|
- 用户信息展示
|
||||||
|
- 青草余额和充值
|
||||||
|
- 功能菜单(喜欢、访客、礼物、订单)
|
||||||
|
- 设置和帮助
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 1. 导入项目
|
||||||
|
1. 打开微信开发者工具
|
||||||
|
2. 选择「导入项目」
|
||||||
|
3. 选择 `miniprogram` 目录
|
||||||
|
4. 填写 AppID(可使用测试号)
|
||||||
|
|
||||||
|
### 2. 添加 TabBar 图标
|
||||||
|
TabBar 需要 PNG 格式图标,请参考 `images/README.md` 说明手动添加。
|
||||||
|
|
||||||
|
### 3. 编译运行
|
||||||
|
点击「编译」按钮即可预览小程序。
|
||||||
|
|
||||||
|
## 技术说明
|
||||||
|
|
||||||
|
### 样式转换
|
||||||
|
- React Tailwind CSS → 小程序 WXSS
|
||||||
|
- 使用 rpx 单位适配不同屏幕
|
||||||
|
- CSS 变量转换为具体颜色值
|
||||||
|
|
||||||
|
### 组件转换
|
||||||
|
- React 组件 → 小程序 Page
|
||||||
|
- useState → Page data
|
||||||
|
- useEffect → onLoad/onShow
|
||||||
|
- onClick → bindtap
|
||||||
|
|
||||||
|
### 动画实现
|
||||||
|
- Framer Motion → CSS Animation
|
||||||
|
- 卡片滑动使用 touch 事件 + transform
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 图片资源使用网络图片(Unsplash),需要在小程序后台配置域名白名单
|
||||||
|
2. TabBar 图标需要手动添加 PNG 格式文件
|
||||||
|
3. 部分功能为模拟实现(如支付、语音识别)
|
||||||
|
|
||||||
|
## 域名白名单配置
|
||||||
|
|
||||||
|
在小程序后台「开发」→「开发设置」→「服务器域名」中添加:
|
||||||
|
|
||||||
|
```
|
||||||
|
request合法域名:
|
||||||
|
- https://images.unsplash.com
|
||||||
|
|
||||||
|
downloadFile合法域名:
|
||||||
|
- https://images.unsplash.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 版本信息
|
||||||
|
|
||||||
|
- 小程序基础库:2.25.0+
|
||||||
|
- 转换自 React 版本
|
||||||
|
- 保持视觉和功能一致性
|
||||||
537
app.js
Normal file
|
|
@ -0,0 +1,537 @@
|
||||||
|
// app.js
|
||||||
|
const api = require('./utils/api')
|
||||||
|
const auth = require('./utils/auth')
|
||||||
|
const config = require('./config/index')
|
||||||
|
const { preloadAssets } = require('./utils/assets')
|
||||||
|
|
||||||
|
App({
|
||||||
|
globalData: {
|
||||||
|
// 用户信息
|
||||||
|
userInfo: null,
|
||||||
|
userId: null,
|
||||||
|
isLoggedIn: false,
|
||||||
|
|
||||||
|
// 登录状态检查
|
||||||
|
loginCheckComplete: false,
|
||||||
|
loginCheckCallbacks: [],
|
||||||
|
|
||||||
|
// 余额信息
|
||||||
|
flowerBalance: 0,
|
||||||
|
earnings: 0,
|
||||||
|
|
||||||
|
// 系统信息
|
||||||
|
systemInfo: null,
|
||||||
|
statusBarHeight: 44,
|
||||||
|
navBarHeight: 44, // 导航内容高度(胶囊按钮区域)
|
||||||
|
totalNavHeight: 88, // 总导航栏高度(状态栏+导航内容)
|
||||||
|
navHeight: 88, // 兼容旧代码,等同于 totalNavHeight
|
||||||
|
|
||||||
|
// 审核状态
|
||||||
|
auditStatus: 0, // 1 表示开启(审核中),0 表示关闭(正式环境)
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
config: config
|
||||||
|
},
|
||||||
|
|
||||||
|
async onLaunch(options) {
|
||||||
|
console.log('小程序启动,options:', options)
|
||||||
|
|
||||||
|
// 获取审核状态(同步等待完成,确保页面能获取到正确的审核状态)
|
||||||
|
await this.loadAuditStatus()
|
||||||
|
console.log('审核状态加载完成:', this.globalData.auditStatus)
|
||||||
|
|
||||||
|
const defaultBaseUrl = String(config.API_BASE_URL || '').replace(/\/api$/, '')
|
||||||
|
if (defaultBaseUrl) {
|
||||||
|
this.globalData.baseUrl = defaultBaseUrl
|
||||||
|
if (!wx.getStorageSync('baseUrl')) {
|
||||||
|
wx.setStorageSync('baseUrl', defaultBaseUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理邀请码(爱心值系统)
|
||||||
|
if (options.query && options.query.invite) {
|
||||||
|
wx.setStorageSync('inviteCode', options.query.invite)
|
||||||
|
console.log('保存邀请码:', options.query.invite)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理推荐码(佣金系统)
|
||||||
|
this.handleReferralCode(options)
|
||||||
|
|
||||||
|
// 获取系统信息
|
||||||
|
this.initSystemInfo()
|
||||||
|
|
||||||
|
// 预加载页面素材配置
|
||||||
|
await preloadAssets()
|
||||||
|
|
||||||
|
// 检查登录状态(支持持久化登录状态恢复)
|
||||||
|
this.checkLoginStatus()
|
||||||
|
},
|
||||||
|
|
||||||
|
onShow(options) {
|
||||||
|
console.log('小程序显示,options:', options)
|
||||||
|
|
||||||
|
if (options.query && options.query.invite) {
|
||||||
|
wx.setStorageSync('inviteCode', options.query.invite)
|
||||||
|
console.log('保存邀请码:', options.query.invite)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handleReferralCode(options)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化系统信息
|
||||||
|
*/
|
||||||
|
initSystemInfo() {
|
||||||
|
try {
|
||||||
|
const systemInfo = wx.getSystemInfoSync()
|
||||||
|
const statusBarHeight = systemInfo.statusBarHeight || 44
|
||||||
|
|
||||||
|
// 获取胶囊按钮位置信息
|
||||||
|
const menuButton = wx.getMenuButtonBoundingClientRect()
|
||||||
|
|
||||||
|
// 正确计算导航栏高度:
|
||||||
|
// 导航内容高度 = 胶囊按钮高度 + 上下边距 × 2(上下对称)
|
||||||
|
// 胶囊按钮上边距 = menuButton.top - statusBarHeight
|
||||||
|
const navBarHeight = menuButton.height + (menuButton.top - statusBarHeight) * 2
|
||||||
|
|
||||||
|
// 总导航栏高度 = 状态栏高度 + 导航内容高度
|
||||||
|
const totalNavHeight = statusBarHeight + navBarHeight
|
||||||
|
|
||||||
|
this.globalData.systemInfo = systemInfo
|
||||||
|
this.globalData.statusBarHeight = statusBarHeight
|
||||||
|
this.globalData.navBarHeight = navBarHeight
|
||||||
|
this.globalData.totalNavHeight = totalNavHeight
|
||||||
|
this.globalData.navHeight = totalNavHeight // 兼容旧代码
|
||||||
|
} catch (e) {
|
||||||
|
console.error('获取系统信息失败', e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查登录状态
|
||||||
|
* 支持持久化登录状态恢复(7天免登录)
|
||||||
|
* Requirements: 2.2, 2.3, 2.4
|
||||||
|
*/
|
||||||
|
async checkLoginStatus() {
|
||||||
|
// 1. 先检查本地登录状态
|
||||||
|
if (!auth.isLoggedIn()) {
|
||||||
|
// 无本地登录状态,清除可能残留的数据
|
||||||
|
const cachedUserInfo = wx.getStorageSync(config.STORAGE_KEYS.USER_INFO)
|
||||||
|
if (cachedUserInfo) {
|
||||||
|
console.log('无有效Token,清除残留缓存')
|
||||||
|
auth.clearLoginInfo()
|
||||||
|
}
|
||||||
|
this.globalData.isLoggedIn = false
|
||||||
|
this.globalData.loginCheckComplete = true
|
||||||
|
this.executeLoginCheckCallbacks()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 有本地登录状态,验证服务端Token
|
||||||
|
try {
|
||||||
|
const result = await auth.verifyLogin()
|
||||||
|
|
||||||
|
if (result.valid && result.user) {
|
||||||
|
// Token有效,恢复登录状态
|
||||||
|
this.setUserInfo(result.user)
|
||||||
|
this.globalData.isLoggedIn = true
|
||||||
|
|
||||||
|
// 获取余额
|
||||||
|
this.loadUserBalance()
|
||||||
|
|
||||||
|
console.log('登录状态恢复成功', result.user)
|
||||||
|
} else {
|
||||||
|
// Token无效或过期
|
||||||
|
if (result.expired) {
|
||||||
|
console.log('Token已过期,需要重新登录')
|
||||||
|
}
|
||||||
|
this.handleTokenInvalid()
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('登录状态验证失败', err)
|
||||||
|
// 网络错误时保持本地状态,允许离线使用
|
||||||
|
const localUser = auth.getLocalUserInfo()
|
||||||
|
if (localUser) {
|
||||||
|
this.globalData.userInfo = localUser
|
||||||
|
this.globalData.userId = localUser.id
|
||||||
|
this.globalData.isLoggedIn = true
|
||||||
|
console.log('网络异常,使用本地缓存用户信息')
|
||||||
|
} else {
|
||||||
|
this.handleTokenInvalid()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记登录检查完成
|
||||||
|
this.globalData.loginCheckComplete = true
|
||||||
|
|
||||||
|
// 执行等待中的回调
|
||||||
|
this.executeLoginCheckCallbacks()
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理Token无效的情况
|
||||||
|
* Requirements: 2.4
|
||||||
|
*/
|
||||||
|
handleTokenInvalid() {
|
||||||
|
auth.clearLoginInfo()
|
||||||
|
this.globalData.userInfo = null
|
||||||
|
this.globalData.userId = null
|
||||||
|
this.globalData.isLoggedIn = false
|
||||||
|
this.globalData.flowerBalance = 0
|
||||||
|
this.globalData.earnings = 0
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等待登录检查完成
|
||||||
|
* @returns {Promise} 登录检查完成后resolve
|
||||||
|
*/
|
||||||
|
waitForLoginCheck() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (this.globalData.loginCheckComplete) {
|
||||||
|
resolve(this.globalData.isLoggedIn)
|
||||||
|
} else {
|
||||||
|
this.globalData.loginCheckCallbacks.push(resolve)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行登录检查完成后的回调
|
||||||
|
*/
|
||||||
|
executeLoginCheckCallbacks() {
|
||||||
|
const callbacks = this.globalData.loginCheckCallbacks
|
||||||
|
this.globalData.loginCheckCallbacks = []
|
||||||
|
callbacks.forEach(callback => {
|
||||||
|
callback(this.globalData.isLoggedIn)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户信息
|
||||||
|
* @param {object} userInfo - 用户信息
|
||||||
|
*/
|
||||||
|
setUserInfo(userInfo) {
|
||||||
|
this.globalData.userInfo = userInfo
|
||||||
|
this.globalData.userId = userInfo.id
|
||||||
|
auth.saveUserInfo(userInfo, null) // 只更新用户信息,不更新token
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载用户余额
|
||||||
|
*/
|
||||||
|
async loadUserBalance() {
|
||||||
|
try {
|
||||||
|
const res = await api.user.getBalance()
|
||||||
|
if (res.success && res.data) {
|
||||||
|
this.globalData.flowerBalance = res.data.flower_balance || 0
|
||||||
|
this.globalData.earnings = res.data.earnings || 0
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取余额失败', err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信登录
|
||||||
|
*/
|
||||||
|
async wxLogin() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.login({
|
||||||
|
success: async (loginRes) => {
|
||||||
|
if (loginRes.code) {
|
||||||
|
try {
|
||||||
|
const res = await api.auth.wxLogin(loginRes.code)
|
||||||
|
if (res.success && res.data) {
|
||||||
|
// 计算过期时间(7天后)
|
||||||
|
const expiresAt = new Date()
|
||||||
|
expiresAt.setDate(expiresAt.getDate() + 7)
|
||||||
|
|
||||||
|
// 保存登录信息
|
||||||
|
auth.saveUserInfo(res.data.user, res.data.token, expiresAt.toISOString())
|
||||||
|
|
||||||
|
// 设置全局状态
|
||||||
|
this.globalData.userInfo = res.data.user
|
||||||
|
this.globalData.userId = res.data.user.id
|
||||||
|
this.globalData.isLoggedIn = true
|
||||||
|
|
||||||
|
// 获取余额
|
||||||
|
this.loadUserBalance()
|
||||||
|
|
||||||
|
resolve(res.data)
|
||||||
|
} else {
|
||||||
|
reject(res)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject({ message: '微信登录失败' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号登录
|
||||||
|
* @param {string} phone - 手机号
|
||||||
|
* @param {string} code - 验证码
|
||||||
|
*/
|
||||||
|
async phoneLogin(phone, code) {
|
||||||
|
try {
|
||||||
|
const res = await api.auth.phoneLogin(phone, code)
|
||||||
|
if (res.success && res.data) {
|
||||||
|
// 计算过期时间(7天后)
|
||||||
|
const expiresAt = new Date()
|
||||||
|
expiresAt.setDate(expiresAt.getDate() + 7)
|
||||||
|
|
||||||
|
// 保存登录信息
|
||||||
|
auth.saveUserInfo(res.data.user, res.data.token, expiresAt.toISOString())
|
||||||
|
|
||||||
|
// 设置全局状态
|
||||||
|
this.globalData.userInfo = res.data.user
|
||||||
|
this.globalData.userId = res.data.user.id
|
||||||
|
this.globalData.isLoggedIn = true
|
||||||
|
|
||||||
|
// 获取余额
|
||||||
|
this.loadUserBalance()
|
||||||
|
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
throw res
|
||||||
|
} catch (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信手机号快速登录
|
||||||
|
* @param {string} code - 微信getPhoneNumber返回的code
|
||||||
|
* Requirements: 1.3, 1.4, 1.5, 2.1
|
||||||
|
*/
|
||||||
|
async wxPhoneLogin(code, loginCode) {
|
||||||
|
try {
|
||||||
|
const result = await auth.wxPhoneLogin(code, loginCode)
|
||||||
|
|
||||||
|
if (result.success && result.user) {
|
||||||
|
// 设置全局状态
|
||||||
|
this.globalData.userInfo = result.user
|
||||||
|
this.globalData.userId = result.user.id
|
||||||
|
this.globalData.isLoggedIn = true
|
||||||
|
|
||||||
|
// 获取余额
|
||||||
|
this.loadUserBalance()
|
||||||
|
|
||||||
|
console.log('微信手机号快速登录成功', result.user)
|
||||||
|
|
||||||
|
return { token: auth.getToken(), user: result.user }
|
||||||
|
}
|
||||||
|
throw { message: result.error || '登录失败' }
|
||||||
|
} catch (err) {
|
||||||
|
console.error('微信手机号快速登录失败', err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录
|
||||||
|
* Requirements: 2.5
|
||||||
|
*/
|
||||||
|
async logout() {
|
||||||
|
await auth.logout()
|
||||||
|
|
||||||
|
// 清除全局状态
|
||||||
|
this.globalData.userInfo = null
|
||||||
|
this.globalData.userId = null
|
||||||
|
this.globalData.isLoggedIn = false
|
||||||
|
this.globalData.flowerBalance = 0
|
||||||
|
this.globalData.earnings = 0
|
||||||
|
|
||||||
|
console.log('已退出登录,清除所有本地状态')
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新用户信息
|
||||||
|
*/
|
||||||
|
async refreshUserInfo() {
|
||||||
|
try {
|
||||||
|
const res = await api.auth.getCurrentUser()
|
||||||
|
if (res.success && res.data) {
|
||||||
|
this.setUserInfo(res.data)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('刷新用户信息失败', err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否需要登录
|
||||||
|
* @param {boolean} showTip - 是否显示提示
|
||||||
|
*/
|
||||||
|
checkNeedLogin(showTip = true) {
|
||||||
|
if (!this.globalData.isLoggedIn) {
|
||||||
|
if (showTip) {
|
||||||
|
wx.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '请先登录后再操作',
|
||||||
|
confirmText: '去登录',
|
||||||
|
confirmColor: '#b06ab3',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
// 跳转到个人中心进行登录
|
||||||
|
wx.switchTab({
|
||||||
|
url: '/pages/profile/profile'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证当前Token是否有效
|
||||||
|
* 用于页面需要确认登录状态时调用
|
||||||
|
* Requirements: 2.2, 2.4
|
||||||
|
* @returns {Promise<boolean>} Token是否有效
|
||||||
|
*/
|
||||||
|
async validateToken() {
|
||||||
|
if (!auth.isLoggedIn()) {
|
||||||
|
this.globalData.isLoggedIn = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await auth.verifyLogin()
|
||||||
|
|
||||||
|
if (result.valid && result.user) {
|
||||||
|
// Token有效,更新用户信息
|
||||||
|
this.globalData.userInfo = result.user
|
||||||
|
this.globalData.userId = result.user.id
|
||||||
|
this.globalData.isLoggedIn = true
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
// Token无效
|
||||||
|
this.handleTokenInvalid()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Token验证失败', err)
|
||||||
|
this.handleTokenInvalid()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录状态(等待初始化完成)
|
||||||
|
* 用于页面onLoad时获取准确的登录状态
|
||||||
|
* @returns {Promise<boolean>} 是否已登录
|
||||||
|
*/
|
||||||
|
async getLoginStatus() {
|
||||||
|
await this.waitForLoginCheck()
|
||||||
|
return this.globalData.isLoggedIn
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载审核状态
|
||||||
|
*/
|
||||||
|
async loadAuditStatus() {
|
||||||
|
try {
|
||||||
|
const res = await api.common.getAuditStatus()
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
this.globalData.auditStatus = Number(res.data.auditStatus || 0)
|
||||||
|
console.log('获取审核状态成功:', this.globalData.auditStatus)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取审核状态失败', err)
|
||||||
|
// 失败时默认为 0(正式环境),或根据需要设为 1(保守方案)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理推荐码(佣金系统)
|
||||||
|
* 支持场景:
|
||||||
|
* 1. 小程序分享:path?referralCode=ABC12345
|
||||||
|
* 2. 朋友圈分享:query.referralCode
|
||||||
|
* 3. 小程序码:scene=r=ABC12345
|
||||||
|
*/
|
||||||
|
handleReferralCode(options) {
|
||||||
|
let referralCode = null
|
||||||
|
|
||||||
|
if (options.query && options.query.referralCode) {
|
||||||
|
referralCode = options.query.referralCode
|
||||||
|
console.log('从query获取推荐码(referralCode):', referralCode)
|
||||||
|
} else if (options.query && options.query.ref) {
|
||||||
|
referralCode = options.query.ref
|
||||||
|
console.log('从query获取推荐码(ref):', referralCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!referralCode && options.scene) {
|
||||||
|
referralCode = this.parseSceneReferralCode(options.scene)
|
||||||
|
if (referralCode) {
|
||||||
|
console.log('从scene获取推荐码:', referralCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (referralCode) {
|
||||||
|
this.globalData.pendingReferralCode = referralCode
|
||||||
|
wx.setStorageSync('pendingReferralCode', referralCode)
|
||||||
|
console.log('推荐码已保存到本地:', referralCode)
|
||||||
|
|
||||||
|
const isLoggedIn = this.globalData.isLoggedIn || !!wx.getStorageSync('auth_token')
|
||||||
|
if (isLoggedIn) {
|
||||||
|
console.log('用户已登录,发起即时静默绑定')
|
||||||
|
const userId = this.globalData.userId || wx.getStorageSync('user_id')
|
||||||
|
const token = wx.getStorageSync('auth_token')
|
||||||
|
if (userId && token) {
|
||||||
|
auth.checkAndBindReferralCode(userId, token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析scene参数中的推荐码
|
||||||
|
* scene格式:r=ABC12345
|
||||||
|
*/
|
||||||
|
parseSceneReferralCode(scene) {
|
||||||
|
if (!scene) return null
|
||||||
|
|
||||||
|
try {
|
||||||
|
const decoded = decodeURIComponent(scene)
|
||||||
|
const match = decoded.match(/r=([A-Z0-9]+)/)
|
||||||
|
return match ? match[1] : null
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析scene失败:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局转发配置
|
||||||
|
* 用户转发小程序时的默认配置
|
||||||
|
*/
|
||||||
|
onShareAppMessage() {
|
||||||
|
return {
|
||||||
|
title: '欢迎来到心伴俱乐部',
|
||||||
|
desc: '随时可聊 一直陪伴',
|
||||||
|
path: '/pages/index/index',
|
||||||
|
imageUrl: '/images/icon-heart-new.png'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局分享到朋友圈配置
|
||||||
|
*/
|
||||||
|
onShareTimeline() {
|
||||||
|
return {
|
||||||
|
title: '欢迎来到心伴俱乐部 - 随时可聊 一直陪伴',
|
||||||
|
imageUrl: '/images/icon-heart-new.png'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
117
app.json
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
{
|
||||||
|
"pages": [
|
||||||
|
"pages/index/index",
|
||||||
|
"pages/entertainment/entertainment",
|
||||||
|
"pages/singles-party/singles-party",
|
||||||
|
"pages/city-selector/city-selector",
|
||||||
|
"pages/interest-partner/interest-partner",
|
||||||
|
"pages/city-activities/city-activities",
|
||||||
|
"pages/activity-detail/activity-detail",
|
||||||
|
"pages/outdoor-activities/outdoor-activities",
|
||||||
|
"pages/theme-travel/theme-travel",
|
||||||
|
"pages/happy-school/happy-school",
|
||||||
|
"pages/companion-chat/companion-chat",
|
||||||
|
"pages/service/service",
|
||||||
|
"pages/service-provider-detail/service-provider-detail",
|
||||||
|
"pages/chat/chat",
|
||||||
|
"pages/chat-detail/chat-detail",
|
||||||
|
"pages/profile/profile",
|
||||||
|
"pages/login/login",
|
||||||
|
"pages/recharge/recharge",
|
||||||
|
"pages/character-detail/character-detail",
|
||||||
|
"pages/counselor-detail/counselor-detail",
|
||||||
|
"pages/orders/orders",
|
||||||
|
"pages/order-detail/order-detail",
|
||||||
|
"pages/my-activities/my-activities",
|
||||||
|
"pages/edit-profile/edit-profile",
|
||||||
|
"pages/customer-management/customer-management",
|
||||||
|
"pages/withdraw/withdraw",
|
||||||
|
"pages/commission/commission",
|
||||||
|
"pages/promote/promote",
|
||||||
|
"pages/backpack/backpack",
|
||||||
|
"pages/square/square",
|
||||||
|
"pages/workbench/workbench",
|
||||||
|
"pages/companion-apply/companion-apply",
|
||||||
|
"pages/companion-orders/companion-orders",
|
||||||
|
"pages/agreement/agreement",
|
||||||
|
"pages/medical-apply/medical-apply",
|
||||||
|
"pages/housekeeping-apply/housekeeping-apply",
|
||||||
|
"pages/eldercare-apply/eldercare-apply",
|
||||||
|
"pages/entertainment-apply/entertainment-apply",
|
||||||
|
"pages/invite/invite",
|
||||||
|
"pages/love-transactions/love-transactions",
|
||||||
|
"pages/gift-shop/gift-shop",
|
||||||
|
"pages/gift-detail/gift-detail",
|
||||||
|
"pages/gift-exchanges/gift-exchanges",
|
||||||
|
"pages/referrals/referrals",
|
||||||
|
"pages/referrals/orders/orders",
|
||||||
|
"pages/withdraw-records/withdraw-records",
|
||||||
|
"pages/support/support",
|
||||||
|
"pages/settings/settings",
|
||||||
|
"pages/team/team",
|
||||||
|
"pages/performance/performance",
|
||||||
|
"pages/promote-poster/promote-poster",
|
||||||
|
"pages/academy/list/list",
|
||||||
|
"pages/academy/detail/detail",
|
||||||
|
"pages/webview/webview",
|
||||||
|
"pages/brand/brand",
|
||||||
|
"pages/eldercare/eldercare",
|
||||||
|
"pages/custom/custom",
|
||||||
|
"pages/notices/notices",
|
||||||
|
"pages/notices/detail/detail"
|
||||||
|
],
|
||||||
|
"subpackages": [
|
||||||
|
{
|
||||||
|
"root": "subpackages/cooperation",
|
||||||
|
"pages": [
|
||||||
|
"pages/cooperation/cooperation"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"__usePrivacyCheck__": false,
|
||||||
|
"window": {
|
||||||
|
"navigationBarBackgroundColor": "#E8C3D4",
|
||||||
|
"navigationBarTitleText": "",
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
"backgroundColor": "#E8C3D4",
|
||||||
|
"backgroundTextStyle": "dark",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
},
|
||||||
|
"tabBar": {
|
||||||
|
"custom": false,
|
||||||
|
"color": "#a58aa5",
|
||||||
|
"selectedColor": "#b06ab3",
|
||||||
|
"backgroundColor": "#ffffff",
|
||||||
|
"borderStyle": "white",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"pagePath": "pages/index/index",
|
||||||
|
"text": "陪伴"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/entertainment/entertainment",
|
||||||
|
"text": "文娱"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/service/service",
|
||||||
|
"text": "服务"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/chat/chat",
|
||||||
|
"text": "消息"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/profile/profile",
|
||||||
|
"text": "我的"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"style": "v2",
|
||||||
|
"sitemapLocation": "sitemap.json",
|
||||||
|
"lazyCodeLoading": "requiredComponents",
|
||||||
|
"permission": {
|
||||||
|
"scope.writePhotosAlbum": {
|
||||||
|
"desc": "保存二维码到相册"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
200
app.wxss
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
/* 统一导航栏样式 */
|
||||||
|
.unified-header {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 194rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-bottom: 2rpx solid #f9fafb;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 32rpx 20rpx;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unified-header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
width: 160rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unified-header-title {
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #101828;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unified-header-right {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unified-back-icon {
|
||||||
|
width: 56rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unified-back-text {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #101828;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 隐藏原生tabBar边框 */
|
||||||
|
.wx-tabbar::before {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全局样式 */
|
||||||
|
page {
|
||||||
|
--primary: #914584;
|
||||||
|
--primary-light: #E8C3D4;
|
||||||
|
--background: #ffffff;
|
||||||
|
--foreground: #1a1a1a;
|
||||||
|
--muted: #ececf0;
|
||||||
|
--muted-foreground: #717182;
|
||||||
|
--border: rgba(0, 0, 0, 0.1);
|
||||||
|
--radius: 20rpx;
|
||||||
|
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
background-color: var(--primary-light);
|
||||||
|
color: var(--foreground);
|
||||||
|
font-size: 28rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100vw;
|
||||||
|
overflow-x: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全局盒模型 */
|
||||||
|
view, text, image, scroll-view, input {
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-reset {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
line-height: inherit;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.btn-reset::after { border: none; }
|
||||||
|
|
||||||
|
.safe-bottom {
|
||||||
|
padding-bottom: constant(safe-area-inset-bottom);
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 通用类 */
|
||||||
|
.container {
|
||||||
|
padding: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-20 {
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-30 {
|
||||||
|
gap: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-full {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow {
|
||||||
|
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 卡片样式 */
|
||||||
|
.card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
box-shadow: 0 8rpx 40rpx rgba(59, 64, 86, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮样式 */
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(135deg, #914584 0%, #B378FE 100%);
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
padding: 24rpx 48rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
padding: 24rpx 48rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 头像样式 */
|
||||||
|
.avatar {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-sm {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-lg {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动画 */
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.5; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-pulse {
|
||||||
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||||
|
}
|
||||||
61
components/icon/icon.js
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
const svgToDataUrl = (svg) => {
|
||||||
|
const encoded = encodeURIComponent(svg)
|
||||||
|
.replace(/'/g, '%27')
|
||||||
|
.replace(/"/g, '%22');
|
||||||
|
return `data:image/svg+xml,${encoded}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ICONS = {
|
||||||
|
'chevron-left': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"/></svg>',
|
||||||
|
'chevron-right': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18l6-6-6-6"/></svg>',
|
||||||
|
'settings': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1a2 2 0 0 1-1.4 3.4h-.2a1.7 1.7 0 0 0-1.7 1.2 2 2 0 0 1-3.8 0 1.7 1.7 0 0 0-1.6-1.2h-.2a2 2 0 0 1-1.4-3.4l.1-.1a1.7 1.7 0 0 0 .3-1.9 1.7 1.7 0 0 0-1.5-1H6.9a2 2 0 0 1 0-4h.2a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.9l-.1-.1A2 2 0 0 1 9.6 2h.2a1.7 1.7 0 0 0 1.6-1.2 2 2 0 0 1 3.8 0A1.7 1.7 0 0 0 16.8 2h.2a2 2 0 0 1 1.4 3.4l-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.5 1h.2a2 2 0 0 1 0 4h-.2a1.7 1.7 0 0 0-1.5 1z"/></svg>',
|
||||||
|
'crown': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="CURRENT"><path d="M3 7l4 3 5-6 5 6 4-3-2 14H5L3 7z"/></svg>',
|
||||||
|
'gift': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 12 20 22 4 22 4 12"></polyline><rect width="20" height="5" x="2" y="7"></rect><line x1="12" y1="22" x2="12" y2="7"></line><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"></path><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"></path></svg>',
|
||||||
|
'diamond': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3h12l4 6-10 13L2 9Z"></path><path d="M11 3 8 9l4 13 4-13-3-6"></path><path d="M2 9h20"></path></svg>',
|
||||||
|
'clock': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>',
|
||||||
|
'wallet': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 7V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1"/><path d="M19 12H16a2 2 0 0 0 0 4h3v-4z"/></svg>',
|
||||||
|
'sprout': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 20h10"/><path d="M10 20c0-6 1-10 5-14"/><path d="M9 12c-2 0-4-2-4-4 2 0 4 2 4 4z"/><path d="M15 8c2 0 4-2 4-4-2 0-4 2-4 4z"/></svg>',
|
||||||
|
'banknote': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><path d="M6 10h.01M18 14h.01"/><circle cx="12" cy="12" r="2"/></svg>',
|
||||||
|
'shopping-bag': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2l1 4h10l1-4"/><path d="M3 6h18l-1.5 16h-15L3 6z"/></svg>',
|
||||||
|
'users': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>',
|
||||||
|
'backpack': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7a5 5 0 0 1 10 0"/><path d="M6 10h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2z"/><path d="M8 16h8"/><path d="M9 10V8a3 3 0 0 1 6 0v2"/></svg>',
|
||||||
|
'share': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"/><path d="M16 6l-4-4-4 4"/><path d="M12 2v14"/></svg>',
|
||||||
|
'briefcase': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 7V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/><path d="M2 12h20"/></svg>',
|
||||||
|
'headphones': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18v-6a9 9 0 0 1 18 0v6"/><path d="M21 19a2 2 0 0 1-2 2h-1v-6h3v2z"/><path d="M3 19a2 2 0 0 0 2 2h1v-6H3v2z"/></svg>',
|
||||||
|
'package': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16.5 9.4 7.5 4.2"/><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4a2 2 0 0 0 1-1.73z"/><path d="M3.3 7.9 12 13l8.7-5.1"/><path d="M12 22V13"/></svg>',
|
||||||
|
'logout': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5"/><path d="M21 12H9"/></svg>',
|
||||||
|
'copy': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><rect x="2" y="2" width="13" height="13" rx="2"/></svg>',
|
||||||
|
'image': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>',
|
||||||
|
'share-2': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>',
|
||||||
|
'scan': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7V5a2 2 0 0 1 2-2h2"/><path d="M16 3h2a2 2 0 0 1 2 2v2"/><path d="M20 17v2a2 2 0 0 1-2 2h-2"/><path d="M8 21H6a2 2 0 0 1-2-2v-2"/><path d="M7 12h10"/></svg>',
|
||||||
|
'camera': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 4h-5L8 6H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-3l-1.5-2z"/><circle cx="12" cy="13" r="3"/></svg>',
|
||||||
|
'clipboard': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/></svg>',
|
||||||
|
'trending-up': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline><polyline points="17 6 23 6 23 12"></polyline></svg>',
|
||||||
|
'map-pin': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 1 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>',
|
||||||
|
'heart': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>',
|
||||||
|
'heart-filled': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="CURRENT"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>',
|
||||||
|
'flame': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="CURRENT" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3 1.06.56 2.09 1.5 2.5 3.5m.5-9c0 4.5-4 9-4 9a2 2 0 0 0 4 0c0-2.5 2-4.5 2-7.5l-.5-1.5z"></path></svg>',
|
||||||
|
'flame-hot': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" fill="CURRENT"><path d="M510.1 510.1l3.8 3.8-3.8-3.8zM514.3 509.6l-4.7 4.7c1.9-1.5 3.4-3 4.7-4.7zM712.2 230.6c21.3 47.2 24.5 125.2-19.6 162.7C621 118.1 442 64.4 442 64.4c21.3 139.9-74.8 293-169.2 408.4-3.2-55.3-6.6-92.7-37.4-149.7C228.8 425.6 150.8 507 128 609.5c-27.6 141.6 22.8 240.9 214.7 350-60.2-125.2-27.6-196.9 19.6-261.9 50.4-74.8 63.6-146.5 63.6-146.5s40.6 50.4 24.5 130.1c68.2-78 81.4-203.5 71.7-249 156.1 109.1 226 350 135 524.1 481.4-275 118.5-683.5 55.1-725.7z"/></svg>'
|
||||||
|
};
|
||||||
|
|
||||||
|
Component({
|
||||||
|
properties: {
|
||||||
|
name: { type: String, value: '' },
|
||||||
|
size: { type: Number, value: 24 },
|
||||||
|
color: { type: String, value: '#111827' }
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
style: ''
|
||||||
|
},
|
||||||
|
observers: {
|
||||||
|
'name,size,color': function(name, size, color) {
|
||||||
|
const raw = ICONS[name] || '';
|
||||||
|
const svg = raw.replace(/CURRENT/g, color || '#111827');
|
||||||
|
const url = svg ? svgToDataUrl(svg) : '';
|
||||||
|
const s = Number(size || 24);
|
||||||
|
this.setData({
|
||||||
|
style: `width:${s}rpx;height:${s}rpx;${url ? `background-image:url('${url}');` : ''}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
3
components/icon/icon.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"component": true
|
||||||
|
}
|
||||||
1
components/icon/icon.wxml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<view class="icon" style="{{style}}" />
|
||||||
6
components/icon/icon.wxss
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
59
config/index.js
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* 小程序配置文件
|
||||||
|
* 包含API地址、环境配置等
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 环境配置
|
||||||
|
const ENV = {
|
||||||
|
// 开发环境
|
||||||
|
development: {
|
||||||
|
API_BASE_URL: 'http://localhost:3000/api',
|
||||||
|
WS_URL: 'ws://localhost:3000',
|
||||||
|
DEBUG: true,
|
||||||
|
TEST_MODE: true // 测试模式:充值不走真实支付
|
||||||
|
},
|
||||||
|
// 测试环境
|
||||||
|
staging: {
|
||||||
|
API_BASE_URL: 'https://test-api.maimanji.com/api',
|
||||||
|
WS_URL: 'wss://test-api.maimanji.com',
|
||||||
|
DEBUG: true,
|
||||||
|
TEST_MODE: true // 测试模式:充值不走真实支付
|
||||||
|
},
|
||||||
|
// 生产环境
|
||||||
|
production: {
|
||||||
|
API_BASE_URL: 'https://ai-c.maimanji.com/api',
|
||||||
|
WS_URL: 'wss://ai-c.maimanji.com',
|
||||||
|
DEBUG: false,
|
||||||
|
TEST_MODE: false // 关闭测试模式,使用真实微信支付(后端测试支付接口有数据库错误)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前环境 - 可根据需要切换
|
||||||
|
// development: 本地开发 staging: 测试环境 production: 正式环境
|
||||||
|
const CURRENT_ENV = 'production'
|
||||||
|
|
||||||
|
// 导出配置
|
||||||
|
const config = {
|
||||||
|
...ENV[CURRENT_ENV],
|
||||||
|
ENV: CURRENT_ENV,
|
||||||
|
|
||||||
|
// 存储键名
|
||||||
|
STORAGE_KEYS: {
|
||||||
|
TOKEN: 'auth_token',
|
||||||
|
REFRESH_TOKEN: 'refresh_token',
|
||||||
|
USER_INFO: 'user_info',
|
||||||
|
USER_ID: 'user_id',
|
||||||
|
TOKEN_EXPIRY: 'token_expiry' // Token过期时间
|
||||||
|
},
|
||||||
|
|
||||||
|
// 请求超时时间(毫秒)
|
||||||
|
REQUEST_TIMEOUT: 30000,
|
||||||
|
|
||||||
|
// 分页默认配置
|
||||||
|
PAGE_SIZE: 20,
|
||||||
|
|
||||||
|
// 版本号
|
||||||
|
VERSION: '1.0.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config
|
||||||
34
git-push.bat
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
echo ========================
|
||||||
|
echo Git 提交脚本
|
||||||
|
echo ========================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
echo [1/5] 添加所有更改...
|
||||||
|
git add -A
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [2/5] 提交更改...
|
||||||
|
git commit -m "feat: 更新小程序代码 - 2026-02-02"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [3/5] 添加 tag...
|
||||||
|
git tag -a v1.0.0 -m "Version 1.0.0 - 2026-02-02"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [4/5] 推送到远程仓库...
|
||||||
|
echo 请输入密码: zy12345678
|
||||||
|
git push https://zhiyun:zy12345678@git.maimanji.com/adminzy/ai-c.git master --force
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [5/5] 推送 tag...
|
||||||
|
git push https://zhiyun:zy12345678@git.maimanji.com/adminzy/ai-c.git v1.0.0
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================
|
||||||
|
echo 完成!
|
||||||
|
echo ========================
|
||||||
|
pause
|
||||||
33
git-push.sh
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Git 提交脚本
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
echo "========================"
|
||||||
|
echo "Git 提交脚本"
|
||||||
|
echo "========================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "[1/5] 添加所有更改..."
|
||||||
|
git add -A
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[2/5] 提交更改..."
|
||||||
|
git commit -m "feat: 更新小程序代码 - 2026-02-02"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[3/5] 添加 tag..."
|
||||||
|
git tag -a v1.0.0 -m "Version 1.0.0 - 2026-02-02"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[4/5] 推送到远程仓库..."
|
||||||
|
git push https://zhiyun:zy12345678@git.maimanji.com/adminzy/ai-c.git master --force
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[5/5] 推送 tag..."
|
||||||
|
git push https://zhiyun:zy12345678@git.maimanji.com/adminzy/ai-c.git v1.0.0
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================"
|
||||||
|
echo "完成!"
|
||||||
|
echo "========================"
|
||||||
74
images/README.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# 图标资源说明
|
||||||
|
|
||||||
|
✅ 页面图标已生成完成(SVG 格式)
|
||||||
|
|
||||||
|
## TabBar 图标(需要手动添加 PNG 格式,81x81px)
|
||||||
|
|
||||||
|
由于微信小程序 TabBar 只支持 PNG 格式,需要手动创建以下图标:
|
||||||
|
|
||||||
|
- `tab-heart.png` - 遇见(未选中,灰色 #999999)
|
||||||
|
- `tab-heart-active.png` - 遇见(选中,紫色 #914584)
|
||||||
|
- `tab-compass.png` - 广场(未选中)
|
||||||
|
- `tab-compass-active.png` - 广场(选中)
|
||||||
|
- `tab-message.png` - 消息(未选中)
|
||||||
|
- `tab-message-active.png` - 消息(选中)
|
||||||
|
- `tab-user.png` - 我的(未选中)
|
||||||
|
- `tab-user-active.png` - 我的(选中)
|
||||||
|
|
||||||
|
### 快速生成 TabBar 图标方法:
|
||||||
|
1. 访问 https://lucide.dev/icons/
|
||||||
|
2. 搜索对应图标(heart, compass, message-circle, user)
|
||||||
|
3. 下载 SVG 后使用在线工具转换为 PNG
|
||||||
|
4. 推荐工具:https://svgtopng.com/
|
||||||
|
|
||||||
|
## 页面图标(SVG 格式推荐)
|
||||||
|
- `icon-bell.svg` - 通知铃铛
|
||||||
|
- `icon-chevron-left.svg` - 左箭头
|
||||||
|
- `icon-chevron-right.svg` - 右箭头
|
||||||
|
- `icon-chevron-down.svg` - 下箭头
|
||||||
|
- `icon-heart.svg` - 爱心(空心)
|
||||||
|
- `icon-heart-filled.svg` - 爱心(实心)
|
||||||
|
- `icon-voice.svg` - 语音/声波
|
||||||
|
- `icon-check.svg` - 勾选
|
||||||
|
- `icon-refresh.svg` - 刷新
|
||||||
|
- `icon-lock.svg` - 锁
|
||||||
|
- `icon-grass.svg` - 青草/植物
|
||||||
|
- `icon-plus.svg` - 加号
|
||||||
|
- `icon-more.svg` - 更多(三个点)
|
||||||
|
- `icon-comment.svg` - 评论
|
||||||
|
- `icon-headphones.svg` - 耳机
|
||||||
|
- `icon-search.svg` - 搜索
|
||||||
|
- `icon-mic.svg` - 麦克风
|
||||||
|
- `icon-star.svg` - 星星
|
||||||
|
- `icon-verified.svg` - 认证标识
|
||||||
|
- `icon-phone.svg` - 电话
|
||||||
|
- `icon-back.svg` - 返回
|
||||||
|
- `icon-keyboard.svg` - 键盘
|
||||||
|
- `icon-emoji.svg` - 表情
|
||||||
|
- `icon-send.svg` - 发送
|
||||||
|
- `icon-settings.svg` - 设置
|
||||||
|
- `icon-camera.svg` - 相机
|
||||||
|
- `icon-eye.svg` - 眼睛
|
||||||
|
- `icon-gift.svg` - 礼物
|
||||||
|
- `icon-order.svg` - 订单
|
||||||
|
- `icon-help.svg` - 帮助
|
||||||
|
- `icon-feedback.svg` - 反馈
|
||||||
|
- `icon-info.svg` - 信息
|
||||||
|
|
||||||
|
## 图标颜色建议
|
||||||
|
- 未选中状态:#999999
|
||||||
|
- 选中状态:#914584(主题紫色)
|
||||||
|
- 白色图标:#FFFFFF
|
||||||
|
|
||||||
|
## 获取图标
|
||||||
|
可以从以下网站获取免费图标:
|
||||||
|
1. [Lucide Icons](https://lucide.dev/) - 推荐,与 React 版本一致
|
||||||
|
2. [Heroicons](https://heroicons.com/)
|
||||||
|
3. [Feather Icons](https://feathericons.com/)
|
||||||
|
4. [阿里巴巴矢量图标库](https://www.iconfont.cn/)
|
||||||
|
|
||||||
|
## 快速生成方法
|
||||||
|
1. 访问 https://lucide.dev/icons/
|
||||||
|
2. 搜索对应图标名称
|
||||||
|
3. 下载 SVG 格式
|
||||||
|
4. 修改颜色后保存到此目录
|
||||||
BIN
images/btn-consult.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/btn-text-consult.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
images/chat-action-camera.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
images/chat-action-gift.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
images/chat-action-photo.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
images/chat-input-emoji.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
images/chat-input-plus.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
images/chat-input-voice.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
5
images/default-avatar.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
|
||||||
|
<circle cx="50" cy="50" r="50" fill="#e0e0e0"/>
|
||||||
|
<circle cx="50" cy="38" r="18" fill="#999"/>
|
||||||
|
<ellipse cx="50" cy="80" rx="28" ry="22" fill="#999"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 248 B |
3
images/figma-gift-shop-chevron-right.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M6.00037 12.0004L10.0004 8.0003L6.00037 4.00024" stroke="white" stroke-width="1.33197" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 248 B |
36
images/figma-gift-shop-decor-icon.svg
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<svg width="71" height="71" viewBox="0 0 71 71" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_i_162_7202)">
|
||||||
|
<mask id="path-1-inside-1_162_7202" fill="white">
|
||||||
|
<path d="M0 16.1915C0 7.2492 7.24919 0 16.1915 0H54.8083C63.7506 0 70.9998 7.24919 70.9998 16.1915V54.8083C70.9998 63.7506 63.7506 70.9998 54.8083 70.9998H16.1915C7.2492 70.9998 0 63.7506 0 54.8083V16.1915Z"/>
|
||||||
|
</mask>
|
||||||
|
<path d="M0 16.1915C0 7.2492 7.24919 0 16.1915 0H54.8083C63.7506 0 70.9998 7.24919 70.9998 16.1915V54.8083C70.9998 63.7506 63.7506 70.9998 54.8083 70.9998H16.1915C7.2492 70.9998 0 63.7506 0 54.8083V16.1915Z" fill="white" fill-opacity="0.2"/>
|
||||||
|
<path d="M16.1915 0V1.11073H54.8083V0V-1.11073H16.1915V0ZM70.9998 16.1915H69.8891V54.8083H70.9998H72.1105V16.1915H70.9998ZM54.8083 70.9998V69.8891H16.1915V70.9998V72.1105H54.8083V70.9998ZM0 54.8083H1.11073V16.1915H0H-1.11073V54.8083H0ZM16.1915 70.9998V69.8891C7.86264 69.8891 1.11073 63.1372 1.11073 54.8083H0H-1.11073C-1.11073 64.364 6.63577 72.1105 16.1915 72.1105V70.9998ZM70.9998 54.8083H69.8891C69.8891 63.1372 63.1372 69.8891 54.8083 69.8891V70.9998V72.1105C64.364 72.1105 72.1105 64.364 72.1105 54.8083H70.9998ZM54.8083 0V1.11073C63.1372 1.11073 69.8891 7.86263 69.8891 16.1915H70.9998H72.1105C72.1105 6.63575 64.364 -1.11073 54.8083 -1.11073V0ZM16.1915 0V-1.11073C6.63575 -1.11073 -1.11073 6.63577 -1.11073 16.1915H0H1.11073C1.11073 7.86264 7.86263 1.11073 16.1915 1.11073V0Z" fill="white" fill-opacity="0.1" mask="url(#path-1-inside-1_162_7202)"/>
|
||||||
|
<g filter="url(#filter1_d_162_7202)">
|
||||||
|
<path d="M47.6428 29.4282H23.3572C22.519 29.4282 21.8394 30.1077 21.8394 30.946V33.9817C21.8394 34.82 22.519 35.4996 23.3572 35.4996H47.6428C48.4811 35.4996 49.1607 34.82 49.1607 33.9817V30.946C49.1607 30.1077 48.4811 29.4282 47.6428 29.4282Z" stroke="white" stroke-width="2.99979" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M35.5 29.4282V49.1602" stroke="white" stroke-width="2.99979" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M46.1242 35.5V46.1249C46.1242 46.9301 45.8044 47.7022 45.2351 48.2715C44.6658 48.8408 43.8936 49.1606 43.0885 49.1606H27.91C27.1049 49.1606 26.3328 48.8408 25.7634 48.2715C25.1941 47.7022 24.8743 46.9301 24.8743 46.1249V35.5" stroke="white" stroke-width="2.99979" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M28.6689 29.4283C27.6625 29.4283 26.6974 29.0285 25.9857 28.3169C25.2741 27.6053 24.8743 26.6401 24.8743 25.6337C24.8743 24.6273 25.2741 23.6621 25.9857 22.9505C26.6974 22.2389 27.6625 21.8391 28.6689 21.8391C30.1332 21.8136 31.5681 22.524 32.7865 23.8778C34.0049 25.2316 34.9502 27.1658 35.4993 29.4283C36.0483 27.1658 36.9937 25.2316 38.2121 23.8778C39.4305 22.524 40.8653 21.8136 42.3296 21.8391C43.336 21.8391 44.3012 22.2389 45.0128 22.9505C45.7244 23.6621 46.1242 24.6273 46.1242 25.6337C46.1242 26.6401 45.7244 27.6053 45.0128 28.3169C44.3012 29.0285 43.336 29.4283 42.3296 29.4283" stroke="white" stroke-width="2.99979" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_i_162_7202" x="0" y="0" width="71" height="73.0239" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="2"/>
|
||||||
|
<feGaussianBlur stdDeviation="2"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_162_7202"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_d_162_7202" x="11.2137" y="14.2496" width="48.5716" height="48.5716" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="3"/>
|
||||||
|
<feGaussianBlur stdDeviation="3"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_162_7202"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_162_7202" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.3 KiB |
11
images/figma-gift-shop-love-icon.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 10.0104C0 4.4818 4.4818 0 10.0104 0H21.9901C27.5187 0 32.0005 4.4818 32.0005 10.0104V21.9901C32.0005 27.5187 27.5187 32.0005 21.9901 32.0005H10.0104C4.4818 32.0005 0 27.5187 0 21.9901V10.0104Z" fill="white" fill-opacity="0.2"/>
|
||||||
|
<g clip-path="url(#clip0_162_7190)">
|
||||||
|
<path d="M21.8384 17.6688C23.0811 16.4511 24.3405 14.9915 24.3405 13.0815C24.3405 11.8649 23.8572 10.6981 22.9969 9.83777C22.1366 8.97747 20.9698 8.49417 19.7532 8.49417C18.2853 8.49417 17.251 8.9112 15.9999 10.1623C14.7488 8.9112 13.7146 8.49417 12.2467 8.49417C11.03 8.49417 9.86321 8.97747 9.00291 9.83777C8.14262 10.6981 7.65931 11.8649 7.65931 13.0815C7.65931 14.9998 8.91041 16.4595 10.1615 17.6688L15.9999 23.5073L21.8384 17.6688Z" fill="white" stroke="white" stroke-width="1.66639" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_162_7190">
|
||||||
|
<rect width="19.9967" height="19.9967" fill="white" transform="translate(5.99157 5.99157) scale(1.00104)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
10
images/figma-gift-shop-price-icon.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_162_7222)">
|
||||||
|
<path d="M14.2498 10.5002C15.3673 9.40522 16.4998 8.09272 16.4998 6.37523C16.4998 5.28122 16.0652 4.23201 15.2916 3.45842C14.518 2.68484 13.4688 2.25024 12.3748 2.25024C11.0548 2.25024 10.1248 2.62524 8.99981 3.75024C7.87481 2.62524 6.94482 2.25024 5.62482 2.25024C4.53081 2.25024 3.4816 2.68484 2.70802 3.45842C1.93443 4.23201 1.49984 5.28122 1.49984 6.37523C1.49984 8.10022 2.62483 9.41272 3.74983 10.5002L8.99981 15.7502L14.2498 10.5002Z" fill="#B06AB3" stroke="#B06AB3" stroke-width="1.49918" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_162_7222">
|
||||||
|
<rect width="17.9902" height="17.9902" fill="white" transform="scale(1.00054)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 830 B |
5
images/figma-gift-shop-section-icon.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M6.00005 1.99967L3 5.99974V20C3 20.5304 3.21072 21.0392 3.5858 21.4142C3.96088 21.7893 4.46959 22 5.00004 22H19.0003C19.5307 22 20.0394 21.7893 20.4145 21.4142C20.7896 21.0392 21.0003 20.5304 21.0003 20V5.99974L18.0003 1.99967H6.00005Z" stroke="#B06AB3" stroke-width="1.99938" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M3 6H21.0003" stroke="#B06AB3" stroke-width="1.99938" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M15.9998 10.0003C15.9998 11.0612 15.5784 12.0786 14.8282 12.8288C14.0781 13.579 13.0606 14.0004 11.9997 14.0004C10.9389 14.0004 9.92143 13.579 9.17127 12.8288C8.42111 12.0786 7.99967 11.0612 7.99967 10.0003" stroke="#B06AB3" stroke-width="1.99938" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 856 B |
BIN
images/fuw-aixin.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
images/fuw-dingzhi.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
images/fuw-kangyang.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
images/fuw-pinpai.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
images/fuw-shangcheng.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
images/fuw-shangjia.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
images/gift-arrow.png
Normal file
|
After Width: | Height: | Size: 955 B |
BIN
images/gift-balloon.png
Normal file
|
After Width: | Height: | Size: 964 B |
BIN
images/gift-cake.png
Normal file
|
After Width: | Height: | Size: 786 B |
BIN
images/gift-cheer.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
images/gift-chicken.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/gift-cup.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
images/gift-diamond.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
images/gift-heart.png
Normal file
|
After Width: | Height: | Size: 715 B |
BIN
images/gift-hug.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/gift-milk.png
Normal file
|
After Width: | Height: | Size: 779 B |
BIN
images/gift-pot.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
images/gift-rice.png
Normal file
|
After Width: | Height: | Size: 851 B |
BIN
images/gift-rose.png
Normal file
|
After Width: | Height: | Size: 973 B |
BIN
images/gift-scarf.png
Normal file
|
After Width: | Height: | Size: 784 B |
1
images/icon-arrow-right-pink.png
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
PNG placeholder - 需要用设计工具导出实际PNG图标
|
||||||
5
images/icon-arrow-right.png
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 15.9933 15.9933" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M5.9975 11.995L9.99584 7.99667L5.9975 3.99833" stroke="var(--stroke-0, #99A1AF)" stroke-width="1.33278" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 380 B |
BIN
images/icon-back-arrow.png
Normal file
|
After Width: | Height: | Size: 298 B |
5
images/icon-back-arrow2.png
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 27.9883 27.9883" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M17.4927 20.9913L10.4956 13.9942L17.4927 6.99709" stroke="var(--stroke-0, #101828)" stroke-width="2.91545" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 383 B |
BIN
images/icon-back-line.png
Normal file
|
After Width: | Height: | Size: 175 B |
BIN
images/icon-back.png
Normal file
|
After Width: | Height: | Size: 262 B |
BIN
images/icon-backpack.png
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
images/icon-bell.png
Normal file
|
After Width: | Height: | Size: 913 B |
BIN
images/icon-calendar.png
Normal file
|
After Width: | Height: | Size: 942 B |
BIN
images/icon-camera.png
Normal file
|
After Width: | Height: | Size: 588 B |
BIN
images/icon-check.png
Normal file
|
After Width: | Height: | Size: 282 B |
BIN
images/icon-checkin.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
images/icon-chevron-down.png
Normal file
|
After Width: | Height: | Size: 282 B |
BIN
images/icon-chevron-left.png
Normal file
|
After Width: | Height: | Size: 246 B |
BIN
images/icon-chevron-right.png
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
images/icon-city.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
6
images/icon-cleaning.png
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 31.9867 31.9867" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M19.9917 27.9883V17.3261C19.9917 16.9726 19.8513 16.6336 19.6013 16.3837C19.3514 16.1338 19.0124 15.9933 18.6589 15.9933H13.3278C12.9743 15.9933 12.6353 16.1338 12.3854 16.3837C12.1354 16.6336 11.995 16.9726 11.995 17.3261V27.9883" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_2" d="M3.99833 13.3278C3.99824 12.94 4.08274 12.5569 4.24595 12.2052C4.40915 11.8535 4.64713 11.5416 4.94327 11.2913L14.2727 3.29596C14.7538 2.88934 15.3634 2.66625 15.9933 2.66625C16.6233 2.66625 17.2328 2.88934 17.714 3.29596L27.0434 11.2913C27.3395 11.5416 27.5775 11.8535 27.7407 12.2052C27.9039 12.5569 27.9884 12.94 27.9883 13.3278V25.3228C27.9883 26.0297 27.7075 26.7077 27.2076 27.2076C26.7077 27.7075 26.0297 27.9883 25.3228 27.9883H6.66389C5.95694 27.9883 5.27895 27.7075 4.77906 27.2076C4.27917 26.7077 3.99833 26.0297 3.99833 25.3228V13.3278Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/icon-clock.png
Normal file
|
After Width: | Height: | Size: 942 B |
BIN
images/icon-close.png
Normal file
|
After Width: | Height: | Size: 363 B |
BIN
images/icon-comment.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/icon-companion.png
Normal file
|
After Width: | Height: | Size: 893 B |
1
images/icon-cooperation.png
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
PNG placeholder - 需要用设计工具导出实际PNG图标
|
||||||
BIN
images/icon-coupon.png
Normal file
|
After Width: | Height: | Size: 457 B |
BIN
images/icon-edit.png
Normal file
|
After Width: | Height: | Size: 694 B |
1
images/icon-eldercare.png
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
PNG placeholder - 需要用设计工具导出实际PNG图标
|
||||||
13
images/icon-elderly.png
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 31.9867 31.9867" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M15.9933 6.66389C15.9949 6.13082 15.8899 5.60281 15.6844 5.11093C15.4789 4.61905 15.1772 4.17323 14.7969 3.79967C14.4166 3.42612 13.9654 3.13239 13.4699 2.93575C12.9745 2.73911 12.4447 2.64353 11.9117 2.65464C11.3787 2.66575 10.8534 2.78332 10.3665 3.00043C9.87968 3.21755 9.44116 3.52983 9.07676 3.9189C8.71235 4.30798 8.42943 4.76599 8.24463 5.26601C8.05983 5.76602 7.97689 6.29794 8.00067 6.83048C7.21726 7.03192 6.48997 7.40898 5.87386 7.93311C5.25776 8.45724 4.769 9.1147 4.44461 9.85569C4.12022 10.5967 3.96869 11.4018 4.00152 12.21C4.03434 13.0182 4.25066 13.8084 4.63407 14.5206C3.95993 15.0683 3.42981 15.7724 3.08983 16.5717C2.74986 17.3709 2.61032 18.2412 2.68337 19.1067C2.75641 19.9722 3.03982 20.8067 3.50895 21.5377C3.97807 22.2687 4.6187 22.874 5.3751 23.301C5.28169 24.0236 5.33743 24.7578 5.53888 25.4581C5.74032 26.1584 6.0832 26.8099 6.54632 27.3725C7.00945 27.9351 7.58299 28.3968 8.23153 28.729C8.88007 29.0613 9.58984 29.257 10.317 29.3042C11.0442 29.3514 11.7733 29.249 12.4593 29.0034C13.1454 28.7578 13.7738 28.3741 14.3057 27.8761C14.8377 27.378 15.2619 26.7763 15.5521 26.1079C15.8424 25.4395 15.9926 24.7187 15.9933 23.99V6.66389Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_2" d="M15.9933 6.66389C15.9918 6.13082 16.0968 5.60281 16.3023 5.11093C16.5078 4.61905 16.8095 4.17323 17.1898 3.79967C17.5701 3.42612 18.0213 3.13239 18.5167 2.93575C19.0122 2.73911 19.542 2.64353 20.075 2.65464C20.6079 2.66575 21.1333 2.78332 21.6201 3.00043C22.107 3.21755 22.5455 3.52983 22.9099 3.9189C23.2743 4.30798 23.5572 4.76599 23.742 5.26601C23.9268 5.76602 24.0098 6.29794 23.986 6.83048C24.7694 7.03192 25.4967 7.40898 26.1128 7.93311C26.7289 8.45724 27.2177 9.1147 27.5421 9.85569C27.8665 10.5967 28.018 11.4018 27.9852 12.21C27.9523 13.0182 27.736 13.8084 27.3526 14.5206C28.0268 15.0683 28.5569 15.7724 28.8968 16.5717C29.2368 17.3709 29.3764 18.2412 29.3033 19.1067C29.2303 19.9722 28.9469 20.8067 28.4777 21.5377C28.0086 22.2687 27.368 22.874 26.6116 23.301C26.705 24.0236 26.6492 24.7578 26.4478 25.4581C26.2464 26.1584 25.9035 26.8099 25.4404 27.3725C24.9772 27.9351 24.4037 28.3968 23.7551 28.729C23.1066 29.0613 22.3968 29.257 21.6697 29.3042C20.9425 29.3514 20.2134 29.249 19.5274 29.0034C18.8413 28.7578 18.2129 28.3741 17.681 27.8761C17.149 27.378 16.7248 26.7763 16.4345 26.1079C16.1443 25.4395 15.9941 24.7187 15.9933 23.99V6.66389Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_3" d="M19.9917 17.3261C18.8727 16.9325 17.8956 16.2159 17.1839 15.267C16.4722 14.3181 16.0579 13.1794 15.9933 11.995C15.9288 13.1794 15.5144 14.3181 14.8027 15.267C14.091 16.2159 13.1139 16.9325 11.995 17.3261" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_4" d="M23.4556 8.66383C23.7783 8.10461 23.9608 7.47559 23.9876 6.8305" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_5" d="M8.00066 6.8305C8.02703 7.47548 8.2091 8.10449 8.53133 8.66383" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_6" d="M4.63407 14.5222C4.87799 14.3235 5.13901 14.1468 5.41407 13.9942" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_7" d="M26.5729 13.9942C26.848 14.1468 27.109 14.3235 27.3529 14.5222" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_8" d="M7.99667 23.99C7.07816 23.9904 6.17512 23.7536 5.3751 23.3023" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_9" d="M26.6116 23.3023C25.8116 23.7536 24.9085 23.9904 23.99 23.99" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.2 KiB |
BIN
images/icon-emoji-face.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
6
images/icon-emoji-gray.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#4A5565" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="10"/>
|
||||||
|
<path d="M8 14s1.5 2 4 2 4-2 4-2"/>
|
||||||
|
<line x1="9" x2="9.01" y1="9" y2="9"/>
|
||||||
|
<line x1="15" x2="15.01" y1="9" y2="9"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 341 B |
BIN
images/icon-emoji.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
images/icon-empty.png
Normal file
|
After Width: | Height: | Size: 889 B |
7
images/icon-errand.png
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 31.9867 31.9867" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M7.99667 2.66555L3.99833 7.99666V26.6556C3.99833 27.3625 4.27917 28.0405 4.77906 28.5404C5.27895 29.0403 5.95694 29.3211 6.66389 29.3211H25.3228C26.0297 29.3211 26.7077 29.0403 27.2076 28.5404C27.7075 28.0405 27.9883 27.3625 27.9883 26.6556V7.99666L23.99 2.66555H7.99667Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_2" d="M3.99833 7.99667H27.9883" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_3" d="M21.3245 13.3278C21.3245 14.7417 20.7628 16.0977 19.763 17.0975C18.7632 18.0972 17.4072 18.6589 15.9933 18.6589C14.5794 18.6589 13.2235 18.0972 12.2237 17.0975C11.2239 16.0977 10.6622 14.7417 10.6622 13.3278" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
images/icon-eye.png
Normal file
|
After Width: | Height: | Size: 980 B |
BIN
images/icon-feedback.png
Normal file
|
After Width: | Height: | Size: 442 B |
BIN
images/icon-gift.png
Normal file
|
After Width: | Height: | Size: 767 B |
BIN
images/icon-grass.png
Normal file
|
After Width: | Height: | Size: 928 B |
BIN
images/icon-headphones.png
Normal file
|
After Width: | Height: | Size: 883 B |
BIN
images/icon-heart-filled.png
Normal file
|
After Width: | Height: | Size: 681 B |
1
images/icon-heart-listen.png
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
PNG placeholder - 需要用设计工具导出实际PNG图标
|
||||||
BIN
images/icon-heart-new.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
images/icon-heart.png
Normal file
|
After Width: | Height: | Size: 681 B |
BIN
images/icon-heart_.png
Normal file
|
After Width: | Height: | Size: 384 B |
BIN
images/icon-help.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
9
images/icon-hospital.png
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 31.9867 31.9867" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M14.6606 2.66555V5.3311" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_2" d="M6.6639 2.66555V5.3311" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_3" d="M6.6639 3.99833H5.33112C4.62417 3.99833 3.94617 4.27917 3.44628 4.77906C2.9464 5.27895 2.66556 5.95694 2.66556 6.66389V11.995C2.66556 14.1159 3.50807 16.1498 5.00773 17.6495C6.5074 19.1492 8.54138 19.9917 10.6622 19.9917C12.7831 19.9917 14.8171 19.1492 16.3167 17.6495C17.8164 16.1498 18.6589 14.1159 18.6589 11.995V6.66389C18.6589 5.95694 18.3781 5.27895 17.8782 4.77906C17.3783 4.27917 16.7003 3.99833 15.9933 3.99833H14.6606" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_4" d="M10.6622 19.9917C10.6622 22.1125 11.5047 24.1465 13.0044 25.6462C14.5041 27.1458 16.5381 27.9883 18.6589 27.9883C20.7797 27.9883 22.8137 27.1458 24.3134 25.6462C25.8131 24.1465 26.6556 22.1125 26.6556 19.9917V15.9933" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_5" d="M26.6556 15.9933C28.1277 15.9933 29.3211 14.7999 29.3211 13.3278C29.3211 11.8556 28.1277 10.6622 26.6556 10.6622C25.1834 10.6622 23.99 11.8556 23.99 13.3278C23.99 14.7999 25.1834 15.9933 26.6556 15.9933Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
1
images/icon-housekeeping.png
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
PNG placeholder - 需要用设计工具导出实际PNG图标
|
||||||
BIN
images/icon-info.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
images/icon-interest.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
images/icon-keyboard.png
Normal file
|
After Width: | Height: | Size: 456 B |
9
images/icon-legal.png
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 31.9867 31.9867" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M21.3245 21.3244L25.3228 10.6622L29.3211 21.3244C28.1616 22.1907 26.7622 22.6572 25.3228 22.6572C23.8834 22.6572 22.484 22.1907 21.3245 21.3244Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_2" d="M2.66555 21.3244L6.66388 10.6622L10.6622 21.3244C9.5027 22.1907 8.10328 22.6572 6.66388 22.6572C5.22448 22.6572 3.82506 22.1907 2.66555 21.3244Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_3" d="M9.32946 27.9883H22.6572" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_4" d="M15.9933 3.99833V27.9883" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_5" d="M3.99833 9.32944H6.66389C9.32945 9.32944 13.3278 7.99666 15.9933 6.66388C18.6589 7.99666 22.6572 9.32944 25.3228 9.32944H27.9883" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
8
images/icon-listen.png
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 31.9867 31.9867" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="Icon">
|
||||||
|
<path id="Vector" d="M25.3228 18.6589C27.3086 16.713 29.3211 14.3807 29.3211 11.3286C29.3211 9.3845 28.5488 7.52002 27.1741 6.14532C25.7994 4.77063 23.935 3.99833 21.9908 3.99833C19.6452 3.99833 17.9925 4.66472 15.9933 6.66389C13.9942 4.66472 12.3415 3.99833 9.99584 3.99833C8.05173 3.99833 6.18724 4.77063 4.81255 6.14532C3.43785 7.52002 2.66556 9.3845 2.66556 11.3286C2.66556 14.394 4.66472 16.7264 6.66389 18.6589L15.9933 27.9883L25.3228 18.6589Z" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_2" d="M15.9933 6.66388L12.0483 10.6089C11.7775 10.8777 11.5626 11.1975 11.4159 11.5497C11.2693 11.902 11.1938 12.2798 11.1938 12.6614C11.1938 13.043 11.2693 13.4208 11.4159 13.773C11.5626 14.1253 11.7775 14.445 12.0483 14.7139C13.1412 15.8067 14.8871 15.8467 16.0467 14.8072L18.8055 12.2749C19.497 11.6474 20.3973 11.2998 21.3311 11.2998C22.2649 11.2998 23.1652 11.6474 23.8567 12.2749L27.8018 15.8201" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_3" d="M23.99 19.9917L21.3245 17.3261" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Vector_4" d="M19.9917 23.99L17.3261 21.3245" stroke="var(--stroke-0, #333333)" stroke-width="1.99917" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
images/icon-location-pin.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
images/icon-location.png
Normal file
|
After Width: | Height: | Size: 745 B |
BIN
images/icon-lock.png
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
images/icon-logout.png
Normal file
|
After Width: | Height: | Size: 457 B |
BIN
images/icon-love.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |