Files
----/前端源码/uni-app/utils/uni-compat.ts

255 lines
6.0 KiB
TypeScript

/**
* uni-app API 兼容层 - 用于 H5 环境
* 提供最小的 API 实现,保持代码不变
*/
// Toast 提示
export function showToast(options: { title: string; icon?: string; duration?: number }) {
const toast = document.createElement('div')
toast.className = 'uni-toast'
toast.textContent = options.title
toast.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 12px 24px;
border-radius: 8px;
font-size: 14px;
z-index: 10000;
max-width: 80%;
text-align: center;
`
document.body.appendChild(toast)
setTimeout(() => {
document.body.removeChild(toast)
}, options.duration || 2000)
}
// Loading 提示
let loadingElement: HTMLElement | null = null
export function showLoading(options: { title?: string; mask?: boolean }) {
hideLoading()
loadingElement = document.createElement('div')
loadingElement.className = 'uni-loading'
loadingElement.innerHTML = `
<div style="
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: ${options.mask ? 'rgba(0, 0, 0, 0.3)' : 'transparent'};
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
">
<div style="
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 20px;
border-radius: 8px;
text-align: center;
">
<div style="
width: 30px;
height: 30px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-top-color: white;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
"></div>
<div>${options.title || '加载中...'}</div>
</div>
</div>
`
// 添加旋转动画
if (!document.getElementById('uni-loading-style')) {
const style = document.createElement('style')
style.id = 'uni-loading-style'
style.textContent = `
@keyframes spin {
to { transform: rotate(360deg); }
}
`
document.head.appendChild(style)
}
document.body.appendChild(loadingElement)
}
export function hideLoading() {
if (loadingElement) {
document.body.removeChild(loadingElement)
loadingElement = null
}
}
// 本地存储
export function setStorageSync(key: string, data: any) {
try {
localStorage.setItem(key, JSON.stringify(data))
} catch (e) {
console.error('setStorageSync error:', e)
}
}
export function getStorageSync(key: string) {
try {
const data = localStorage.getItem(key)
return data ? JSON.parse(data) : null
} catch (e) {
console.error('getStorageSync error:', e)
return null
}
}
export function removeStorageSync(key: string) {
try {
localStorage.removeItem(key)
} catch (e) {
console.error('removeStorageSync error:', e)
}
}
// 导航
export function navigateTo(options: { url: string }) {
const path = options.url.split('?')[0]
const query = options.url.split('?')[1]
const params = new URLSearchParams(query)
if (window.vueRouter) {
window.vueRouter.push({
path,
query: Object.fromEntries(params)
})
}
}
export function redirectTo(options: { url: string }) {
const path = options.url.split('?')[0]
const query = options.url.split('?')[1]
const params = new URLSearchParams(query)
if (window.vueRouter) {
window.vueRouter.replace({
path,
query: Object.fromEntries(params)
})
}
}
export function navigateBack(options?: { delta?: number }) {
if (window.vueRouter) {
window.vueRouter.go(-(options?.delta || 1))
}
}
export function switchTab(options: { url: string }) {
navigateTo(options)
}
// 系统信息
export function getSystemInfoSync() {
return {
statusBarHeight: 0,
windowWidth: window.innerWidth,
windowHeight: window.innerHeight,
platform: 'h5'
}
}
// 请求
export function request(options: any) {
return fetch(options.url, {
method: options.method || 'GET',
headers: options.header || {},
body: options.data ? JSON.stringify(options.data) : undefined
})
.then(res => res.json())
.then(data => {
options.success?.({ data })
return { data }
})
.catch(err => {
options.fail?.(err)
throw err
})
}
// 上传文件
export function uploadFile(options: any) {
const formData = new FormData()
formData.append(options.name, options.filePath)
if (options.formData) {
Object.keys(options.formData).forEach(key => {
formData.append(key, options.formData[key])
})
}
return fetch(options.url, {
method: 'POST',
headers: options.header || {},
body: formData
})
.then(res => res.json())
.then(data => {
options.success?.({ data })
return { data }
})
.catch(err => {
options.fail?.(err)
throw err
})
}
// 选择图片
export function chooseImage(options: any) {
const input = document.createElement('input')
input.type = 'file'
input.accept = 'image/*'
input.multiple = options.count > 1
input.onchange = (e: any) => {
const files = Array.from(e.target.files || [])
const tempFilePaths = files.map((file: any) => URL.createObjectURL(file))
options.success?.({ tempFilePaths, tempFiles: files })
}
input.click()
}
// 全局 uni 对象
export const uni = {
showToast,
showLoading,
hideLoading,
setStorageSync,
getStorageSync,
removeStorageSync,
navigateTo,
redirectTo,
navigateBack,
switchTab,
getSystemInfoSync,
request,
uploadFile,
chooseImage
}
// 挂载到全局
if (typeof window !== 'undefined') {
(window as any).uni = uni
}
export default uni