fix(api): 替换所有接口请求的域名为 guilixu-api.websoft.top
- 将获取 STS Token 的接口地址由 paopao-api 改为 guilixu-api - 更新图片上传接口地址为新的 guilixu-api 域名 - 修改用户推广页面中邀请码链接和二维码接口的域名 - 更改注册页微信登录接口请求的域名为 guilixu-api
This commit is contained in:
21
src/utils/auth.ts
Normal file
21
src/utils/auth.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import Taro from '@tarojs/taro'
|
||||
import { clearStorageByLoginUser } from '@/utils/server'
|
||||
|
||||
export function isLoggedIn(): boolean {
|
||||
return !!Taro.getStorageSync('access_token') && !!Taro.getStorageSync('UserId')
|
||||
}
|
||||
|
||||
export function goToRegister(options?: { redirect?: string }) {
|
||||
const redirect = options?.redirect ? `?redirect=${encodeURIComponent(options.redirect)}` : ''
|
||||
Taro.navigateTo({ url: `/passport/register${redirect}` })
|
||||
}
|
||||
|
||||
export function ensureLoggedIn(redirect?: string): boolean {
|
||||
if (isLoggedIn()) return true
|
||||
goToRegister({ redirect })
|
||||
return false
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
clearStorageByLoginUser()
|
||||
}
|
||||
35
src/utils/common.ts
Normal file
35
src/utils/common.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import Taro from '@tarojs/taro'
|
||||
|
||||
export function wxParse(htmlText: string) {
|
||||
return htmlText
|
||||
.replace(/\<img/gi, '<img style="max-width:100%;height:auto;margin:0;padding:0;display:block;"')
|
||||
.replace(
|
||||
/style\s*?=\s*?(['"])(?!.*?text-align)[\s\S]*?\1/ig,
|
||||
'style="max-width:100%;height:auto;margin:0;padding:0;display:block;"'
|
||||
)
|
||||
}
|
||||
|
||||
export function copyText(text: string) {
|
||||
Taro.setClipboardData({
|
||||
data: text,
|
||||
success() {
|
||||
Taro.showToast({
|
||||
title: '复制成功',
|
||||
icon: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
},
|
||||
fail() {
|
||||
Taro.showToast({
|
||||
title: '复制失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export default function navTo(url: string) {
|
||||
const normalizedUrl = url.startsWith('/') ? url : `/${url}`
|
||||
Taro.navigateTo({ url: normalizedUrl })
|
||||
}
|
||||
131
src/utils/geofence.ts
Normal file
131
src/utils/geofence.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
export type LngLat = { lng: number; lat: number }
|
||||
|
||||
function normalizeLngLat(a: number, b: number): LngLat | null {
|
||||
if (!Number.isFinite(a) || !Number.isFinite(b)) return null
|
||||
const looksLikeLngLat = Math.abs(a) <= 180 && Math.abs(b) <= 90
|
||||
const looksLikeLatLng = Math.abs(a) <= 90 && Math.abs(b) <= 180
|
||||
if (looksLikeLngLat) return { lng: a, lat: b }
|
||||
if (looksLikeLatLng) return { lng: b, lat: a }
|
||||
return null
|
||||
}
|
||||
|
||||
function parsePointLike(v: any): LngLat | null {
|
||||
if (!v) return null
|
||||
if (Array.isArray(v) && v.length >= 2) {
|
||||
return normalizeLngLat(Number(v[0]), Number(v[1]))
|
||||
}
|
||||
if (typeof v === 'object') {
|
||||
const a = v.lng ?? v.lon ?? v.longitude ?? v.x
|
||||
const b = v.lat ?? v.latitude ?? v.y
|
||||
if (a !== undefined && b !== undefined) {
|
||||
return normalizeLngLat(Number(a), Number(b))
|
||||
}
|
||||
}
|
||||
if (typeof v === 'string') {
|
||||
return parseLngLatFromText(v)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function parseLngLatFromText(raw: string | undefined): LngLat | null {
|
||||
const text = (raw || '').trim()
|
||||
if (!text) return null
|
||||
const parts = text.split(/[,\s]+/).filter(Boolean)
|
||||
if (parts.length < 2) return null
|
||||
const a = parts[0]
|
||||
const b = parts[1]
|
||||
if (!a || !b) return null
|
||||
return normalizeLngLat(parseFloat(a), parseFloat(b))
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse fence "points" into a polygon point list.
|
||||
*/
|
||||
export function parseFencePoints(pointsRaw: string | undefined): LngLat[] {
|
||||
const text = (pointsRaw || '').trim()
|
||||
if (!text) return []
|
||||
|
||||
if (text.startsWith('[') || text.startsWith('{')) {
|
||||
try {
|
||||
const parsed = JSON.parse(text)
|
||||
if (Array.isArray(parsed)) {
|
||||
const list = parsed.map(parsePointLike).filter(Boolean) as LngLat[]
|
||||
if (list.length) return list
|
||||
if (Array.isArray(parsed[0])) {
|
||||
const inner = (parsed[0] as any[]).map(parsePointLike).filter(Boolean) as LngLat[]
|
||||
if (inner.length) return inner
|
||||
}
|
||||
}
|
||||
} catch (_e) {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
|
||||
const segments = text.split(/[;|\n\r]+/).map(s => s.trim()).filter(Boolean)
|
||||
if (segments.length > 1) {
|
||||
const list = segments.map(seg => {
|
||||
const nums = seg.match(/-?\d+(\.\d+)?/g) || []
|
||||
if (nums.length < 2) return null
|
||||
const a = nums[0]
|
||||
const b = nums[1]
|
||||
if (!a || !b) return null
|
||||
return normalizeLngLat(parseFloat(a), parseFloat(b))
|
||||
}).filter(Boolean) as LngLat[]
|
||||
if (list.length) return list
|
||||
}
|
||||
|
||||
const nums = text.match(/-?\d+(\.\d+)?/g) || []
|
||||
if (nums.length >= 6 && nums.length % 2 === 0) {
|
||||
const list: LngLat[] = []
|
||||
for (let i = 0; i < nums.length; i += 2) {
|
||||
const a = nums[i]
|
||||
const b = nums[i + 1]
|
||||
if (!a || !b) continue
|
||||
const p = normalizeLngLat(parseFloat(a), parseFloat(b))
|
||||
if (p) list.push(p)
|
||||
}
|
||||
if (list.length) return list
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
function pointOnSegment(p: LngLat, a: LngLat, b: LngLat, eps = 1e-9): boolean {
|
||||
const cross = (b.lat - a.lat) * (p.lng - a.lng) - (b.lng - a.lng) * (p.lat - a.lat)
|
||||
if (Math.abs(cross) > eps) return false
|
||||
const dot = (p.lng - a.lng) * (b.lng - a.lng) + (p.lat - a.lat) * (b.lat - a.lat)
|
||||
if (dot < -eps) return false
|
||||
const lenSq = (b.lng - a.lng) ** 2 + (b.lat - a.lat) ** 2
|
||||
return dot <= lenSq + eps
|
||||
}
|
||||
|
||||
export function pointInPolygon(p: LngLat, polygon: LngLat[]): boolean {
|
||||
if (!polygon || polygon.length < 3) return false
|
||||
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const a = polygon[j]
|
||||
const b = polygon[i]
|
||||
if (pointOnSegment(p, a, b)) return true
|
||||
}
|
||||
|
||||
let inside = false
|
||||
const x = p.lng
|
||||
const y = p.lat
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i].lng
|
||||
const yi = polygon[i].lat
|
||||
const xj = polygon[j].lng
|
||||
const yj = polygon[j].lat
|
||||
|
||||
const intersect = (yi > y) !== (yj > y) && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi
|
||||
if (intersect) inside = !inside
|
||||
}
|
||||
return inside
|
||||
}
|
||||
|
||||
export function pointInAnyPolygon(p: LngLat, polygons: LngLat[][]): boolean {
|
||||
for (const poly of polygons) {
|
||||
if (pointInPolygon(p, poly)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
114
src/utils/index.ts
Normal file
114
src/utils/index.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import dayjs from 'dayjs'
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
* @param date 日期
|
||||
* @param format 格式
|
||||
* @returns 格式化后的日期字符串
|
||||
*/
|
||||
export const formatDate = (date: Date | string, format = 'YYYY-MM-DD HH:mm:ss') => {
|
||||
return dayjs(date).format(format)
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5 加密
|
||||
* @param str 待加密字符串
|
||||
* @returns MD5 值
|
||||
*/
|
||||
export const md5 = (str: string) => {
|
||||
return CryptoJS.MD5(str).toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* AES 加密
|
||||
* @param data 待加密数据
|
||||
* @param key 密钥
|
||||
* @returns 加密后的字符串
|
||||
*/
|
||||
export const aesEncrypt = (data: string, key: string) => {
|
||||
return CryptoJS.AES.encrypt(data, key).toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* AES 解密
|
||||
* @param encrypted 加密字符串
|
||||
* @param key 密钥
|
||||
* @returns 解密后的字符串
|
||||
*/
|
||||
export const aesDecrypt = (encrypted: string, key: string) => {
|
||||
return CryptoJS.AES.decrypt(encrypted, key).toString(CryptoJS.enc.Utf8)
|
||||
}
|
||||
|
||||
/**
|
||||
* 防抖函数
|
||||
* @param fn 目标函数
|
||||
* @param delay 延迟时间
|
||||
* @returns 防抖后的函数
|
||||
*/
|
||||
export const debounce = <T extends (...args: any[]) => any>(
|
||||
fn: T,
|
||||
delay: number
|
||||
): ((...args: Parameters<T>) => void) => {
|
||||
let timer: NodeJS.Timeout
|
||||
|
||||
return (...args: Parameters<T>) => {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(() => fn(...args), delay)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 节流函数
|
||||
* @param fn 目标函数
|
||||
* @param interval 间隔时间
|
||||
* @returns 节流后的函数
|
||||
*/
|
||||
export const throttle = <T extends (...args: any[]) => any>(
|
||||
fn: T,
|
||||
interval: number
|
||||
): ((...args: Parameters<T>) => void) => {
|
||||
let lastTime = 0
|
||||
|
||||
return (...args: Parameters<T>) => {
|
||||
const now = Date.now()
|
||||
if (now - lastTime >= interval) {
|
||||
lastTime = now
|
||||
fn(...args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 深拷贝
|
||||
* @param obj 目标对象
|
||||
* @returns 拷贝后的对象
|
||||
*/
|
||||
export const deepClone = <T>(obj: T): T => {
|
||||
if (obj === null || typeof obj !== 'object') {
|
||||
return obj
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(item => deepClone(item)) as T
|
||||
}
|
||||
|
||||
const cloned = {} as T
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
cloned[key] = deepClone(obj[key])
|
||||
}
|
||||
}
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
export default {
|
||||
formatDate,
|
||||
md5,
|
||||
aesEncrypt,
|
||||
aesDecrypt,
|
||||
debounce,
|
||||
throttle,
|
||||
deepClone
|
||||
}
|
||||
66
src/utils/invite.ts
Normal file
66
src/utils/invite.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import Taro from '@tarojs/taro'
|
||||
|
||||
export interface InviteParams {
|
||||
inviter?: string
|
||||
source?: string
|
||||
t?: string
|
||||
}
|
||||
|
||||
const STORAGE_KEY = 'invite_params'
|
||||
|
||||
export function parseInviteParams(options: any): InviteParams | null {
|
||||
try {
|
||||
const query = options?.query || options || {}
|
||||
if (query.inviter) {
|
||||
return {
|
||||
inviter: String(query.inviter),
|
||||
source: query.source ? String(query.source) : 'share',
|
||||
t: query.t ? String(query.t) : undefined,
|
||||
}
|
||||
}
|
||||
if (query.scene && String(query.scene).startsWith('uid_')) {
|
||||
return {
|
||||
inviter: String(query.scene).replace('uid_', ''),
|
||||
source: 'qrcode',
|
||||
t: Date.now().toString(),
|
||||
}
|
||||
}
|
||||
return null
|
||||
} catch (_error) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function saveInviteParams(params: InviteParams) {
|
||||
Taro.setStorageSync(STORAGE_KEY, {
|
||||
...params,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
}
|
||||
|
||||
export function getStoredInviteParams(): InviteParams | null {
|
||||
const stored = Taro.getStorageSync(STORAGE_KEY)
|
||||
if (!stored?.inviter) return null
|
||||
return {
|
||||
inviter: stored.inviter,
|
||||
source: stored.source,
|
||||
t: stored.t,
|
||||
}
|
||||
}
|
||||
|
||||
export function clearInviteParams() {
|
||||
Taro.removeStorageSync(STORAGE_KEY)
|
||||
}
|
||||
|
||||
export function hasPendingInvite() {
|
||||
return !!getStoredInviteParams()?.inviter
|
||||
}
|
||||
|
||||
export function trackInviteSource(_source: string, _inviterId?: number) {
|
||||
return
|
||||
}
|
||||
|
||||
export async function checkAndHandleInviteRelation() {
|
||||
clearInviteParams()
|
||||
return true
|
||||
}
|
||||
284
src/utils/request.ts
Normal file
284
src/utils/request.ts
Normal file
@@ -0,0 +1,284 @@
|
||||
import Taro from '@tarojs/taro'
|
||||
import { BaseUrl, TenantId } from '@/config/app'
|
||||
import { clearStorageByLoginUser } from '@/utils/server'
|
||||
|
||||
export interface RequestConfig {
|
||||
url: string
|
||||
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
||||
data?: any
|
||||
header?: Record<string, string>
|
||||
timeout?: number
|
||||
retry?: number
|
||||
showLoading?: boolean
|
||||
showError?: boolean
|
||||
returnRaw?: boolean
|
||||
}
|
||||
|
||||
interface ApiResponse<T = any> {
|
||||
code: number
|
||||
message?: string
|
||||
data?: T
|
||||
}
|
||||
|
||||
export enum ErrorType {
|
||||
NETWORK_ERROR = 'NETWORK_ERROR',
|
||||
TIMEOUT_ERROR = 'TIMEOUT_ERROR',
|
||||
BUSINESS_ERROR = 'BUSINESS_ERROR',
|
||||
AUTH_ERROR = 'AUTH_ERROR',
|
||||
UNKNOWN_ERROR = 'UNKNOWN_ERROR',
|
||||
}
|
||||
|
||||
export class RequestError extends Error {
|
||||
public type: ErrorType
|
||||
public code?: number
|
||||
public data?: any
|
||||
|
||||
constructor(message: string, type: ErrorType, code?: number, data?: any) {
|
||||
super(message)
|
||||
this.name = 'RequestError'
|
||||
this.type = type
|
||||
this.code = code
|
||||
this.data = data
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_CONFIG: Required<Pick<RequestConfig, 'timeout' | 'retry' | 'showLoading' | 'showError' | 'returnRaw'>> = {
|
||||
timeout: 10000,
|
||||
retry: 2,
|
||||
showLoading: false,
|
||||
showError: true,
|
||||
returnRaw: true,
|
||||
}
|
||||
|
||||
const baseUrl = BaseUrl
|
||||
|
||||
const requestInterceptor = (config: RequestConfig): RequestConfig => {
|
||||
const token = Taro.getStorageSync('access_token')
|
||||
const tenantId = Taro.getStorageSync('TenantId') || TenantId
|
||||
|
||||
const defaultHeaders: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
TenantId: String(tenantId),
|
||||
}
|
||||
|
||||
if (token) {
|
||||
defaultHeaders.Authorization = token
|
||||
}
|
||||
|
||||
config.header = { ...defaultHeaders, ...config.header }
|
||||
|
||||
if (config.showLoading) {
|
||||
Taro.showLoading({ title: '加载中...' })
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// Redis 临时故障关键词 - 这类 401 是服务端问题,不应清除本地 token
|
||||
const REDIS_ERROR_KEYWORDS = ['RedisSystemException', 'RedisException', 'Operation timed out', 'Redis']
|
||||
|
||||
const isRedisError = (message?: string): boolean => {
|
||||
if (!message) return false
|
||||
return REDIS_ERROR_KEYWORDS.some((keyword) => message.includes(keyword))
|
||||
}
|
||||
|
||||
// 防抖:避免同一时间多个接口都触发跳登录页
|
||||
let authErrorTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const handleAuthError = (message?: string) => {
|
||||
// Redis 临时故障导致的 401,不清除 token,静默处理
|
||||
if (isRedisError(message)) {
|
||||
console.warn('[Auth] Redis 临时故障导致 401,忽略处理:', message)
|
||||
return
|
||||
}
|
||||
|
||||
clearStorageByLoginUser()
|
||||
|
||||
// 防抖:多个接口同时 401 只弹一次 Toast
|
||||
if (authErrorTimer) return
|
||||
authErrorTimer = setTimeout(() => {
|
||||
authErrorTimer = null
|
||||
}, 3000)
|
||||
|
||||
Taro.showToast({
|
||||
title: '登录已过期,请重新登录',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
})
|
||||
}
|
||||
|
||||
const responseInterceptor = <T>(response: any, config: RequestConfig): T => {
|
||||
if (config.showLoading) {
|
||||
Taro.hideLoading()
|
||||
}
|
||||
|
||||
const { statusCode, data } = response
|
||||
|
||||
if (statusCode !== 200) {
|
||||
throw new RequestError(`HTTP错误: ${statusCode}`, ErrorType.NETWORK_ERROR, statusCode, data)
|
||||
}
|
||||
|
||||
if (data === null || data === undefined) {
|
||||
throw new RequestError('响应数据为空', ErrorType.NETWORK_ERROR, statusCode, data)
|
||||
}
|
||||
|
||||
if (typeof data === 'object' && data !== null && 'code' in data) {
|
||||
const apiResponse = data as ApiResponse<T>
|
||||
|
||||
if (apiResponse.code === 0) {
|
||||
return (config.returnRaw ? data : apiResponse.data) as T
|
||||
}
|
||||
|
||||
if (apiResponse.code === 401 || apiResponse.code === 403) {
|
||||
handleAuthError(apiResponse.message)
|
||||
throw new RequestError(apiResponse.message || '认证失败', ErrorType.AUTH_ERROR, apiResponse.code, apiResponse.data)
|
||||
}
|
||||
|
||||
throw new RequestError(apiResponse.message || '请求失败', ErrorType.BUSINESS_ERROR, apiResponse.code, apiResponse.data)
|
||||
}
|
||||
|
||||
return data as T
|
||||
}
|
||||
|
||||
const handleError = (error: RequestError, config: RequestConfig) => {
|
||||
if (config.showLoading) {
|
||||
Taro.hideLoading()
|
||||
}
|
||||
|
||||
if (!config.showError) return
|
||||
|
||||
const titleMap: Record<ErrorType, string> = {
|
||||
[ErrorType.NETWORK_ERROR]: '网络连接失败',
|
||||
[ErrorType.TIMEOUT_ERROR]: '请求超时',
|
||||
[ErrorType.BUSINESS_ERROR]: error.message || '操作失败',
|
||||
[ErrorType.AUTH_ERROR]: '认证失败',
|
||||
[ErrorType.UNKNOWN_ERROR]: '未知错误',
|
||||
}
|
||||
|
||||
Taro.showToast({
|
||||
title: titleMap[error.type] || '请求失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
})
|
||||
}
|
||||
|
||||
const executeRequest = <T>(config: RequestConfig): Promise<T> =>
|
||||
new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
reject(new RequestError('请求超时', ErrorType.TIMEOUT_ERROR))
|
||||
}, config.timeout || DEFAULT_CONFIG.timeout)
|
||||
|
||||
Taro.request({
|
||||
url: config.url,
|
||||
method: config.method || 'GET',
|
||||
data: config.data || {},
|
||||
header: config.header || {},
|
||||
success: (res) => {
|
||||
clearTimeout(timer)
|
||||
try {
|
||||
resolve(responseInterceptor<T>(res, config))
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
clearTimeout(timer)
|
||||
reject(new RequestError(err.errMsg || '网络请求失败', ErrorType.NETWORK_ERROR, undefined, err))
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const retryRequest = async <T>(config: RequestConfig, retryCount = 0): Promise<T> => {
|
||||
try {
|
||||
return await executeRequest<T>(config)
|
||||
} catch (error) {
|
||||
const requestError = error as RequestError
|
||||
if (requestError.type === ErrorType.AUTH_ERROR || requestError.type === ErrorType.BUSINESS_ERROR) {
|
||||
throw error
|
||||
}
|
||||
if (retryCount < (config.retry || DEFAULT_CONFIG.retry)) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000 * (retryCount + 1)))
|
||||
return retryRequest<T>(config, retryCount + 1)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export async function request<T>(options: RequestConfig): Promise<T> {
|
||||
try {
|
||||
const config = requestInterceptor({ ...DEFAULT_CONFIG, ...options })
|
||||
return await retryRequest<T>(config)
|
||||
} catch (error) {
|
||||
const requestError = error as RequestError
|
||||
handleError(requestError, options)
|
||||
throw requestError
|
||||
}
|
||||
}
|
||||
|
||||
const buildUrl = (url: string): string => {
|
||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||
return url
|
||||
}
|
||||
return `${baseUrl}${url}`
|
||||
}
|
||||
|
||||
const buildQueryString = (params: Record<string, any>): string => {
|
||||
const queryString = Object.keys(params)
|
||||
.filter((key) => params[key] !== undefined && params[key] !== null)
|
||||
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
||||
.join('&')
|
||||
return queryString ? `?${queryString}` : ''
|
||||
}
|
||||
|
||||
export function get<T>(url: string, params?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
const fullUrl = buildUrl(url) + (params ? buildQueryString(params) : '')
|
||||
return request<T>({ url: fullUrl, method: 'GET', returnRaw: true, ...config })
|
||||
}
|
||||
|
||||
export function post<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
return request<T>({ url: buildUrl(url), method: 'POST', data, returnRaw: true, ...config })
|
||||
}
|
||||
|
||||
export function put<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
return request<T>({ url: buildUrl(url), method: 'PUT', data, returnRaw: true, ...config })
|
||||
}
|
||||
|
||||
export function patch<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
return request<T>({ url: buildUrl(url), method: 'PATCH', data, returnRaw: true, ...config })
|
||||
}
|
||||
|
||||
export function del<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
return request<T>({ url: buildUrl(url), method: 'DELETE', data, returnRaw: true, ...config })
|
||||
}
|
||||
|
||||
export function getData<T>(url: string, params?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
const fullUrl = buildUrl(url) + (params ? buildQueryString(params) : '')
|
||||
return request<T>({ url: fullUrl, method: 'GET', returnRaw: false, ...config })
|
||||
}
|
||||
|
||||
export function postData<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
return request<T>({ url: buildUrl(url), method: 'POST', data, returnRaw: false, ...config })
|
||||
}
|
||||
|
||||
export function putData<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
return request<T>({ url: buildUrl(url), method: 'PUT', data, returnRaw: false, ...config })
|
||||
}
|
||||
|
||||
export function delData<T>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<T> {
|
||||
return request<T>({ url: buildUrl(url), method: 'DELETE', data, returnRaw: false, ...config })
|
||||
}
|
||||
|
||||
export default {
|
||||
request,
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
patch,
|
||||
del,
|
||||
getData,
|
||||
postData,
|
||||
putData,
|
||||
delData,
|
||||
ErrorType,
|
||||
RequestError,
|
||||
}
|
||||
23
src/utils/server.ts
Normal file
23
src/utils/server.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import Taro from '@tarojs/taro'
|
||||
import { ServerBaseUrl } from '@/config/app'
|
||||
import type { User } from '@/api/system/user/model'
|
||||
|
||||
export const SERVER_API_URL = ServerBaseUrl
|
||||
|
||||
export function saveStorageByLoginUser(token: string, user: User) {
|
||||
Taro.setStorageSync('TenantId', user.tenantId)
|
||||
Taro.setStorageSync('access_token', token)
|
||||
Taro.setStorageSync('UserId', user.userId)
|
||||
Taro.setStorageSync('Phone', user.phone)
|
||||
Taro.setStorageSync('WxNickName', user.nickname)
|
||||
Taro.setStorageSync('User', user)
|
||||
}
|
||||
|
||||
export function clearStorageByLoginUser() {
|
||||
Taro.removeStorageSync('TenantId')
|
||||
Taro.removeStorageSync('access_token')
|
||||
Taro.removeStorageSync('UserId')
|
||||
Taro.removeStorageSync('Phone')
|
||||
Taro.removeStorageSync('WxNickName')
|
||||
Taro.removeStorageSync('User')
|
||||
}
|
||||
Reference in New Issue
Block a user