255 lines
6.0 KiB
TypeScript
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
|