20 changed files with 825 additions and 60 deletions
@ -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": "" |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
/** |
||||||
|
* 微信登录相关接口 |
||||||
|
*/ |
||||||
|
import request from '../services/request' |
||||||
|
import { WechatLoginRequest, WechatAuthResponse } from '../types/login' |
||||||
|
|
||||||
|
/** |
||||||
|
* 微信登录 |
||||||
|
* @param code 微信登录凭证 |
||||||
|
*/ |
||||||
|
export const wechatLogin = (code: string, grpSn=''): Promise<WechatAuthResponse> => { |
||||||
|
const data: WechatLoginRequest = { code,grpSn } |
||||||
|
|
||||||
|
return request({ |
||||||
|
url: '/WechatAuth/login-wechat', |
||||||
|
method: 'POST', |
||||||
|
data |
||||||
|
}) |
||||||
|
} |
||||||
@ -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 |
||||||
|
} |
||||||
@ -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') |
||||||
|
|
||||||
|
<Image src={noDataImg} /> |
||||||
|
``` |
||||||
|
|
||||||
|
### 现在的写法: |
||||||
|
```typescript |
||||||
|
// ✅ 新写法 - 服务器图片 |
||||||
|
import { getBigImage } from '@/utils/imageHelper' |
||||||
|
|
||||||
|
<Image src={getBigImage('NO_DATA')} /> |
||||||
|
``` |
||||||
|
|
||||||
|
## 在组件中的使用示例 |
||||||
|
|
||||||
|
### 空数据组件 |
||||||
|
```typescript |
||||||
|
import { getBigImage } from '@/utils/imageHelper' |
||||||
|
|
||||||
|
const EmptyData = () => { |
||||||
|
return ( |
||||||
|
<View className="empty-data"> |
||||||
|
<Image |
||||||
|
src={getBigImage('NO_DATA')} |
||||||
|
mode="aspectFit" |
||||||
|
/> |
||||||
|
<Text>没有数据哦~</Text> |
||||||
|
</View> |
||||||
|
) |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### 轮播图组件 |
||||||
|
```typescript |
||||||
|
import { getBigImage } from '@/utils/imageHelper' |
||||||
|
|
||||||
|
const Banner = () => { |
||||||
|
return ( |
||||||
|
<Swiper> |
||||||
|
<Swiper.Item> |
||||||
|
<Image |
||||||
|
src={getBigImage('SW_BG')} |
||||||
|
mode="aspectFill" |
||||||
|
/> |
||||||
|
</Swiper.Item> |
||||||
|
</Swiper> |
||||||
|
) |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## 添加新图片 |
||||||
|
|
||||||
|
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 |
||||||
|
<Image src={getBigImage('NEW_IMAGE')} /> |
||||||
|
``` |
||||||
|
|
||||||
|
## 注意事项 |
||||||
|
|
||||||
|
1. **文件名规范**:确保服务器上的文件名与代码中定义的一致 |
||||||
|
2. **网络依赖**:图片加载依赖网络,建议添加加载失败的兜底处理 |
||||||
|
3. **缓存策略**:小程序会自动缓存网络图片,但首次加载会有延迟 |
||||||
|
4. **预加载**:对于关键图片,建议在应用启动时预加载 |
||||||
|
|
||||||
|
## 错误处理 |
||||||
|
|
||||||
|
```typescript |
||||||
|
// 添加图片加载失败的处理 |
||||||
|
<Image |
||||||
|
src={getBigImage('NO_DATA')} |
||||||
|
mode="aspectFit" |
||||||
|
onError={() => { |
||||||
|
console.warn('图片加载失败') |
||||||
|
// 可以设置默认图片或隐藏图片 |
||||||
|
}} |
||||||
|
/> |
||||||
|
``` |
||||||
|
|
||||||
|
## 性能优化建议 |
||||||
|
|
||||||
|
1. **按需加载**:只在需要时获取图片 URL |
||||||
|
2. **预加载关键图片**:在应用启动时预加载常用图片 |
||||||
|
3. **图片压缩**:确保服务器上的图片已经过压缩优化 |
||||||
|
4. **CDN 加速**:考虑使用 CDN 加速图片访问 |
||||||
@ -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<void[]> => { |
||||||
|
const promises = imageUrls.map(url => { |
||||||
|
return new Promise<void>((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 |
||||||
|
} |
||||||
@ -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() |
||||||
|
} |
||||||
Loading…
Reference in new issue