Files
sh-app/utils/request.js
T

139 lines
3.6 KiB
JavaScript
Raw Normal View History

2026-06-09 19:29:04 +08:00
import { useUserStore } from '@/store'
2026-06-16 19:26:48 +08:00
export const baseUrl = 'https://lygcgs.com.cn:8078/shjapi/api/'
2026-06-24 16:50:38 +08:00
export const baseFileUrl = 'https://lygcgs.com.cn:8078/shj/'
2026-06-09 19:29:04 +08:00
/**
2026-07-06 16:46:07 +08:00
* 将参数对象序列化为 URL query string
* 手动构建确保跨平台(小程序 / H5 / App)行为一致
* - 过滤 undefined 和 null
* - encodeURIComponent 编码中文和特殊字符
2026-06-09 19:29:04 +08:00
*/
2026-07-06 16:46:07 +08:00
function toQueryString(params) {
if (!params) return ''
const parts = Object.keys(params)
.filter((k) => params[k] !== undefined && params[k] !== null)
.map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`)
return parts.length ? '?' + parts.join('&') : ''
2026-06-09 19:29:04 +08:00
}
/**
2026-07-06 16:46:07 +08:00
* 核心请求方法(兼容 小程序 / H5 / App)
*
* @param {string} url - API 路径(不含 baseUrl
* @param {object} options - 可选配置
* {string} method - GET | POST,默认 GET
* {object} data - GET 时自动拼入 query stringPOST 时作为请求体
* {object} header - 自定义请求头
* {boolean} loading - 是否显示 loading,默认 true
* {boolean} toast - 是否在失败时弹 toast,默认 true
2026-06-09 19:29:04 +08:00
*/
2026-07-06 16:46:07 +08:00
export function request(url, options = {}) {
const {
method = 'GET',
data,
header = {},
loading = true,
toast = true
} = options
const userStore = useUserStore()
const headers = {
'content-type': 'application/json',
...header
}
if (userStore.token) {
headers.token = userStore.token
2026-06-09 19:29:04 +08:00
}
2026-07-06 16:46:07 +08:00
// GET: 手动拼 query string(不依赖 uni.request 各平台差异)
let fullUrl = `${baseUrl}${url}`
if (method === 'GET' && data) {
fullUrl += toQueryString(data)
}
2026-06-09 19:29:04 +08:00
2026-07-06 16:46:07 +08:00
if (loading) {
uni.showLoading({ title: '加载中...', mask: true })
}
2026-06-09 19:29:04 +08:00
2026-07-06 16:46:07 +08:00
return new Promise((resolve, reject) => {
uni.request({
url: fullUrl,
method,
data: method === 'POST' ? data : undefined,
header: headers,
success: (res) => {
if (loading) uni.hideLoading()
const body = res.data
if (body.code !== 1) {
if (toast) {
uni.showToast({
title: body.message || '请求失败',
icon: 'none'
})
}
if (body.code === 401) {
userStore.logout()
uni.reLaunch({ url: '/pages/login/index' })
}
reject(new Error(body.message || '请求失败'))
return
}
resolve(body)
},
fail: (err) => {
if (loading) uni.hideLoading()
uni.showToast({ title: '网络连接失败', icon: 'none' })
reject(err)
}
2026-06-09 19:29:04 +08:00
})
2026-07-06 16:46:07 +08:00
})
2026-06-09 19:29:04 +08:00
}
/**
2026-07-06 16:46:07 +08:00
* GET 快捷方法
* 兼容两种调用方式:
* get('/path?key=val') 旧风格(URL 自带参数)
* get('/path', { key: 'val' }) 新风格(参数对象,自动编码)
2026-06-09 19:29:04 +08:00
*/
2026-07-06 16:46:07 +08:00
export const get = (url, params) => {
if (params) {
url += toQueryString(params)
}
return request(url, { method: 'GET' })
2026-06-09 19:29:04 +08:00
}
2026-07-06 16:46:07 +08:00
/**
* POST 快捷方法
*/
export const post = (url, data) => {
return request(url, { method: 'POST', data })
2026-06-09 19:29:04 +08:00
}
2026-06-11 09:43:42 +08:00
2026-06-24 16:50:38 +08:00
/**
* 解析附件 URL 字符串为可展示的照片列表
* @param {string} urlStr - 逗号分隔的附件路径,如 "FileUpLoad/xxx.png,FileUpLoad/yyy.png"
* @param {number} startId - 起始 ID,用于生成唯一标识
* @returns {Array<{_id: number, src: string, uploaded: boolean}>}
*/
export const parseAttachUrls = (urlStr, startId = 0) => {
if (!urlStr) return []
let id = startId
2026-07-06 16:46:07 +08:00
return urlStr.split(',').filter(Boolean).map((url) => ({
2026-06-24 16:50:38 +08:00
_id: ++id,
src: `${baseFileUrl}${url}`,
2026-06-24 20:50:15 +08:00
_attachUrl: url,
2026-06-24 16:50:38 +08:00
uploaded: true
}))
}
2026-06-11 09:43:42 +08:00
export const getUrlParam = (url, name) => {
2026-07-06 16:46:07 +08:00
if (!url || !name) return null
const regex = new RegExp(`[?&]${name}=([^&]*)`, 'i')
const match = url.match(regex)
if (match && match[1]) {
return decodeURIComponent(match[1])
}
return null
}