97 lines
3.0 KiB
TypeScript
97 lines
3.0 KiB
TypeScript
import { logger } from '../../utils/logger'
|
||
|
||
// 日志模块名
|
||
const LOG = 'v2-overlay'
|
||
|
||
/**
|
||
* v2 统一玻璃弹层。
|
||
*
|
||
* 三类形态:
|
||
* modal 居中玻璃卡(确认/提示),buttons 决定按钮,事件 confirm/cancel
|
||
* actionsheet 底部动作表(选择),items 决定条目,事件 select/cancel
|
||
* toast 深色玻璃胶囊,duration 后自动关闭并抛出 close
|
||
*
|
||
* 页面侧只维护 visible 与文案数据,回调分支与原生 wx.showModal 一一对应。
|
||
*/
|
||
Component({
|
||
properties: {
|
||
visible: { type: Boolean, value: false },
|
||
type: { type: String, value: 'modal' },
|
||
title: { type: String, value: '' },
|
||
content: { type: String, value: '' },
|
||
// modal 按钮:[{ text, value, type: 'main' | 'normal' }]
|
||
buttons: { type: Array, value: [] },
|
||
// actionsheet 条目:['拍照', '从相册选择'] 或 [{ text, value }]
|
||
items: { type: Array, value: [] },
|
||
cancelText: { type: String, value: '取消' },
|
||
// toast 自动关闭时长(ms)
|
||
duration: { type: Number, value: 1800 },
|
||
},
|
||
|
||
observers: {
|
||
visible(v: boolean) {
|
||
if (!v) {
|
||
this.clearTimer()
|
||
return
|
||
}
|
||
if (this.data.type === 'toast') this.startTimer()
|
||
},
|
||
},
|
||
|
||
lifetimes: {
|
||
detached() {
|
||
this.clearTimer()
|
||
},
|
||
},
|
||
|
||
methods: {
|
||
startTimer() {
|
||
this.clearTimer()
|
||
const t = setTimeout(() => {
|
||
logger.debug(LOG, 'toast 自动关闭')
|
||
this.triggerEvent('close')
|
||
}, this.data.duration)
|
||
;(this as any).timer = t
|
||
},
|
||
|
||
clearTimer() {
|
||
const t = (this as any).timer
|
||
if (t) {
|
||
clearTimeout(t)
|
||
;(this as any).timer = null
|
||
}
|
||
},
|
||
|
||
onBtn(e: WechatMiniprogram.TouchEvent) {
|
||
const index = Number((e.currentTarget.dataset as any).index) || 0
|
||
const btn = (this.data.buttons[index] || {}) as any
|
||
const value = btn.value || ''
|
||
// 按语义分流:主按钮抛 confirm,其余(取消 / 稍后再说 / 再想想…)抛 cancel。
|
||
// 否则「取消」也会落进页面的确认分支,取消后没有出口(曾出现停在空页)
|
||
if (btn.type === 'main') {
|
||
logger.debug(LOG, 'modal 主按钮点击, index=', index, 'value=', value)
|
||
this.triggerEvent('confirm', { index, value })
|
||
return
|
||
}
|
||
logger.debug(LOG, 'modal 取消按钮点击, index=', index, 'value=', value)
|
||
this.triggerEvent('cancel', { index, value })
|
||
},
|
||
|
||
onItem(e: WechatMiniprogram.TouchEvent) {
|
||
const index = Number((e.currentTarget.dataset as any).index) || 0
|
||
const raw = this.data.items[index] as any
|
||
const value = raw && typeof raw === 'object' ? raw.value || '' : raw
|
||
logger.debug(LOG, 'actionsheet 条目点击, index=', index, 'value=', value)
|
||
this.triggerEvent('select', { index, value })
|
||
},
|
||
|
||
onCancel() {
|
||
logger.debug(LOG, '弹层取消')
|
||
this.triggerEvent('cancel')
|
||
},
|
||
|
||
// 阻断蒙层下的页面滚动
|
||
noop() {},
|
||
},
|
||
})
|