Skip to content

UI — 界面控件

原生提供的全局 UI 组件:Toast、Loading、Dialog、ActionSheet、导航栏控制等。

交互示例

Toast 轻提示

showToast()
<script setup lang="ts">
import { ref } from 'vue'
import woo from 'mini-sdk'

type ToastIcon = 'success' | 'error' | 'loading' | 'none'
const duration = ref(2000)
const title = ref('操作成功')
const icon = ref<ToastIcon>('success')
const isLoading = ref(false)

async function showToast() {
  await woo.showToast({ title: title.value, icon: icon.value, duration: duration.value === 0 ? 0 : duration.value })
  if (icon.value === 'loading' || duration.value === 0) {
    isLoading.value = true
  } else {
    isLoading.value = false
  }
}

async function hideToast() {
  await woo.hideToast()
  isLoading.value = false
}

const iconOptions: { label: string; value: ToastIcon }[] = [
  { label: '✅ success', value: 'success' },
  { label: '❌ error', value: 'error' },
  { label: '⏳ loading', value: 'loading' },
  { label: '📝 none', value: 'none' },
]
</script>

<template>
  <div class="demo-toast">
    <div class="form-grid">
      <div class="field">
        <label>标题文字</label>
        <input v-model="title" placeholder="输入提示文字" />
      </div>
      <div class="field">
        <label>图标 icon</label>
        <select v-model="icon">
          <option v-for="opt in iconOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
        </select>
      </div>
      <div class="field">
        <label>显示时长 (ms,0=永久)</label>
        <input v-model.number="duration" type="number" min="0" step="500" />
      </div>
    </div>

    <div class="btn-row">
      <button class="btn btn-primary" @click="showToast">showToast()</button>
      <button class="btn btn-outline" @click="hideToast" :disabled="!isLoading">hideToast()</button>
    </div>

    <div class="note" v-if="isLoading">
      ↑ Toast 已锁定显示(duration=0 或 loading 图标),点击 hideToast 关闭
    </div>
  </div>
</template>

