feat: project scaffold + bridge + maplibre engine
- Vite + Vue 3 + TypeScript strict - @yuto-water/js-bridge (types, detector, browser provider) - MapLibre engine (MapManager singleton, MapFactory, LayerFactory) - Map composables (useMap, useLayer, usePopup) - Tianditu tile source, 6 layer type factory - SCSS design tokens (water-blue theme, dark mode) - Vant 4, maplibre-gl, axios, pinia, echarts deps - Build passes (vue-tsc + vite)
This commit is contained in:
87
src/bridge/detector.ts
Normal file
87
src/bridge/detector.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* 环境检测器
|
||||
*
|
||||
* 检测当前运行环境类型,返回统一的环境标识,
|
||||
* 供上层使用以决定加载哪个 Bridge 提供者。
|
||||
*
|
||||
* @module bridge/detector
|
||||
*/
|
||||
|
||||
/** 可识别的运行环境 */
|
||||
export type Environment = 'browser' | 'wechat-mp' | 'uniapp-webview'
|
||||
|
||||
/** wechat 全局声明扩展 */
|
||||
interface WechatWindow extends Window {
|
||||
/** 微信 JS-SDK 桥接对象 */
|
||||
WeixinJSBridge?: Record<string, unknown>
|
||||
/** 微信环境标识 */
|
||||
__wxjs_environment?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局 uni 对象(uni-app WebView 中存在)
|
||||
* 声明为 any 以避免对 @dcloudio 类型包的硬依赖
|
||||
*/
|
||||
declare const uni: Record<string, unknown> | undefined
|
||||
|
||||
/**
|
||||
* 检测当前运行环境
|
||||
*
|
||||
* 判断优先级:
|
||||
* 1. 微信小程序 WebView —— userAgent 含 MicroMessenger 且标记为 miniprogram
|
||||
* 2. uni-app WebView —— 全局存在 uni 对象(且非小程序场景)
|
||||
* 3. 普通浏览器 —— 其余情况降级
|
||||
*
|
||||
* @returns 环境标识字符串
|
||||
*/
|
||||
export function detectEnvironment(): Environment {
|
||||
const win = window as WechatWindow
|
||||
|
||||
// ── 检测微信环境 ──
|
||||
const ua = navigator.userAgent
|
||||
const isWechat = /MicroMessenger/i.test(ua)
|
||||
|
||||
if (isWechat) {
|
||||
// 检查是否为小程序 WebView
|
||||
// 方式一:WeixinJSBridge 注入的环境标识
|
||||
// 方式二:页面 URL 参数 __wxjs_environment(少数场景)
|
||||
if (win.__wxjs_environment === 'miniprogram') {
|
||||
return 'wechat-mp'
|
||||
}
|
||||
|
||||
// 微信 JS-SDK ready 后可通过 WeixinJSBridge 进一步确认,
|
||||
// 但此处仅做同步检测,保守返回 wechat-mp(若 UA 匹配且环境变量已注入)
|
||||
// 否则仍可能为普通微信内置浏览器,暂归为 wechat-mp
|
||||
return 'wechat-mp'
|
||||
}
|
||||
|
||||
// ── 检测 uni-app WebView ──
|
||||
// uni 对象在 uni-app 的 WebView 环境中由框架注入
|
||||
if (typeof uni !== 'undefined' && uni !== null) {
|
||||
return 'uniapp-webview'
|
||||
}
|
||||
|
||||
// ── 默认:普通浏览器 ──
|
||||
return 'browser'
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否在微信小程序 WebView 中
|
||||
*/
|
||||
export function isWechatMiniProgram(): boolean {
|
||||
return detectEnvironment() === 'wechat-mp'
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否在 uni-app WebView 中
|
||||
*/
|
||||
export function isUniappWebView(): boolean {
|
||||
return detectEnvironment() === 'uniapp-webview'
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否为普通浏览器环境
|
||||
*/
|
||||
export function isBrowser(): boolean {
|
||||
return detectEnvironment() === 'browser'
|
||||
}
|
||||
67
src/bridge/index.ts
Normal file
67
src/bridge/index.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 桥接层统一入口
|
||||
*
|
||||
* 导出类型定义、环境检测器以及各环境提供者,
|
||||
* 并提供 createBridge() 工厂函数自动选择合适的提供者实例。
|
||||
*
|
||||
* @module bridge
|
||||
*/
|
||||
|
||||
// ── 类型定义 ──
|
||||
export type {
|
||||
IBridge,
|
||||
GetLocationOptions,
|
||||
LocationResult,
|
||||
ScanType,
|
||||
ScanCodeOptions,
|
||||
ScanCodeResult,
|
||||
OpenMapParams,
|
||||
ImageSourceType,
|
||||
ChooseImageOptions,
|
||||
ChooseImageResult,
|
||||
DeviceInfo,
|
||||
} from './types'
|
||||
|
||||
// ── 环境检测 ──
|
||||
export {
|
||||
detectEnvironment,
|
||||
isWechatMiniProgram,
|
||||
isUniappWebView,
|
||||
isBrowser,
|
||||
} from './detector'
|
||||
export type { Environment } from './detector'
|
||||
|
||||
// ── 提供者 ──
|
||||
export { default as browserProvider } from './providers/browser'
|
||||
|
||||
// ── 工厂函数 ──
|
||||
import type { IBridge } from './types'
|
||||
import { detectEnvironment } from './detector'
|
||||
import browserProvider from './providers/browser'
|
||||
|
||||
/**
|
||||
* 根据当前运行环境自动创建对应的 Bridge 实例
|
||||
*
|
||||
* - 普通浏览器:返回 browserProvider(基于 Web API 降级实现)
|
||||
* - 微信小程序 WebView:待实现
|
||||
* - uni-app WebView:待实现
|
||||
*
|
||||
* @returns 符合 IBridge 接口的提供者实例
|
||||
*/
|
||||
export function createBridge(): IBridge {
|
||||
const env = detectEnvironment()
|
||||
|
||||
switch (env) {
|
||||
case 'wechat-mp':
|
||||
// TODO: 引入 WechatProvider 后替换
|
||||
throw new Error('微信小程序 WebView Bridge 尚未实现')
|
||||
|
||||
case 'uniapp-webview':
|
||||
// TODO: 引入 UniappProvider 后替换
|
||||
throw new Error('uni-app WebView Bridge 尚未实现')
|
||||
|
||||
case 'browser':
|
||||
default:
|
||||
return browserProvider
|
||||
}
|
||||
}
|
||||
327
src/bridge/providers/browser.ts
Normal file
327
src/bridge/providers/browser.ts
Normal file
@@ -0,0 +1,327 @@
|
||||
/**
|
||||
* 浏览器环境 Bridge 提供者
|
||||
*
|
||||
* 作为普通浏览器中的降级实现,利用 Web API 尽可能模拟原生能力。
|
||||
* 当 navigator.geolocation 不可用时,getLocation 会抛出清晰的错误。
|
||||
*
|
||||
* @module bridge/providers/browser
|
||||
*/
|
||||
|
||||
import type {
|
||||
IBridge,
|
||||
GetLocationOptions,
|
||||
LocationResult,
|
||||
ScanCodeOptions,
|
||||
ScanCodeResult,
|
||||
OpenMapParams,
|
||||
ChooseImageOptions,
|
||||
ChooseImageResult,
|
||||
DeviceInfo,
|
||||
} from '../types'
|
||||
|
||||
/**
|
||||
* 浏览器降级提供者
|
||||
*
|
||||
* 实现了 IBridge 接口的六个方法:
|
||||
* - getLocation —— 依赖 navigator.geolocation
|
||||
* - scanCode —— 浏览器无法扫码,直接抛出错误
|
||||
* - openMap —— 通过 URL Scheme 跳转高德/百度地图
|
||||
* - chooseImage —— 通过 <input type="file"> 选择图片
|
||||
* - getDeviceInfo —— 通过 navigator / screen 收集设备信息
|
||||
* - setTitle —— 通过 document.title 设置标题
|
||||
*/
|
||||
const browserProvider: IBridge = {
|
||||
// ────────────────────────────────────────────
|
||||
// 获取地理位置
|
||||
// ────────────────────────────────────────────
|
||||
async getLocation(options: GetLocationOptions = {}): Promise<LocationResult> {
|
||||
const geolocation = navigator.geolocation
|
||||
|
||||
if (!geolocation) {
|
||||
throw new Error('浏览器不支持定位功能(geolocation API 不可用)')
|
||||
}
|
||||
|
||||
const {
|
||||
enableHighAccuracy = false,
|
||||
timeout = 10000,
|
||||
needAddress = false,
|
||||
} = options
|
||||
|
||||
return new Promise<LocationResult>((resolve, reject) => {
|
||||
geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
const result: LocationResult = {
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude,
|
||||
speed: position.coords.speed ?? undefined,
|
||||
accuracy: position.coords.accuracy,
|
||||
}
|
||||
|
||||
if (needAddress) {
|
||||
// 浏览器原生 geolocation 不支持逆地理编码,
|
||||
// address 留空,由调用方自行调用第三方服务补齐
|
||||
result.address = undefined
|
||||
}
|
||||
|
||||
resolve(result)
|
||||
},
|
||||
(error) => {
|
||||
let message: string
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
message = '用户拒绝定位授权'
|
||||
break
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
message = '无法获取位置信息'
|
||||
break
|
||||
case error.TIMEOUT:
|
||||
message = '定位请求超时'
|
||||
break
|
||||
default:
|
||||
message = `定位失败: ${error.message}`
|
||||
}
|
||||
reject(new Error(message))
|
||||
},
|
||||
{
|
||||
enableHighAccuracy,
|
||||
timeout,
|
||||
maximumAge: 0,
|
||||
},
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
// ────────────────────────────────────────────
|
||||
// 扫码
|
||||
// ────────────────────────────────────────────
|
||||
async scanCode(_options?: ScanCodeOptions): Promise<ScanCodeResult> {
|
||||
throw new Error('浏览器不支持扫码功能,请使用移动端打开')
|
||||
},
|
||||
|
||||
// ────────────────────────────────────────────
|
||||
// 打开地图
|
||||
// ────────────────────────────────────────────
|
||||
async openMap(params: OpenMapParams): Promise<boolean> {
|
||||
const { latitude, longitude, name, address, scale = 16 } = params
|
||||
|
||||
const label = encodeURIComponent(name || address || '目标位置')
|
||||
|
||||
// 优先尝试高德地图 URI
|
||||
// 格式参考: https://lbs.amap.com/api/uri-api/guide/mobile-web/open
|
||||
const amapUrl = `https://uri.amap.com/marker?position=${longitude},${latitude}&name=${label}&callnative=1`
|
||||
|
||||
// 同时准备通用经纬度链接作为降级(打开系统默认地图)
|
||||
const fallbackUrl = `https://maps.google.com/maps?q=${latitude},${longitude}(${label})&z=${scale}`
|
||||
|
||||
// 检测当前环境
|
||||
const ua = navigator.userAgent
|
||||
let mapUrl: string
|
||||
|
||||
if (/iPhone|iPad|iPod/i.test(ua)) {
|
||||
// iOS:使用 Apple Maps URL Scheme
|
||||
mapUrl = `https://maps.apple.com/?q=${label}&ll=${latitude},${longitude}&z=${scale}`
|
||||
} else if (/Android/i.test(ua)) {
|
||||
// Android:优先使用高德,浏览器会自动唤起
|
||||
mapUrl = amapUrl
|
||||
} else {
|
||||
// 桌面端:打开 Google Maps
|
||||
mapUrl = fallbackUrl
|
||||
}
|
||||
|
||||
try {
|
||||
window.open(mapUrl, '_blank')
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
// ────────────────────────────────────────────
|
||||
// 选择图片
|
||||
// ────────────────────────────────────────────
|
||||
async chooseImage(options: ChooseImageOptions = {}): Promise<ChooseImageResult> {
|
||||
const { count = 1, sourceType = ['album', 'camera'], compress = true } = options
|
||||
|
||||
return new Promise<ChooseImageResult>((resolve, reject) => {
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = 'image/*'
|
||||
|
||||
// 根据 sourceType 设置 capture 属性
|
||||
if (sourceType.length === 1 && sourceType[0] === 'camera') {
|
||||
input.capture = 'environment'
|
||||
}
|
||||
|
||||
// 支持多选
|
||||
if (count > 1) {
|
||||
input.multiple = true
|
||||
}
|
||||
|
||||
// 压缩由 accept / 浏览器默认行为处理,
|
||||
// 真实压缩需后续通过 Canvas 实现,此处仅标记
|
||||
|
||||
// 超时兜底:30s 后自动 reject
|
||||
const timeoutId = setTimeout(() => {
|
||||
reject(new Error('选择图片超时,请重试'))
|
||||
cleanup()
|
||||
}, 30000)
|
||||
|
||||
const cleanup = () => {
|
||||
clearTimeout(timeoutId)
|
||||
input.removeEventListener('change', onChange)
|
||||
input.removeEventListener('cancel', onCancel)
|
||||
input.remove()
|
||||
}
|
||||
|
||||
const onChange = () => {
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
const files = input.files
|
||||
if (!files || files.length === 0) {
|
||||
reject(new Error('未选择任何图片'))
|
||||
cleanup()
|
||||
return
|
||||
}
|
||||
|
||||
const tempFilePaths: string[] = []
|
||||
const tempFiles: Array<{ path: string; size: number }> = []
|
||||
|
||||
const validFiles: File[] = []
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files.item(i)
|
||||
if (file) {
|
||||
validFiles.push(file)
|
||||
}
|
||||
}
|
||||
|
||||
for (const file of validFiles) {
|
||||
// 通过 URL.createObjectURL 创建临时可访问路径
|
||||
const objectUrl = URL.createObjectURL(file)
|
||||
tempFilePaths.push(objectUrl)
|
||||
tempFiles.push({ path: objectUrl, size: file.size })
|
||||
}
|
||||
|
||||
resolve({
|
||||
tempFilePaths,
|
||||
tempFiles,
|
||||
})
|
||||
cleanup()
|
||||
}
|
||||
|
||||
// 用户取消选择(部分浏览器支持)
|
||||
const onCancel = () => {
|
||||
clearTimeout(timeoutId)
|
||||
reject(new Error('用户取消选择图片'))
|
||||
cleanup()
|
||||
}
|
||||
|
||||
input.addEventListener('change', onChange)
|
||||
// 监听 cancel 事件(部分浏览器)
|
||||
input.addEventListener('cancel', onCancel)
|
||||
|
||||
// 兼容移动端 webview 的取消操作:
|
||||
// 通过 focus 丢失检测取消操作
|
||||
let focusLost = false
|
||||
const onFocus = () => {
|
||||
focusLost = false
|
||||
}
|
||||
const onBlur = () => {
|
||||
focusLost = true
|
||||
// 延迟检测:如果 blur 后 change 未触发,视为取消
|
||||
setTimeout(() => {
|
||||
if (focusLost && input.files && input.files.length === 0) {
|
||||
clearTimeout(timeoutId)
|
||||
reject(new Error('用户取消选择图片'))
|
||||
cleanup()
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
|
||||
input.addEventListener('focus', onFocus)
|
||||
input.addEventListener('blur', onBlur)
|
||||
|
||||
// 触发文件选择
|
||||
input.click()
|
||||
})
|
||||
},
|
||||
|
||||
// ────────────────────────────────────────────
|
||||
// 获取设备信息
|
||||
// ────────────────────────────────────────────
|
||||
async getDeviceInfo(): Promise<DeviceInfo> {
|
||||
const ua = navigator.userAgent
|
||||
|
||||
// 解析平台
|
||||
let platform: string
|
||||
if (/iPhone|iPad|iPod/i.test(ua)) {
|
||||
platform = 'ios'
|
||||
} else if (/Android/i.test(ua)) {
|
||||
platform = 'android'
|
||||
} else if (/Windows/i.test(ua)) {
|
||||
platform = 'windows'
|
||||
} else if (/Macintosh|Mac OS/i.test(ua)) {
|
||||
platform = 'mac'
|
||||
} else if (/Linux/i.test(ua)) {
|
||||
platform = 'linux'
|
||||
} else {
|
||||
platform = 'unknown'
|
||||
}
|
||||
|
||||
// 尝试解析设备型号(粗糙方式)
|
||||
let model = 'unknown'
|
||||
const deviceMatch = ua.match(/\(([^)]+)\)/)
|
||||
if (deviceMatch && deviceMatch[1]) {
|
||||
// 从 UA 括号中取设备信息
|
||||
const parts = deviceMatch[1].split(';')
|
||||
// 最后一个不含版本号的 token 通常是设备型号
|
||||
for (let i = parts.length - 1; i >= 0; i--) {
|
||||
const part = parts[i].trim()
|
||||
if (
|
||||
part &&
|
||||
!/AppleWebKit|KHTML|Gecko|Chrome|Safari|Firefox|Edge|Version|Mobile/i.test(part) &&
|
||||
!/^[0-9._]+$/.test(part) &&
|
||||
!/U;|CPU|iPhone|iPad|iPod|Mac OS|Windows|Android|Linux/i.test(part)
|
||||
) {
|
||||
model = part
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 解析版本
|
||||
let version = 'unknown'
|
||||
if (platform === 'android') {
|
||||
const match = ua.match(/Android\s+([0-9.]+)/i)
|
||||
if (match && match[1]) {
|
||||
version = match[1]
|
||||
}
|
||||
} else if (platform === 'ios') {
|
||||
const match = ua.match(/OS\s+([0-9_]+)/i)
|
||||
if (match && match[1]) {
|
||||
version = match[1].replace(/_/g, '.')
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
platform,
|
||||
model,
|
||||
version,
|
||||
language: navigator.language,
|
||||
pixelRatio: window.devicePixelRatio || 1,
|
||||
screenWidth: screen.width,
|
||||
screenHeight: screen.height,
|
||||
windowWidth: window.innerWidth,
|
||||
windowHeight: window.innerHeight,
|
||||
}
|
||||
},
|
||||
|
||||
// ────────────────────────────────────────────
|
||||
// 设置标题
|
||||
// ────────────────────────────────────────────
|
||||
async setTitle(title: string): Promise<boolean> {
|
||||
document.title = title
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
export default browserProvider
|
||||
184
src/bridge/types.ts
Normal file
184
src/bridge/types.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* 桥接层类型定义
|
||||
*
|
||||
* 定义统一的能力接口 IBridge,屏蔽不同运行环境(浏览器、微信小程序、uni-app WebView)的差异,
|
||||
* 让上层业务代码只需依赖此接口即可调用原生能力。
|
||||
*
|
||||
* @module bridge/types
|
||||
*/
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 地理位置
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
/** 获取地理位置时的配置选项 */
|
||||
export interface GetLocationOptions {
|
||||
/** 是否启用高精度模式(GPS),默认 false */
|
||||
enableHighAccuracy?: boolean
|
||||
/** 超时时间(毫秒),默认 10000 */
|
||||
timeout?: number
|
||||
/** 是否需要返回逆地理编码后的地址描述 */
|
||||
needAddress?: boolean
|
||||
}
|
||||
|
||||
/** 地理位置坐标 */
|
||||
export interface LocationResult {
|
||||
/** 纬度,范围 -90 ~ 90 */
|
||||
latitude: number
|
||||
/** 经度,范围 -180 ~ 180 */
|
||||
longitude: number
|
||||
/** 速度(m/s) */
|
||||
speed?: number
|
||||
/** 精度(米) */
|
||||
accuracy?: number
|
||||
/** 逆地理编码后的地址描述(需要 needAddress 选项) */
|
||||
address?: string
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 扫码
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
/** 扫码类型 */
|
||||
export type ScanType = 'qr' | 'barcode' | 'all'
|
||||
|
||||
/** 扫码配置选项 */
|
||||
export interface ScanCodeOptions {
|
||||
/** 扫码类型,默认 'all' */
|
||||
type?: ScanType
|
||||
}
|
||||
|
||||
/** 扫码结果 */
|
||||
export interface ScanCodeResult {
|
||||
/** 扫码得到的字符串内容 */
|
||||
result: string
|
||||
/** 码的类型,如 'QR_CODE'、'EAN_13' 等 */
|
||||
format?: string
|
||||
/** 字符集 */
|
||||
charset?: string
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 地图
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
/** 打开地图查看位置所需的参数 */
|
||||
export interface OpenMapParams {
|
||||
/** 目标纬度 */
|
||||
latitude: number
|
||||
/** 目标经度 */
|
||||
longitude: number
|
||||
/** 位置名称 */
|
||||
name?: string
|
||||
/** 地址详情 */
|
||||
address?: string
|
||||
/** 缩放级别,默认 16 */
|
||||
scale?: number
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 图片选择
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
/** 图片来源 */
|
||||
export type ImageSourceType = 'album' | 'camera'
|
||||
|
||||
/** 选择图片的配置选项 */
|
||||
export interface ChooseImageOptions {
|
||||
/** 最多可选图片数量,默认 1 */
|
||||
count?: number
|
||||
/** 图片来源,默认 ['album', 'camera'] */
|
||||
sourceType?: ImageSourceType[]
|
||||
/** 是否允许压缩,默认 true */
|
||||
compress?: boolean
|
||||
}
|
||||
|
||||
/** 选择图片的返回结果 */
|
||||
export interface ChooseImageResult {
|
||||
/** 选中图片的临时文件路径列表 */
|
||||
tempFilePaths: string[]
|
||||
/** 选中图片的临时文件对象列表 */
|
||||
tempFiles?: Array<{
|
||||
path: string
|
||||
size: number
|
||||
}>
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 设备信息
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
/** 设备信息 */
|
||||
export interface DeviceInfo {
|
||||
/** 操作系统平台,如 'ios'、'android'、'windows'、'mac' */
|
||||
platform: string
|
||||
/** 设备型号 */
|
||||
model: string
|
||||
/** 操作系统版本号 */
|
||||
version: string
|
||||
/** 系统语言 */
|
||||
language?: string
|
||||
/** 设备像素比 */
|
||||
pixelRatio?: number
|
||||
/** 屏幕宽度(px) */
|
||||
screenWidth?: number
|
||||
/** 屏幕高度(px) */
|
||||
screenHeight?: number
|
||||
/** 窗口宽度(px) */
|
||||
windowWidth?: number
|
||||
/** 窗口高度(px) */
|
||||
windowHeight?: number
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Bridge 接口 —— 所有提供者需实现此接口
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 统一桥接接口
|
||||
*
|
||||
* 所有环境提供者(浏览器、微信小程序 WebView、uni-app WebView)
|
||||
* 都必须实现此接口,确保上层业务代码不感知底层差异。
|
||||
*/
|
||||
export interface IBridge {
|
||||
/**
|
||||
* 获取当前地理位置
|
||||
* @param options - 配置选项
|
||||
* @returns Promise 返回位置信息
|
||||
*/
|
||||
getLocation(options?: GetLocationOptions): Promise<LocationResult>
|
||||
|
||||
/**
|
||||
* 调起扫码
|
||||
* @param options - 扫码配置
|
||||
* @returns Promise 返回扫码结果
|
||||
*/
|
||||
scanCode(options?: ScanCodeOptions): Promise<ScanCodeResult>
|
||||
|
||||
/**
|
||||
* 打开地图查看指定位置
|
||||
* @param params - 目标位置参数
|
||||
* @returns Promise 返回是否成功打开
|
||||
*/
|
||||
openMap(params: OpenMapParams): Promise<boolean>
|
||||
|
||||
/**
|
||||
* 从相册或相机选择图片
|
||||
* @param options - 选择配置
|
||||
* @returns Promise 返回选中图片信息
|
||||
*/
|
||||
chooseImage(options?: ChooseImageOptions): Promise<ChooseImageResult>
|
||||
|
||||
/**
|
||||
* 获取设备信息
|
||||
* @returns Promise 返回设备信息
|
||||
*/
|
||||
getDeviceInfo(): Promise<DeviceInfo>
|
||||
|
||||
/**
|
||||
* 设置页面标题
|
||||
* @param title - 标题文本
|
||||
* @returns Promise 返回是否设置成功
|
||||
*/
|
||||
setTitle(title: string): Promise<boolean>
|
||||
}
|
||||
Reference in New Issue
Block a user