You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
4.1 KiB
271 lines
4.1 KiB
/** |
|
|
|
* 客户信息相关 API |
|
|
|
*/ |
|
|
|
import Taro from '@tarojs/taro' |
|
|
|
import config from '../config' |
|
|
|
import { get, post } from '../services/request' |
|
|
|
import { CustomerDto, UpdateCustomerDto } from '../types/login' |
|
|
|
import { normalizeCustomer } from '../utils/customerNormalize' |
|
|
|
import { pickField, toNumber } from '../utils/apiNormalize' |
|
|
|
import { userStore } from '../store' |
|
|
|
|
|
|
|
export interface CustomerBalanceResult { |
|
|
|
amount: number |
|
|
|
} |
|
|
|
|
|
|
|
interface ResponseResult<T = unknown> { |
|
|
|
message: string |
|
|
|
code: number |
|
|
|
success: boolean |
|
|
|
data: T |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据 OpenId 获取客户信息 |
|
|
|
*/ |
|
|
|
export const getCustomerByOpenId = async (openId: string) => { |
|
|
|
const res = await get<Record<string, unknown>>( |
|
|
|
`/customer/byopenid/${encodeURIComponent(openId)}` |
|
|
|
) |
|
|
|
return { ...res, data: normalizeCustomer(res.data as Record<string, unknown>) } |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 查询客户在指定门店的余额 |
|
|
|
*/ |
|
|
|
export const getCustomerBalance = async (openId: string, bpSn: string) => { |
|
|
|
const res = await get<Record<string, unknown>>('/customer/balance', { |
|
|
|
openid: openId, |
|
|
|
bpsn: bpSn, |
|
|
|
}) |
|
|
|
const amount = toNumber(pickField(res.data as Record<string, unknown>, 'amount')) |
|
|
|
return { ...res, data: { amount } as CustomerBalanceResult } |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 刷新用户资料 + 余额(有 bpSn 时) |
|
|
|
*/ |
|
|
|
export const refreshCustomerProfile = async (openId: string, bpSn?: string) => { |
|
|
|
const profileRes = await getCustomerByOpenId(openId) |
|
|
|
if (profileRes.data) { |
|
|
|
userStore.setUserInfoFromWechat(profileRes.data) |
|
|
|
} |
|
|
|
|
|
|
|
const storeSn = bpSn || profileRes.data?.bpSn || userStore.userInfo?.bpSn |
|
|
|
if (storeSn) { |
|
|
|
try { |
|
|
|
const balanceRes = await getCustomerBalance(openId, storeSn) |
|
|
|
userStore.setBalance(balanceRes.data.amount) |
|
|
|
if (userStore.userInfo) { |
|
|
|
userStore.setUserInfo({ |
|
|
|
...userStore.userInfo, |
|
|
|
amount: balanceRes.data.amount, |
|
|
|
}) |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
console.warn('刷新余额失败:', e) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return profileRes |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* multipart 上传头像(小程序 uploadFile 仅支持 POST) |
|
|
|
*/ |
|
|
|
const uploadCustomerWithAvatar = ( |
|
|
|
customerId: number, |
|
|
|
dto: UpdateCustomerDto |
|
|
|
): Promise<ResponseResult<CustomerDto>> => { |
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
const openId = Taro.getStorageSync('openId') as string |
|
|
|
const formData: Record<string, string> = { id: String(customerId) } |
|
|
|
if (dto.name) formData.name = dto.name |
|
|
|
if (dto.phone) formData.phone = dto.phone |
|
|
|
if (dto.birthday) formData.birthday = dto.birthday |
|
|
|
|
|
|
|
Taro.uploadFile({ |
|
|
|
url: `${config.apiPrefix}/customer/update`, |
|
|
|
filePath: dto.avatarFilePath!, |
|
|
|
name: 'avatarimage', |
|
|
|
formData, |
|
|
|
header: openId ? { 'X-OpenId': openId } : {}, |
|
|
|
success: (res) => { |
|
|
|
try { |
|
|
|
const body = JSON.parse(res.data) as ResponseResult<Record<string, unknown>> |
|
|
|
if (body.success) { |
|
|
|
resolve({ ...body, data: normalizeCustomer(body.data) }) |
|
|
|
} else { |
|
|
|
reject(body) |
|
|
|
} |
|
|
|
} catch (err) { |
|
|
|
reject(err) |
|
|
|
} |
|
|
|
}, |
|
|
|
fail: reject, |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 更新客户信息(昵称、头像、手机号等) |
|
|
|
*/ |
|
|
|
export const updateCustomer = async (customerId: number, dto: UpdateCustomerDto) => { |
|
|
|
if (dto.avatarFilePath) { |
|
|
|
return uploadCustomerWithAvatar(customerId, dto) |
|
|
|
} |
|
|
|
|
|
|
|
const body: Record<string, string> = { id: String(customerId) } |
|
|
|
if (dto.name !== undefined) body.name = dto.name |
|
|
|
if (dto.phone !== undefined) body.phone = dto.phone |
|
|
|
if (dto.birthday !== undefined) body.birthday = dto.birthday |
|
|
|
|
|
|
|
const res = await post<Record<string, unknown>>('/customer/update', body) |
|
|
|
return { ...res, data: normalizeCustomer(res.data) } |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @deprecated 新接口使用 multipart avatarFilePath |
|
|
|
*/ |
|
|
|
export const readImageAsBase64 = (filePath: string): Promise<string> => { |
|
return new Promise((resolve, reject) => { |
|
const fs = Taro.getFileSystemManager() |
|
fs.readFile({ |
|
filePath, |
|
encoding: 'base64', |
|
success: (res) => resolve(res.data as string), |
|
fail: (err: TaroGeneral.CallbackResult) => reject(err), |
|
}) |
|
}) |
|
} |
|
|
|
|
|
|