<style scoped>
.demo-toast { display: flex; flex-direction: column; gap: 14px; width: 100%; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.field { display: flex; flex-direction: column; gap: 5px; }
label { font-size: 11.5px; font-weight: 600; color: var(--vp-c-text-3); text-transform: uppercase; letter-spacing: 0.05em; }
input, select {
  padding: 7px 10px; border-radius: 6px; border: 1px solid var(--vp-c-divider);
  background: var(--vp-c-bg); font-size: 13px; color: var(--vp-c-text-1);
  font-family: inherit; outline: none; transition: border-color 0.15s;
}
input:focus, select:focus { border-color: #6366f1; }
.btn-row { display: flex; gap: 8px; }
.btn { padding: 8px 18px; border-radius: 7px; border: none; font-size: 13.5px; font-weight: 500; cursor: pointer; font-family: inherit; transition: all 0.15s; }
.btn-primary { background: #6366f1; color: white; }
.btn-primary:hover { background: #4f46e5; }
.btn-outline { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); color: var(--vp-c-text-1); }
.btn-outline:hover:not(:disabled) { background: var(--vp-c-bg-soft); }
.btn-outline:disabled { opacity: 0.5; cursor: not-allowed; }
.note { font-size: 12.5px; color: #f59e0b; background: rgba(245,158,11,0.08); border: 1px solid rgba(245,158,11,0.2); border-radius: 6px; padding: 8px 12px; }
</style>
Attributes
参数说明类型可选值默认值
title提示文字string''
icon图标类型'success' | 'error' | 'loading' | 'none'success / error / loading / none'none'
duration显示时长(ms),0 表示永久number2000
mask是否显示透明遮罩booleantrue / falsefalse

Dialog 弹窗

showDialog() / alert()
<script setup lang="ts">
import { ref } from 'vue'
import woo from 'mini-sdk'

const result = ref<{ confirm: boolean; cancel: boolean } | null>(null)
const showCancel = ref(true)
const confirmText = ref('确认')
const cancelText = ref('取消')
const content = ref('此操作不可撤销,是否继续?')

async function openDialog() {
  result.value = null
  const res = await woo.showDialog({
    title: '确认操作',
    content: content.value,
    showCancel: showCancel.value,
    confirmText: confirmText.value,
    cancelText: cancelText.value,
  })
  result.value = res
}

async function openAlert() {
  await woo.alert({ title: '温馨提示', content: '操作已完成!', buttonText: '知道了' })
}
</script>

<template>
  <div class="demo-dialog">
    <div class="form-grid">
      <div class="field flex-2">
        <label>内容文字</label>
        <input v-model="content" />
      </div>
      <div class="field">
        <label>确认按钮文字</label>
        <input v-model="confirmText" />
      </div>
      <div class="field">
        <label>取消按钮文字</label>
        <input v-model="cancelText" />
      </div>
      <div class="field checkbox-field">
        <label class="checkbox-label">
          <input type="checkbox" v-model="showCancel" />
          显示取消按钮
        </label>
      </div>
    </div>

    <div class="btn-row">
      <button class="btn btn-primary" @click="openDialog">showDialog()</button>
      <button class="btn btn-outline" @click="openAlert">alert()</button>
    </div>

    <div v-if="result" class="result-chip" :class="result.confirm ? 'confirmed' : 'cancelled'">
      用户点击了:{{ result.confirm ? `"${confirmText}"(confirm)` : `"${cancelText}"(cancel)` }}
    </div>
  </div>
</template>

<style scoped>
.demo-dialog { display: flex; flex-direction: column; gap: 14px; width: 100%; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; align-items: end; }
.flex-2 { grid-column: span 2; }
.field { display: flex; flex-direction: column; gap: 5px; }
label { font-size: 11.5px; font-weight: 600; color: var(--vp-c-text-3); text-transform: uppercase; letter-spacing: 0.05em; }
input[type="text"], input:not([type]) {
  padding: 7px 10px; border-radius: 6px; border: 1px solid var(--vp-c-divider);
  background: var(--vp-c-bg); font-size: 13px; color: var(--vp-c-text-1);
  font-family: inherit; outline: none; transition: border-color 0.15s;
}
input:focus { border-color: #6366f1; }
.checkbox-field { justify-content: flex-end; padding-bottom: 2px; }
.checkbox-label { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 500; color: var(--vp-c-text-1); text-transform: none; letter-spacing: 0; cursor: pointer; }
.checkbox-label input { width: 15px; height: 15px; cursor: pointer; }
.btn-row { display: flex; gap: 8px; }
.btn { padding: 8px 18px; border-radius: 7px; border: none; font-size: 13.5px; font-weight: 500; cursor: pointer; font-family: inherit; transition: all 0.15s; }
.btn-primary { background: #6366f1; color: white; }
.btn-primary:hover { background: #4f46e5; }
.btn-outline { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); color: var(--vp-c-text-1); }
.btn-outline:hover { background: var(--vp-c-bg-soft); }
.result-chip { display: inline-flex; align-items: center; padding: 7px 14px; border-radius: 7px; font-size: 13px; font-weight: 500; }
.confirmed { background: rgba(16,185,129,0.1); color: #059669; border: 1px solid rgba(16,185,129,0.2); }
.cancelled { background: rgba(239,68,68,0.08); color: #dc2626; border: 1px solid rgba(239,68,68,0.15); }
</style>
Attributes
参数说明类型可选值默认值
title弹窗标题string''
content弹窗内容string''
showCancel是否显示取消按鈕booleantrue / falsetrue
cancelText取消按鈕文字string'取消'
confirmText确认按鈕文字string'确定'

API 参考

woo.showToast(options)

显示轻提示,自动消失。支持字符串简写
ts
// ✨ 字符串简写(icon 默认 'none',duration 默认 2000)
await woo.showToast('已复制到剪贴板')

// 成功提示
await woo.showToast({ title: '保存成功', icon: 'success', duration: 2000 })

// 加载中(不自动消失,需手动 hideToast)
await woo.showToast({ title: '正在上传...', icon: 'loading' })
await woo.hideToast()

// duration=0 永久显示
await woo.showToast({ title: '处理中...', duration: 0 })

Options

参数类型默认值说明
titlestring''提示文字
icon'success' | 'error' | 'loading' | 'none''none'图标类型
durationnumber2000显示时长(ms),0 表示永久
maskbooleanfalse是否显示遮罩

woo.hideToast()

主动关闭 Toast(用于 icon: 'loading'duration: 0 的场景)。


woo.showLoading(options) / woo.hideLoading()

显示/关闭全屏加载遮罩。支持字符串简写
ts
// ✨ 字符串简写
await woo.showLoading('加载中')

try {
  await woo.showLoading({ title: '提交中...', mask: true })
  await submitForm()
} finally {
  await woo.hideLoading()
}

Options

参数类型默认值说明
titlestring''提示文字
maskbooleantrue是否显示遮罩,防止用户误操作

woo.showDialog(options)

模态确认框,等待用户点击后 resolve。
ts
const { confirm } = await woo.showDialog({
  title: '删除确认',
  content: '此操作不可撤销,是否继续?',
  cancelText: '取消',
  confirmText: '删除',
})
if (confirm) {
  await deleteItem()
}

Options

参数类型默认值说明
titlestring''弹窗标题
contentstring''弹窗内容
showCancelbooleantrue是否显示取消按钮
cancelTextstring'取消'取消按钮文字
confirmTextstring'确定'确认按钮文字

Result

字段类型说明
confirmboolean用户点击了确认
cancelboolean用户点击了取消

woo.alert(options)

单按钮提示框。支持字符串简写
ts
// ✨ 字符串简写
await woo.alert('操作成功')

await woo.alert({
  title: '网络错误',
  content: '请检查网络连接后重试',
  buttonText: '知道了',
})

woo.showActionSheet(options)

底部操作菜单。
ts
try {
  const { index } = await woo.showActionSheet({
    itemList: ['拍照', '从相册选择', '取消'],
  })
  console.log('用户选择了第', index, '项') // 0-based
} catch (err) {
  // 用户取消
}

Options / Result

参数类型说明
OptionsitemListstring[]选项文字列表
Resultindexnumber用户点击的下标(0-based)

导航栏控制

ts
// 动态修改标题
await woo.setNavigationBarTitle({ title: '文章详情' })

// 修改颜色(十六进制)
await woo.setNavigationBarColor({
  frontColor: '#ffffff',
  backgroundColor: '#1a1a2e',
})

// 加载动画
await woo.showNavigationBarLoading()
try {
  await loadData()
} finally {
  await woo.hideNavigationBarLoading()
}

TabBar 控制

ts
await woo.hideTabBar()   // 进入沉浸式页面时隐藏
await woo.showTabBar()   // 退出时恢复

// 设置红点
await woo.setTabBarBadge({ index: 2, text: '99+' })
await woo.removeTabBarBadge({ index: 2 })

图片预览

ts
// 多图预览,从指定图开始
await woo.previewImage({
  urls: ['img1.jpg', 'img2.jpg', 'img3.jpg'],
  current: 'img2.jpg',
})

基于 OpenSumi IDE 构建