Files
shanxia2.0/miniprogram/components/phone-dial-inline.vue
T
2026-07-11 17:15:17 +08:00

150 lines
4.0 KiB
Vue

<script>
export default {
options: { virtualHost: true }
}
</script>
<script setup>
import { computed } from 'vue'
// #ifdef H5
import VanIcon from 'vant/es/icon'
import 'vant/es/icon/style'
// #endif
// #ifdef MP-WEIXIN
import UniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'
// #endif
import { dialPhone, normalizeDialNumber } from '@/utils/phone-dial'
const props = defineProps({
phone: { type: [String, null], default: null },
dialPhone: { type: [String, null], default: undefined },
emptyText: { type: String, default: '暂无' },
/** 仅作用于号码/占位文字;拨号图标固定黑色,见 `dialIconColor` */
color: { type: String, default: '' },
iconSize: { type: [String, Number], default: 18 },
iconOnly: { type: Boolean, default: false },
hideIcon: { type: Boolean, default: false },
expand: { type: Boolean, default: false },
endAlign: { type: Boolean, default: false }
})
const displayLine = computed(() => String(props.phone ?? '').trim())
const dialRaw = computed(() =>
normalizeDialNumber(props.dialPhone !== undefined && props.dialPhone !== null ? props.dialPhone : props.phone)
)
const canDial = computed(() => !!dialRaw.value)
const displayText = computed(() => {
if (props.iconOnly) return ''
return displayLine.value || props.emptyText
})
/** 拨号图标颜色(与号码文字 `color` 解耦,统一黑色) */
const dialIconColor = '#000000'
/** 号码文字色:`icon-only` 无文字时不应用 */
const textStyle = computed(() => {
if (props.iconOnly)
return {}
const c = String(props.color ?? '').trim()
if (!c)
return {}
return { color: c }
})
/** App 等非 H5、非微信小程序端:Unicode 兜底(小程序用 uni-icons,见模板) */
const iconStyle = computed(() => {
const n = Number(props.iconSize)
const px = Number.isFinite(n) ? n : 18
return { color: dialIconColor, fontSize: `${px * 2}rpx`, lineHeight: 1 }
})
function onDial() {
dialPhone(props.dialPhone !== undefined && props.dialPhone !== null ? props.dialPhone : props.phone)
}
function onTextClick(e) {
if (!props.hideIcon || !canDial.value) return
e.stopPropagation()
onDial()
}
</script>
<template>
<view
class="phone-dial-inline"
:class="{
'phone-dial-inline--icon-only': iconOnly,
'phone-dial-inline--hide-icon': hideIcon,
'phone-dial-inline--expand': expand,
'phone-dial-inline--end': endAlign
}"
>
<text v-if="!iconOnly" class="phone-dial-inline__text" :style="textStyle" @click="onTextClick">{{ displayText }}</text>
<view v-if="canDial && !hideIcon" class="phone-dial-inline__btn" @click.stop="onDial">
<!-- #ifdef H5 -->
<VanIcon name="phone-o" :size="iconSize" :color="dialIconColor" />
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<UniIcons type="phone" :color="dialIconColor" :size="iconSize" />
<!-- #endif -->
<!-- #ifndef H5 -->
<!-- #ifndef MP-WEIXIN -->
<text class="phone-dial-inline__icon" :style="iconStyle">☎</text>
<!-- #endif -->
<!-- #endif -->
</view>
</view>
</template>
<style scoped>
.phone-dial-inline {
display: inline-flex;
align-items: center;
gap: 10rpx;
min-width: 0;
max-width: 100%;
box-sizing: border-box;
}
.phone-dial-inline--expand {
flex: 1;
min-width: 0;
}
.phone-dial-inline--icon-only.phone-dial-inline--expand {
flex: 0 0 auto;
}
.phone-dial-inline--end {
justify-content: flex-end;
}
.phone-dial-inline--end .phone-dial-inline__text {
text-align: right;
}
.phone-dial-inline__text {
flex: 1;
min-width: 0;
word-break: break-all;
line-height: 1.4;
}
.phone-dial-inline--icon-only .phone-dial-inline__text {
display: none;
}
.phone-dial-inline__btn {
flex-shrink: 0;
min-width: 44rpx;
min-height: 44rpx;
display: flex;
align-items: center;
justify-content: center;
}
.phone-dial-inline__icon {
font-weight: 600;
}
</style>