feat: 更新小程序代码 - 2026-02-02

This commit is contained in:
zhiyun 2026-02-02 18:21:32 +08:00
commit ff4c7b7e09
434 changed files with 58912 additions and 0 deletions

111
README.md Normal file
View 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
View 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
View 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
View 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
View 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}');` : ''}`
});
}
}
});

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

@ -0,0 +1 @@
<view class="icon" style="{{style}}" />

View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/btn-text-consult.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
images/chat-action-gift.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
images/chat-input-emoji.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
images/chat-input-plus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
images/chat-input-voice.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View 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

View 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

View 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

View 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

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
images/fuw-dingzhi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
images/fuw-kangyang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
images/fuw-pinpai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
images/fuw-shangcheng.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
images/fuw-shangjia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
images/gift-arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

BIN
images/gift-balloon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

BIN
images/gift-cake.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

BIN
images/gift-cheer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
images/gift-chicken.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/gift-cup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
images/gift-diamond.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
images/gift-heart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

BIN
images/gift-hug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/gift-milk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

BIN
images/gift-pot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
images/gift-rice.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

BIN
images/gift-rose.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

BIN
images/gift-scarf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

BIN
images/icon-arrow-right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

BIN
images/icon-back-arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

BIN
images/icon-back-arrow2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

BIN
images/icon-back-line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

BIN
images/icon-back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

BIN
images/icon-backpack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

BIN
images/icon-bell.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

BIN
images/icon-calendar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

BIN
images/icon-camera.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

BIN
images/icon-check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

BIN
images/icon-checkin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

BIN
images/icon-city.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
images/icon-cleaning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/icon-clock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

BIN
images/icon-close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

BIN
images/icon-comment.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/icon-companion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

BIN
images/icon-cooperation.png Normal file

Binary file not shown.

BIN
images/icon-coupon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

BIN
images/icon-edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

BIN
images/icon-eldercare.png Normal file

Binary file not shown.

BIN
images/icon-elderly.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
images/icon-emoji-face.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/icon-empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

BIN
images/icon-errand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
images/icon-eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

BIN
images/icon-feedback.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

BIN
images/icon-gift.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

BIN
images/icon-grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

BIN
images/icon-headphones.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

BIN
images/icon-heart-new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
images/icon-heart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

BIN
images/icon-heart_.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

BIN
images/icon-help.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
images/icon-hospital.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

BIN
images/icon-info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
images/icon-interest.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
images/icon-keyboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

BIN
images/icon-legal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
images/icon-listen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
images/icon-location.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

BIN
images/icon-lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

BIN
images/icon-logout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

BIN
images/icon-love.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Some files were not shown because too many files have changed in this diff Show More