From ae443b7fc73dfae12a9902ea06e060d9d6896286 Mon Sep 17 00:00:00 2001 From: DU Date: Wed, 18 Mar 2026 10:09:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=84=E7=90=86=20=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E8=BF=87=E5=A4=A7=EF=BC=8C=20=E5=AF=B9=E6=8E=A5=E7=99=BB?= =?UTF-8?q?=E9=99=86=EF=BC=8C=E4=BD=86=E6=98=AF=E4=B8=8D=E9=80=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MIGRATION_CHECKLIST.md | 110 +++++++++++ src/api/apidoc/login.md | 116 ++++++++++++ src/api/login.ts | 19 ++ src/components/EmptyData/index.tsx | 5 +- src/config/index.ts | 6 + src/pageStore/storeDetail/index.tsx | 6 +- src/pages/index/index.tsx | 15 +- src/pages/message/index.tsx | 10 +- src/pages/user/index.scss | 24 +++ src/pages/user/index.tsx | 127 ++++++++++--- .../accountBalance/components/BalanceList.tsx | 4 +- .../components/OpenRecordList.tsx | 4 +- .../components/RechargeRecordList.tsx | 4 +- src/pagesOrder/rechargeDetail/index.tsx | 4 +- src/pagesUser/orderList/index.tsx | 4 +- src/store/user.ts | 60 +++++- src/types/login.ts | 47 +++++ src/utils/README_imageHelper.md | 176 ++++++++++++++++++ src/utils/imageHelper.ts | 108 +++++++++++ src/utils/testImageHelper.ts | 36 ++++ 20 files changed, 825 insertions(+), 60 deletions(-) create mode 100644 MIGRATION_CHECKLIST.md create mode 100644 src/api/apidoc/login.md create mode 100644 src/api/login.ts create mode 100644 src/types/login.ts create mode 100644 src/utils/README_imageHelper.md create mode 100644 src/utils/imageHelper.ts create mode 100644 src/utils/testImageHelper.ts diff --git a/MIGRATION_CHECKLIST.md b/MIGRATION_CHECKLIST.md new file mode 100644 index 0000000..69f5a1b --- /dev/null +++ b/MIGRATION_CHECKLIST.md @@ -0,0 +1,110 @@ +# 图片迁移检查清单 + +## ✅ 已完成的工作 + +### 1. 创建图片工具 +- ✅ 创建 `src/utils/imageHelper.ts` 工具类 +- ✅ 配置预定义图片映射 `BIG_IMAGES` +- ✅ 提供多种使用方式:`getBigImage()`, `getBigImageUrl()`, `getBigImagesUrl()` +- ✅ 添加图片预加载功能 `preloadImages()` + +### 2. 更新代码引用 +- ✅ `src/components/EmptyData/index.tsx` - 空数据组件 +- ✅ `src/pages/index/index.tsx` - 首页轮播图和卡片 +- ✅ `src/pages/user/index.tsx` - 用户页面背景 +- ✅ `src/pageStore/storeDetail/index.tsx` - 门店详情轮播图 +- ✅ `src/pages/message/index.tsx` - 消息页面图片和空数据 +- ✅ `src/pagesUser/orderList/index.tsx` - 订单列表空数据 +- ✅ `src/pagesOrder/rechargeDetail/index.tsx` - 充值详情空数据 +- ✅ `src/pagesOrder/accountBalance/components/OpenRecordList.tsx` - 开台记录空数据 +- ✅ `src/pagesOrder/accountBalance/components/RechargeRecordList.tsx` - 充值记录空数据 +- ✅ `src/pagesOrder/accountBalance/components/BalanceList.tsx` - 余额记录空数据 + +### 3. 构建测试 +- ✅ 修复所有语法错误 +- ✅ 成功构建微信小程序 +- ✅ 生成的代码正确使用图片工具 + +## 🔄 需要你完成的工作 + +### 1. 服务器图片检查 +确保以下图片已上传到服务器 `http://39.101.75.71:8888/img/MiniBgImage/`: + +- [ ] `noData.png` - 空数据占位图 +- [ ] `swBG.png` - 轮播背景图 +- [ ] `user_bg.png` - 用户页面背景 +- [ ] `fjmd.png` - 附近门店功能图 +- [ ] `smkt.png` - 扫码开台功能图 +- [ ] `tghx.png` - 团购核销功能图 + +### 2. 图片访问测试 +在浏览器中测试以下 URL 是否可以正常访问: + +- [ ] http://39.101.75.71:8888/img/MiniBgImage/noData.png +- [ ] http://39.101.75.71:8888/img/MiniBgImage/swBG.png +- [ ] http://39.101.75.71:8888/img/MiniBgImage/user_bg.png +- [ ] http://39.101.75.71:8888/img/MiniBgImage/fjmd.png +- [ ] http://39.101.75.71:8888/img/MiniBgImage/smkt.png +- [ ] http://39.101.75.71:8888/img/MiniBgImage/tghx.png + +### 3. 小程序测试 +- [ ] 在微信开发者工具中预览小程序 +- [ ] 检查所有页面的图片是否正常显示 +- [ ] 测试网络较慢时的图片加载体验 +- [ ] 检查图片加载失败时的表现 + +### 4. 性能优化(可选) +- [ ] 在 `app.tsx` 中添加关键图片预加载 +- [ ] 为图片组件添加 `onError` 错误处理 +- [ ] 考虑添加图片懒加载 + +## 📝 使用示例 + +### 基础用法 +```typescript +import { getBigImage } from '@/utils/imageHelper' + +// 在组件中使用 + +``` + +### 预加载关键图片 +```typescript +import { preloadImages, getBigImage } from '@/utils/imageHelper' + +// 在应用启动时预加载 +const keyImages = [ + getBigImage('NO_DATA'), + getBigImage('SW_BG'), + getBigImage('USER_BG') +] + +preloadImages(keyImages).then(() => { + console.log('关键图片预加载完成') +}) +``` + +### 添加新图片 +1. 上传图片到服务器:`http://39.101.75.71:8888/img/MiniBgImage/新图片.png` +2. 在 `BIG_IMAGES` 中添加映射: +```typescript +export const BIG_IMAGES = { + // 现有图片... + NEW_IMAGE: '新图片.png', +} as const +``` +3. 在代码中使用:`getBigImage('NEW_IMAGE')` + +## ⚠️ 注意事项 + +1. **网络依赖**:图片加载现在依赖网络,首次加载会有延迟 +2. **缓存机制**:小程序会自动缓存网络图片 +3. **错误处理**:建议为重要图片添加加载失败的兜底处理 +4. **包体积**:本地大图已移除,小程序包体积显著减少 + +## 🚀 预期收益 + +- ✅ **包体积减少**:移除本地大图,预计减少包体积 500KB+ +- ✅ **便于管理**:图片统一在服务器管理,更新无需重新发布 +- ✅ **加载灵活**:可以动态更新图片内容 +- ✅ **代码整洁**:统一的图片引用方式,便于维护 \ No newline at end of file diff --git a/src/api/apidoc/login.md b/src/api/apidoc/login.md new file mode 100644 index 0000000..e32fa43 --- /dev/null +++ b/src/api/apidoc/login.md @@ -0,0 +1,116 @@ + + +## 微信登录 + + +**接口地址**:`/api/v2/WechatAuth/login-wechat` + + +**请求方式**:`POST` + + +**请求数据类型**:`application/x-www-form-urlencoded,application/json,text/json,application/*+json` + + +**响应数据类型**:`text/plain` + + +**接口描述**: + + +**请求示例**: + + +```javascript +{ + "code": "" +} +``` + + +**请求参数**: + + +**请求参数**: + + +| 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | +| -------- | -------- | ----- | -------- | -------- | ------ | +|wechatLoginRequest|微信授权请求模型\n\n用于微信登录|body|true|WechatLoginRequest|WechatLoginRequest| +|  code|微信登录凭证code\n\n通过 wx.login() 获取的临时登录凭证||true|string|| + + +**响应状态**: + + +| 状态码 | 说明 | schema | +| -------- | -------- | ----- | +|200|OK|WechatAuthResultDtoOpResult| + + +**响应参数**: + + +| 参数名称 | 参数说明 | 类型 | schema | +| -------- | -------- | ----- |----- | +|message|描述消息|string|| +|code|返回值|integer(int32)|integer(int32)| +|success|是否成功|boolean|| +|data||WechatAuthResultDto|WechatAuthResultDto| +|  success|是否成功|boolean|| +|  customer|客户Dto|CustomerDto|CustomerDto| +|    id|id|integer|| +|    sn|客户编码|string|| +|    wxOpenId|OpenId|string|| +|    name|名称|string|| +|    type|类型 0会员 1VIP|integer|| +|    typeName|类型描述|string|| +|    amount|余额|number|| +|    wchart|微信号|string|| +|    phone|手机号|string|| +|    bpSn|店铺编码|string|| +|    bpInfoName|店铺名称|string|| +|    instSn|机构编码|string|| +|    ownerName|机构名称|string|| +|    createTime|创建时间|string|| +|    lastLoginTime||string|| +|    wxNickName|微信昵称|string|| +|    wxAvatarUrl|头像URL|string|| +|  operationResult|操作结果||| +|  isNewCustomer|是否是新用户|boolean|| +|  message|消息|string|| + + +**响应示例**: +```javascript +{ + "message": "", + "code": 0, + "success": true, + "data": { + "success": true, + "customer": { + "id": 0, + "sn": "", + "wxOpenId": "", + "name": "", + "type": 0, + "typeName": "", + "amount": 0, + "wchart": "", + "phone": "", + "bpSn": "", + "bpInfoName": "", + "instSn": "", + "ownerName": "", + "createTime": "", + "lastLoginTime": "", + "wxNickName": "", + "wxAvatarUrl": "" + }, + "operationResult": {}, + "isNewCustomer": true, + "message": "" + } +} +``` \ No newline at end of file diff --git a/src/api/login.ts b/src/api/login.ts new file mode 100644 index 0000000..4409159 --- /dev/null +++ b/src/api/login.ts @@ -0,0 +1,19 @@ +/** + * 微信登录相关接口 + */ +import request from '../services/request' +import { WechatLoginRequest, WechatAuthResponse } from '../types/login' + +/** + * 微信登录 + * @param code 微信登录凭证 + */ +export const wechatLogin = (code: string, grpSn=''): Promise => { + const data: WechatLoginRequest = { code,grpSn } + + return request({ + url: '/WechatAuth/login-wechat', + method: 'POST', + data + }) +} \ No newline at end of file diff --git a/src/components/EmptyData/index.tsx b/src/components/EmptyData/index.tsx index 302ffa3..05e37d9 100644 --- a/src/components/EmptyData/index.tsx +++ b/src/components/EmptyData/index.tsx @@ -2,10 +2,9 @@ * 空数据组件 */ import { View, Text, Image } from '@tarojs/components' +import { getBigImage } from '@/utils/imageHelper' import './index.scss' -const noDataImg = require('../../assets/big/noData.png') - interface EmptyDataProps { text?: string imageSize?: 'small' | 'medium' | 'large' @@ -19,7 +18,7 @@ const EmptyData: React.FC = ({ {text} diff --git a/src/config/index.ts b/src/config/index.ts index 3fe0207..9114fbf 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -7,6 +7,9 @@ // 直接配置,如需修改请更改此处 const API_BASE_URL = 'https://39.101.75.71:8889' +// 大图服务器地址 http://39.101.75.71:8888/img/MiniBgImage/swBG.png +const BIG_IMAGE_URL = 'http://39.101.75.71:8888/img/MiniBgImage' + // API 版本 const API_VERSION = 'v2' @@ -19,6 +22,9 @@ const DEBUG_MODE = true export const config = { // API 基础地址 apiBaseUrl: API_BASE_URL, + + // 大图服务器地址 + bigImageUrl: BIG_IMAGE_URL, // API 版本 apiVersion: API_VERSION, diff --git a/src/pageStore/storeDetail/index.tsx b/src/pageStore/storeDetail/index.tsx index 9dec202..66cde1d 100644 --- a/src/pageStore/storeDetail/index.tsx +++ b/src/pageStore/storeDetail/index.tsx @@ -22,7 +22,7 @@ import payVipBg from '../images/payVip.png' import billiardTabBg from '../images/billiardtab.png' import paiTabBg from '../images/paitab.png' import storeBoxBg from '../images/storeBox.png' -import swBG from '../../assets/big/swBG.png' +import { getBigImage } from '@/utils/imageHelper' // 台球桌状态类型 type TableStatus = 'available' | 'using' | 'waiting' | 'reserved' @@ -280,14 +280,14 @@ const StoreDetail = () => { diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index 7f0bc9d..d1c79b7 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -9,10 +9,7 @@ import { Swiper } from '@taroify/core' import { LocationOutlined } from '@taroify/icons' import { useEffect, useState } from 'react' import { userStore } from '../../store' -import swBG from '../../assets/big/swBG.png' -import smkt from '../../assets/big/smkt.png' -import fjmd from '../../assets/big/fjmd.png' -import tghx from '../../assets/big/tghx.png' +import { getBigImage, BIG_IMAGES } from '@/utils/imageHelper' import './index.scss' const Index = observer(() => { @@ -105,14 +102,14 @@ const Index = observer(() => { @@ -126,7 +123,7 @@ const Index = observer(() => { @@ -141,7 +138,7 @@ const Index = observer(() => { @@ -158,7 +155,7 @@ const Index = observer(() => { diff --git a/src/pages/message/index.tsx b/src/pages/message/index.tsx index 72f745b..7045e26 100644 --- a/src/pages/message/index.tsx +++ b/src/pages/message/index.tsx @@ -6,7 +6,7 @@ import { useLoad } from '@tarojs/taro' import { observer } from 'mobx-react' import { useState } from 'react' import { Tabs, Badge } from '@taroify/core' -import noDataImg from '../../assets/big/noData.png' +import { getBigImage } from '@/utils/imageHelper' import './index.scss' // 消息数据接口 @@ -85,7 +85,7 @@ const MessageIndex = observer(() => { content: '金风科技上课福建省咖啡机看得见风可视对讲开发机十大费晶...', time: '2025-01-10', createTime: currentTime - 1 * 60 * 60 * 1000, - image: require('../../assets/big/fjmd.png'), + image: getBigImage('FJMD'), }, { id: '5', @@ -100,7 +100,7 @@ const MessageIndex = observer(() => { content: '来力台球厅新店盛大开业,前100名顾客可享受5折优惠,还有精美礼品相送!', time: '2025-01-09 20:00:00', createTime: currentTime - 4 * 60 * 60 * 1000, - image: require('../../assets/big/smkt.png'), + image: getBigImage('SMKT'), }, { id: '12', @@ -115,7 +115,7 @@ const MessageIndex = observer(() => { content: '本周末会员专享8折优惠,非会员可享受9折优惠,欢迎预约!', time: '2025-01-09 10:00:00', createTime: currentTime - 14 * 60 * 60 * 1000, - image: require('../../assets/big/tghx.png'), + image: getBigImage('TGHX'), }, ]) @@ -183,7 +183,7 @@ const MessageIndex = observer(() => { // 渲染空状态 const renderEmptyState = () => ( - + 没有数据哦~ ) diff --git a/src/pages/user/index.scss b/src/pages/user/index.scss index c361989..e4dd10f 100644 --- a/src/pages/user/index.scss +++ b/src/pages/user/index.scss @@ -97,6 +97,25 @@ color: #000; flex-shrink: 0; } + + // 登录按钮样式 + .login-btn { + margin-left: 20px; + padding: 8px 16px; + font-size: 24rpx; + border-radius: 20px; + flex-shrink: 0; + min-width: 80px; + height: 36px; + + :global { + .taroify-button { + height: 100%; + font-size: 24rpx; + border-radius: 20px; + } + } + } } // 成长值 @@ -117,6 +136,11 @@ margin-right: 10px; flex-shrink: 0; } + + .no-data { + font-size: 25rpx; + color: #666666; + } } } } diff --git a/src/pages/user/index.tsx b/src/pages/user/index.tsx index 1f656b0..c869cf3 100644 --- a/src/pages/user/index.tsx +++ b/src/pages/user/index.tsx @@ -5,12 +5,13 @@ import { View, Text, Image } from '@tarojs/components' import { useLoad } from '@tarojs/taro' import Taro from '@tarojs/taro' import { observer } from 'mobx-react' -import { Image as TaroifyImage } from '@taroify/core' +import { Image as TaroifyImage, Button } from '@taroify/core' import { userStore } from '../../store' +import { wechatLogin } from '../../api/login' +import { getBigImage } from '@/utils/imageHelper' import './index.scss' -// 导入图片 -import userBg from '../../assets/big/user_bg.png' +// 导入小图标(保留本地引用) import userEdite from '../../assets/icon/user_edite.png' import zuanIcon from '../../assets/icon/zuan.png' import sunIcon from '../../assets/icon/sun.png' @@ -70,10 +71,47 @@ const UserIndex = observer(() => { }) } + // 微信登录 + const handleWechatLogin = async () => { + let grpSn = '212' + try { + userStore.setLoading(true) + + // 调用微信登录获取code + const loginResult = await Taro.login() + if (!loginResult.code) { + throw new Error('获取微信登录凭证失败') + } + + // 调用后端接口 + const response = await wechatLogin(loginResult.code,grpSn) + + if (response.success && response.data.success) { + // 保存用户信息到store + userStore.setUserInfoFromWechat(response.data.customer) + + Taro.showToast({ + title: response.data.isNewCustomer ? '注册成功' : '登录成功', + icon: 'success' + }) + } else { + throw new Error(response.data.message || response.message || '登录失败') + } + } catch (error: any) { + console.error('微信登录失败:', error) + Taro.showToast({ + title: error.message || '登录失败,请重试', + icon: 'error' + }) + } finally { + userStore.setLoading(false) + } + } + return ( {/* 上部分:背景图和用户信息 */} - + {/* 用户信息模块 */} @@ -83,7 +121,7 @@ const UserIndex = observer(() => { @@ -91,30 +129,61 @@ const UserIndex = observer(() => { {/* 右侧信息 */} - {/* 用户名称和编辑按钮 */} - - - {userStore.userInfo?.nickname || '旋转跳跃的球圣'} - - - VIP - - - {/* 成长值 */} - - 成长值: - {growthIcons.map((icon, index) => ( - - ))} - + {userStore.isLoggedIn ? ( + <> + {/* 已登录状态 */} + {/* 用户名称和编辑按钮 */} + + + {userStore.userInfo?.nickname || '微信用户'} + + + + {userStore.userInfo?.typeName || 'VIP'} + + + + {/* 成长值 */} + + 成长值: + {growthIcons.map((icon, index) => ( + + ))} + + + ) : ( + <> + {/* 未登录状态 */} + + + 未登录 + + + + + {/* 成长值显示为暂无 */} + + 成长值: + 暂无 + + + )} diff --git a/src/pagesOrder/accountBalance/components/BalanceList.tsx b/src/pagesOrder/accountBalance/components/BalanceList.tsx index 49e470c..8715427 100644 --- a/src/pagesOrder/accountBalance/components/BalanceList.tsx +++ b/src/pagesOrder/accountBalance/components/BalanceList.tsx @@ -5,7 +5,7 @@ import { View, Text, Image } from '@tarojs/components' import { FC } from 'react' import './BalanceList.scss' -const noDataImg = require('../../../assets/big/noData.png') +import { getBigImage } from '@/utils/imageHelper' interface StoreBalanceItem { id: string @@ -33,7 +33,7 @@ const BalanceList: FC = ({ balanceList, onRecharge, onViewCabi {balanceList.length === 0 ? ( - + ) : ( <> diff --git a/src/pagesOrder/accountBalance/components/OpenRecordList.tsx b/src/pagesOrder/accountBalance/components/OpenRecordList.tsx index 0b55ba4..eab2c2c 100644 --- a/src/pagesOrder/accountBalance/components/OpenRecordList.tsx +++ b/src/pagesOrder/accountBalance/components/OpenRecordList.tsx @@ -8,7 +8,7 @@ import { Popup, DatetimePicker } from '@taroify/core' import Taro from '@tarojs/taro' import './OpenRecordList.scss' -const noDataImg = require('../../../assets/big/noData.png') +import { getBigImage } from '@/utils/imageHelper' interface OpenRecordItem { id: string @@ -135,7 +135,7 @@ const OpenRecordList: FC = ({ recordList }) => { {dataList.length === 0 ? ( - + ) : ( <> diff --git a/src/pagesOrder/accountBalance/components/RechargeRecordList.tsx b/src/pagesOrder/accountBalance/components/RechargeRecordList.tsx index 59e8ca6..f990629 100644 --- a/src/pagesOrder/accountBalance/components/RechargeRecordList.tsx +++ b/src/pagesOrder/accountBalance/components/RechargeRecordList.tsx @@ -8,7 +8,7 @@ import { Popup, DatetimePicker } from '@taroify/core' import Taro from '@tarojs/taro' import './RechargeRecordList.scss' -const noDataImg = require('../../../assets/big/noData.png') +import { getBigImage } from '@/utils/imageHelper' interface RechargeRecordItem { id: string @@ -114,7 +114,7 @@ const RechargeRecordList: FC = ({ recordList }) => { {dataList.length === 0 ? ( - + ) : ( <> diff --git a/src/pagesOrder/rechargeDetail/index.tsx b/src/pagesOrder/rechargeDetail/index.tsx index b61eb36..6b1ebd4 100644 --- a/src/pagesOrder/rechargeDetail/index.tsx +++ b/src/pagesOrder/rechargeDetail/index.tsx @@ -8,7 +8,7 @@ import { Popup, DatetimePicker } from '@taroify/core' import Taro, { useLoad } from '@tarojs/taro' import './index.scss' -const noDataImg = require('../../assets/big/noData.png') +import { getBigImage } from '@/utils/imageHelper' interface RechargeRecordItem { id: string @@ -133,7 +133,7 @@ const RechargeDetail = () => { {dataList.length === 0 ? ( - + ) : ( <> diff --git a/src/pagesUser/orderList/index.tsx b/src/pagesUser/orderList/index.tsx index 49682b4..4432bd9 100644 --- a/src/pagesUser/orderList/index.tsx +++ b/src/pagesUser/orderList/index.tsx @@ -9,7 +9,7 @@ import { ArrowDown } from '@taroify/icons' import FilterPopup from './components/FilterPopup' import './index.scss' -const noDataImg = require('../../assets/big/noData.png') +import { getBigImage } from '@/utils/imageHelper' // 订单数据接口 interface OrderItem { @@ -141,7 +141,7 @@ const OrderList = () => { {filteredOrders.length === 0 ? ( - + 没有数据哦~ ) : ( diff --git a/src/store/user.ts b/src/store/user.ts index 8bec9e1..ebdbc5f 100644 --- a/src/store/user.ts +++ b/src/store/user.ts @@ -3,21 +3,49 @@ */ import { makeAutoObservable } from 'mobx' import Taro from '@tarojs/taro' +import { CustomerDto } from '../types/login' export interface UserInfo { - id: string + id: number nickname: string avatar?: string phone?: string + wxOpenId?: string + name?: string + type?: number + typeName?: string + amount?: number + wchart?: string + bpSn?: string + bpInfoName?: string + instSn?: string + ownerName?: string + createTime?: string + lastLoginTime?: string } class UserStore { userInfo: UserInfo | null = null isLoggedIn: boolean = false balance: number = 0 + isLoading: boolean = false constructor() { makeAutoObservable(this) + this.initUserInfo() + } + + // 初始化用户信息(从本地存储读取) + initUserInfo = () => { + try { + const userInfo = Taro.getStorageSync('userInfo') + if (userInfo) { + this.userInfo = userInfo + this.isLoggedIn = true + } + } catch (error) { + console.error('读取用户信息失败:', error) + } } setUserInfo = (userInfo: UserInfo | null) => { @@ -31,12 +59,42 @@ class UserStore { } } + // 从微信登录结果设置用户信息 + setUserInfoFromWechat = (customer: CustomerDto) => { + const userInfo: UserInfo = { + id: customer.id, + nickname: customer.wxNickName || customer.name || '微信用户', + avatar: customer.wxAvatarUrl, + phone: customer.phone, + wxOpenId: customer.wxOpenId, + name: customer.name, + type: customer.type, + typeName: customer.typeName, + amount: customer.amount, + wchart: customer.wchart, + bpSn: customer.bpSn, + bpInfoName: customer.bpInfoName, + instSn: customer.instSn, + ownerName: customer.ownerName, + createTime: customer.createTime, + lastLoginTime: customer.lastLoginTime + } + + this.setUserInfo(userInfo) + this.setBalance(customer.amount || 0) + } + setBalance = (balance: number) => { this.balance = balance } + setLoading = (loading: boolean) => { + this.isLoading = loading + } + logout = () => { this.setUserInfo(null) + this.balance = 0 Taro.removeStorageSync('token') Taro.removeStorageSync('userInfo') } diff --git a/src/types/login.ts b/src/types/login.ts new file mode 100644 index 0000000..5d5a0cd --- /dev/null +++ b/src/types/login.ts @@ -0,0 +1,47 @@ +/** + * 微信登录相关类型定义 + */ + +// 微信登录请求参数 +export interface WechatLoginRequest { + code: string + grpSn?: string +} + +// 客户信息 +export interface CustomerDto { + id: number + sn: string + wxOpenId: string + name: string + type: number + typeName: string + amount: number + wchart: string + phone: string + bpSn: string + bpInfoName: string + instSn: string + ownerName: string + createTime: string + lastLoginTime: string + wxNickName: string + wxAvatarUrl: string +} + +// 微信登录结果数据 +export interface WechatAuthResultDto { + success: boolean + customer: CustomerDto + operationResult: any + isNewCustomer: boolean + message: string +} + +// 微信登录响应 +export interface WechatAuthResponse { + message: string + code: number + success: boolean + data: WechatAuthResultDto +} \ No newline at end of file diff --git a/src/utils/README_imageHelper.md b/src/utils/README_imageHelper.md new file mode 100644 index 0000000..a649383 --- /dev/null +++ b/src/utils/README_imageHelper.md @@ -0,0 +1,176 @@ +# 图片工具使用说明 + +## 概述 + +`imageHelper.ts` 是一个用于管理服务器端大图资源的工具类,可以将本地大图迁移到服务器,减少小程序包体积。 + +## 配置 + +图片服务器地址在 `src/config/index.ts` 中配置: + +```typescript +const BIG_IMAGE_URL = 'http://39.101.75.71:8888/img/MiniBgImage' +``` + +## 使用方法 + +### 1. 基础用法 - 通过文件名获取 + +```typescript +import { getBigImageUrl } from '@/utils/imageHelper' + +// 直接传入文件名 +const imageUrl = getBigImageUrl('noData.png') +// 结果: http://39.101.75.71:8888/img/MiniBgImage/noData.png +``` + +### 2. 推荐用法 - 使用预定义常量 + +```typescript +import { getBigImage, BIG_IMAGES } from '@/utils/imageHelper' + +// 使用预定义的图片键 +const noDataUrl = getBigImage('NO_DATA') +const backgroundUrl = getBigImage('SW_BG') + +// 查看所有可用的图片键 +console.log(BIG_IMAGES) +// { +// NO_DATA: 'noData.png', +// SW_BG: 'swBG.png', +// USER_BG: 'user_bg.png', +// FJMD: 'fjmd.png', +// SMKT: 'smkt.png', +// TGHX: 'tghx.png' +// } +``` + +### 3. 批量获取 + +```typescript +import { getBigImagesUrl } from '@/utils/imageHelper' + +const urls = getBigImagesUrl(['noData.png', 'swBG.png']) +// 结果: [ +// 'http://39.101.75.71:8888/img/MiniBgImage/noData.png', +// 'http://39.101.75.71:8888/img/MiniBgImage/swBG.png' +// ] +``` + +### 4. 图片预加载 + +```typescript +import { preloadImages, getBigImage } from '@/utils/imageHelper' + +// 预加载关键图片 +const keyImages = [ + getBigImage('NO_DATA'), + getBigImage('SW_BG'), + getBigImage('USER_BG') +] + +preloadImages(keyImages).then(() => { + console.log('关键图片预加载完成') +}) +``` + +## 迁移指南 + +### 原来的写法: +```typescript +// ❌ 旧写法 - 本地图片 +import noDataImg from '../../assets/big/noData.png' +const noDataImg = require('../../assets/big/noData.png') + + +``` + +### 现在的写法: +```typescript +// ✅ 新写法 - 服务器图片 +import { getBigImage } from '@/utils/imageHelper' + + +``` + +## 在组件中的使用示例 + +### 空数据组件 +```typescript +import { getBigImage } from '@/utils/imageHelper' + +const EmptyData = () => { + return ( + + + 没有数据哦~ + + ) +} +``` + +### 轮播图组件 +```typescript +import { getBigImage } from '@/utils/imageHelper' + +const Banner = () => { + return ( + + + + + + ) +} +``` + +## 添加新图片 + +1. **将图片上传到服务器**:`http://39.101.75.71:8888/img/MiniBgImage/新图片.png` + +2. **在 `BIG_IMAGES` 中添加映射**: +```typescript +export const BIG_IMAGES = { + // 现有图片... + NEW_IMAGE: '新图片.png', // 添加新图片 +} as const +``` + +3. **在代码中使用**: +```typescript + +``` + +## 注意事项 + +1. **文件名规范**:确保服务器上的文件名与代码中定义的一致 +2. **网络依赖**:图片加载依赖网络,建议添加加载失败的兜底处理 +3. **缓存策略**:小程序会自动缓存网络图片,但首次加载会有延迟 +4. **预加载**:对于关键图片,建议在应用启动时预加载 + +## 错误处理 + +```typescript +// 添加图片加载失败的处理 + { + console.warn('图片加载失败') + // 可以设置默认图片或隐藏图片 + }} +/> +``` + +## 性能优化建议 + +1. **按需加载**:只在需要时获取图片 URL +2. **预加载关键图片**:在应用启动时预加载常用图片 +3. **图片压缩**:确保服务器上的图片已经过压缩优化 +4. **CDN 加速**:考虑使用 CDN 加速图片访问 \ No newline at end of file diff --git a/src/utils/imageHelper.ts b/src/utils/imageHelper.ts new file mode 100644 index 0000000..ed4a303 --- /dev/null +++ b/src/utils/imageHelper.ts @@ -0,0 +1,108 @@ +/** + * 图片资源工具类 + * 用于获取服务器端的大图资源 + */ + +import { config } from '@/config' + +/** + * 获取大图的完整 URL + * @param fileName 图片文件名(包含扩展名) + * @returns 完整的图片 URL + * + * @example + * getBigImageUrl('noData.png') // 返回: http://39.101.75.71:8888/img/MiniBgImage/noData.png + * getBigImageUrl('swBG.png') // 返回: http://39.101.75.71:8888/img/MiniBgImage/swBG.png + */ +export const getBigImageUrl = (fileName: string): string => { + // 确保文件名不为空 + if (!fileName) { + console.warn('图片文件名不能为空') + return '' + } + + // 移除可能的前导斜杠 + const cleanFileName = fileName.startsWith('/') ? fileName.slice(1) : fileName + + return `${config.bigImageUrl}/${cleanFileName}` +} + +/** + * 预定义的大图映射 + * 方便使用和维护,避免硬编码文件名 + */ +export const BIG_IMAGES = { + // 空数据占位图 + NO_DATA: 'noData.png', + + // 背景图片 + SW_BG: 'swBG.png', + USER_BG: 'user_bg.png', + + // 功能图片 + FJMD: 'fjmd.png', + SMKT: 'smkt.png', + TGHX: 'tghx.png', +} as const + +/** + * 获取预定义大图的 URL + * @param imageKey 图片键名 + * @returns 完整的图片 URL + * + * @example + * getBigImage('NO_DATA') // 返回: http://39.101.75.71:8888/img/MiniBgImage/noData.png + * getBigImage('SW_BG') // 返回: http://39.101.75.71:8888/img/MiniBgImage/swBG.png + */ +export const getBigImage = (imageKey: keyof typeof BIG_IMAGES): string => { + const fileName = BIG_IMAGES[imageKey] + if (!fileName) { + console.warn(`未找到图片键: ${imageKey}`) + return '' + } + + return getBigImageUrl(fileName) +} + +/** + * 批量获取大图 URL + * @param fileNames 图片文件名数组 + * @returns 图片 URL 数组 + * + * @example + * getBigImagesUrl(['noData.png', 'swBG.png']) + * // 返回: ['http://39.101.75.71:8888/img/MiniBgImage/noData.png', 'http://39.101.75.71:8888/img/MiniBgImage/swBG.png'] + */ +export const getBigImagesUrl = (fileNames: string[]): string[] => { + return fileNames.map(fileName => getBigImageUrl(fileName)) +} + +/** + * 图片预加载工具 + * @param imageUrls 图片 URL 数组 + * @returns Promise,所有图片加载完成后 resolve + */ +export const preloadImages = (imageUrls: string[]): Promise => { + const promises = imageUrls.map(url => { + return new Promise((resolve, reject) => { + const img = new Image() + img.onload = () => resolve() + img.onerror = () => { + console.warn(`图片预加载失败: ${url}`) + resolve() // 即使失败也 resolve,避免阻塞其他图片 + } + img.src = url + }) + }) + + return Promise.all(promises) +} + +// 默认导出主要方法 +export default { + getBigImageUrl, + getBigImage, + getBigImagesUrl, + preloadImages, + BIG_IMAGES +} \ No newline at end of file diff --git a/src/utils/testImageHelper.ts b/src/utils/testImageHelper.ts new file mode 100644 index 0000000..1fc6377 --- /dev/null +++ b/src/utils/testImageHelper.ts @@ -0,0 +1,36 @@ +/** + * 图片工具测试文件 + * 用于验证服务器图片是否可以正常访问 + */ + +import { getBigImage, getBigImageUrl, BIG_IMAGES } from './imageHelper' + +// 测试所有预定义图片的 URL 生成 +export const testImageUrls = () => { + console.log('=== 图片工具测试 ===') + + // 测试预定义图片 + Object.keys(BIG_IMAGES).forEach(key => { + const url = getBigImage(key as keyof typeof BIG_IMAGES) + console.log(`${key}: ${url}`) + }) + + // 测试直接文件名 + console.log('\n=== 直接文件名测试 ===') + console.log('noData.png:', getBigImageUrl('noData.png')) + console.log('swBG.png:', getBigImageUrl('swBG.png')) + + return { + NO_DATA: getBigImage('NO_DATA'), + SW_BG: getBigImage('SW_BG'), + USER_BG: getBigImage('USER_BG'), + FJMD: getBigImage('FJMD'), + SMKT: getBigImage('SMKT'), + TGHX: getBigImage('TGHX'), + } +} + +// 在开发环境下自动运行测试 +if (process.env.NODE_ENV === 'development') { + testImageUrls() +} \ No newline at end of file