You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

706 lines
19 KiB
Vue

1 year ago
<template>
<view class="tm-button " :class="[block ? 'd-block' : 'd-inline-block ']" hover-class="opacity-6">
<view
class="flex-center tm-button-btn fulled-height"
:class="[block ? '' : customDense_puted ? '' : 'ma-10', block ? 'd-block' : 'd-inline-block', black_tmeme ? 'bk' : '', customStyleTm]"
>
<!-- @getuserinfo="getuserinfo" -->
<button
@contact="contact"
@error="error"
@getphonenumber="getphonenumber"
@launchapp="launchapp"
@opensetting="opensetting"
@click="onclick"
@longpress="$emit('longpress', $event)"
@touchcancel="$emit('touchcancel', $event)"
@touchend="$emit('touchend', $event)"
@touchstart="$emit('touchstart', $event)"
:disabled="disabled"
:loading="loading"
:open-type="openType"
:hover-start-time="hoverStartTime"
:hover-stay-time="hoverStaySime"
:hover-stop-propagation="hoverStopPropagation"
:send-message-img="sendMessageImg"
:send-message-path="sendMessagePath"
:send-message-title="sendMessageTitle"
:show-message-card="showMessageCard"
:class="[
showValue ? 'showValue' : '',
titl ? 'text-' + color_tmeme : '',
vertical ? 'flex-col flex-center' : 'flex-center',
black_tmeme ? 'bk' : '',
disabled ? color_tmeme + ' grey-lighten-2' : color_tmeme,
block ? '' : sizes,
text || titl ? '' : bgcolor ? 'shadow-' + shadow : 'shadow-' + shadowthemeName + '-' + shadow,
flat ? 'flat' : '',
text ? 'text ' : '',
plan ? 'plan outlined' : '',
titl ? 'titl' : '',
fab?'rounded':'round-' + round,
customClassTm_puted
]"
:style="{
background: bgcolor ? bgcolor + ' !important' : 'default',
width: widths != 0 && widths != 'inherit' ? widths : 'inherit',
height: heights,
lineHeight: 'inherit'
}"
>
<slot name="icon" :data="{ icon: icon, size: icon_size.upx, fab: fab }">
<block v-if="vtype == true">
<text
v-if="!fab && icon"
:class="[`${prefx_computed} ${icon}`, fontColor ? `text-${colors.color}` : '', black_tmeme ? 'opacity-6' : '', 'px-12','flex-shrink']"
:style="{
fontSize: `${icon_size.px}px`,
lineHeight:'normal'
}"
></text>
<text
v-if="fab && icon && !loading && !titl"
:class="[`${prefx_computed} ${icon}`, fontColor ? `text-${colors.color}` : '', black_tmeme ? 'opacity-6' : '','flex-shrink']"
:style="{
fontSize: `${icon_size.px}px`,
lineHeight:'normal'
}"
></text>
<text
v-if="fab && icon && !loading && titl"
:class="[`${prefx_computed} ${icon}`, fontColor ? `text-${color_tmeme}` : '', black_tmeme ? 'opacity-6' : '','flex-shrink']"
:style="{
fontSize: `${icon_size.px}px`,
lineHeight:'normal'
}"
></text>
</block>
<block v-if="vtype == false"><tm-icons :size="icon_size.upx" :name="icon"></tm-icons></block>
</slot>
<view v-if="!fab || showValue" class="d-inline-block tm-button-label flex-shrink" :style="{ fontSize: font_size }" :class="[fontColor ? `text-${colors.color}` : '',vertical ? 'full ' : '',]">
<slot name="default" :data="label">{{ label }}</slot>
</view>
</button>
</view>
</view>
</template>
<script>
/**
* 按钮
* @description 注意按钮功能同原生按钮功能所有属性都有
* @property {Function} contact
* @property {Function} error
* @property {Function} getphonenumber
* @property {Function} getuserinfo
* @property {Function} opensetting
* @property {Function} click
* @property {Boolean} disabled = [true|false] 是否禁用
* @property {Boolean} loading = [true|false] 是否加载中
* @property {String} open-type = [contact|getPhoneNumber|getUserInfo|launchapp|share|openSetting] 同原生btn相同,//当等于getUserProfile时自动获取微信授权。
* @property {Boolean} block = [true|false] 是否独占一行
* @property {Boolean} show-value = [true|false] fab模式是隐藏文字的如果这个设置为true,不管在什么情况下都会显示文字
* @property {String} url = [] 默认"",如果提供将会跳转连接
* @property {String} size = [xs|s|m|n|l|g] 默认"n",按钮尺寸大小
* @property {Number|String} font-size = [] 默认 0,自定义文字大小默认使用主题size的大小
* @property {Number|String} icon-size = [] upx单位默认 0,自定义图标大小默认使用主题size的大小
* @property {String} icon = [] 单位默认 "",自定义按钮图标
* @property {String} item-class = [] 默认 "",按钮自定样式类
* @property {String|Number} shadow = [] 默认 5,按钮投影
* @property {String} font-color = [] 默认主题颜色,自定文字颜色
* @property {String} bgcolor = [] 默认主题颜色,自定义-背景颜色
* @property {String} theme = [] 默认 primary,主题颜色
* @property {Boolean|String} black = [true|false] 默认 false, 暗黑模式
* @property {Boolean|String} flat = [true|false] 默认 false, 去除所有投影圆角效果扁平模式
* @property {Boolean|String} text = [true|false] 默认 false, 文本模式背景减淡文字使用主题色
* @property {Boolean|String} plan = [true|false] 默认 false, 镂空
* @property {Boolean|String} fab = [true|false] 默认 false, 圆模式
* @property {Boolean|String} dense = [true|false] 默认 false, 是否去除外间隙
* @property {Boolean|String} titl = [true|false] 默认 false, 无背景无边框只保留按钮区域和文字颜色或者图标颜色
* @property {String} label = [] 默认 "", 按钮文字也可以使用插槽模式直接写在组件内部
* @property {String|Number} width = [] 默认 "", 按钮宽, 单位px ,可以是百分比 如果不设置block为true时此项设置无效
* @property {String|Number} height = [] 默认 "", 按钮高, 单位px ,可以是百分比如果不设置block为true时此项设置无效
* @property {String|Number} round = [] 默认 2, 圆角
* @property {String|Number} navtie-type = [form] 默认 :'', 可选值form提供此属性为form时事件会被表单接替会触发表单提交事件
* @property {String} userProfileError = ['auto'] 默认:'auto' 仅open-type='getUserProfile'时有效当微信授权失败提示的信息默认为auto,如果非auto将显示自定义错误提示如果为''将不显示错误提示
* @example <tm-button>确定</tm-button>
*/
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
export default {
components: { tmIcons },
name: 'tm-button',
props: {
hoverStartTime:20,
hoverStaySime:70,
appParameter:String,
hoverStopPropagation:{
type:Boolean,
default:false
},
sessionFrom:String,
sendMessageTitle:String,
sendMessagePath:String,
sendMessageImg:String,
showMessageCard:String,
navtieType: {
type: String,
default: '' //form
},
// 内联还是独占一行的块状100%,默认内联样式。
block: {
type: String | Boolean,
default: false
},
// fab模式是隐藏文字的。如果这个设置为true,不管在什么情况下都会显示文字。
showValue: {
type: String | Boolean,
default: false
},
disabled: {
type: String | Boolean,
default: false
},
loading: {
type: String | Boolean,
default: false
},
url: {
type: String,
default: ''
},
// xs,s,n,l,g
size: {
type: String,
default: 'n'
},
// 文字大小。
fontSize: {
type: Number | String,
default: 0
},
// 图标大小。
iconSize: {
type: Number | String,
default: 0
},
// icon-cog-fill
icon: {
type: String,
default: ''
},
// 按钮自定样式类。
itemClass: {
type: String,
default: ''
},
// 同原生btn相同。contact|getPhoneNumber|getUserInfo|launchapp|share|openSetting
//当等于getUserProfile时自动获取微信授权。
openType: {
type: String,
default: ''
},
shadow: {
type: Number | String,
default: 4
},
vertical: {
type: Boolean | String,
default: false
},
// 自定义-文字颜色。
fontColor: {
type: String,
default: ''
},
// 自定义-背景颜色
bgcolor: {
type: String | Array,
default: ''
},
// 主题颜色
theme: {
type: String,
default: 'primary'
},
//优先级最高: 优先级1
black: {
type: Boolean | String,
default: null
},
// 优先级高优先级2
flat: {
type: Boolean | String,
default: null
},
// 优先级高:文本模式。背景减淡。文字使用主题色。
text: {
type: Boolean | String,
default: false
},
// 优先级高:镂空。
plan: {
type: Boolean | String,
default: false
},
// 圆模式。
fab: {
type: Boolean | String,
default: false
},
// 无背景,无边框,只保留按钮区域和文字颜色或者图标颜色。
titl: {
type: Boolean | String,
default: false
},
label: {
type: String,
default: ''
},
// 如果不设置block为true时此项设置无效。
width: {
type: String | Number,
default: NaN
},
// 如果不设置block为true时此项设置无效。
height: {
type: String | Number,
default: NaN
},
// 圆角
round: {
type: String | Number,
default: 3
},
dense: {
type: Boolean | String,
default: false
},
// 跟随主题色的改变而改变。
fllowTheme: {
type: Boolean | String,
default: true
},
//当微信授权失败提示的信息默认为auto,如果非auto将显示自定义错误提示。如果为'',将不显示错误提示。
userProfileError:{
type:String,
default:'auto'
}
},
created() {
this.customClassTm_puted = this.itemClass;
this.customDense_puted = this.dense;
this.color_tmeme = this.theme;
},
watch: {
theme: function() {
this.color_tmeme = this.theme;
}
},
computed: {
prefx_computed() {
let prefix = this.icon.split('-')[0];
if (prefix == 'icon') return 'iconfont';
if (prefix == 'mdi') return 'mdi';
return prefix;
},
customDense_puted: {
get: function() {
return this.customDense;
},
set: function(val) {
this.customDense = val;
}
},
customClassTm_puted: {
get: function() {
return this.customClassTm;
},
set: function(val) {
this.customClassTm = val;
}
},
vtype: function() {
if (this.icon[0] == '.' || this.icon[0] == '/' || this.icon.substring(0, 4) == 'http' || this.icon.substring(0, 5) == 'https' || this.icon.substring(0, 3) == 'ftp') {
return false;
}
return true;
},
black_tmeme: function() {
if (this.black !== null) return this.black;
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme: {
get: function() {
if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this.fllowTheme) {
return this.$tm.vx.state().tmVuetify.color;
}
return this.color_tmeme_computed;
},
set: function(val) {
this.color_tmeme_computed = val;
}
},
// 投影的颜色名字。
shadowthemeName: function() {
if (!this.theme) return 'none';
return this.color_tmeme;
},
widths: {
get: function() {
let w;
if (typeof this.width === 'undefined') {
return 'auto';
}
let item = this.$TestUnit(this.width);
if (item) {
if (item.type == 'string') {
w = item.value;
}
if (item.type == 'number') {
w = item.value + 'px';
}
}
return w;
}
},
heights: {
get: function() {
let item = this.$TestUnit(this.height);
if (item) {
if (item.type == 'string') {
return item.value;
}
if (item.type == 'number') {
return item.value + 'px';
}
}
return 'auto';
}
},
sizes: function() {
if (!isNaN(this.width) || !isNaN(this.height)) return;
if (this.size == 'xs') {
return this.fab ? 'fabxs text-size-xs rounded' : 'wxs round-1 text-size-xs';
} else if (this.size == 's') {
return this.fab ? 'fabs text-size-xs rounded' : 'ws round-1 text-size-s';
} else if (this.size == 'm') {
return this.fab ? 'fabm text-size-xs rounded' : 'wm round-1 text-size-n';
} else if (this.size == 'n') {
return this.fab ? 'fabn text-size-xs rounded' : 'wn round-1 text-size-n';
} else if (this.size == 'l') {
return this.fab ? 'fabl text-size-xs rounded' : 'wl round-2 text-size-g';
} else if (this.size == 'g') {
return this.fab ? 'fabg text-size-xs rounded' : 'wg round-3 text-size-g';
}
},
font_size: function() {
if (this.fontSize > 0) {
return this.fontSize + 'rpx';
}
if (this.size == 'xs') {
return uni.upx2px(20) + 'px';
} else if (this.size == 's') {
return uni.upx2px(22) + 'px';
} else if (this.size == 'm') {
return uni.upx2px(24) + 'px';
} else if (this.size == 'n') {
return uni.upx2px(28) + 'px';
} else if (this.size == 'l') {
return uni.upx2px(32) + 'px';
} else if (this.size == 'g') {
return uni.upx2px(36) + 'px';
}
},
icon_size: function() {
if (this.iconSize) {
return { px: uni.upx2px(this.iconSize), upx: this.iconSize };
}
if (this.size == 'xs') {
return { px: uni.upx2px(20), upx: 20 };
} else if (this.size == 's') {
return { px: uni.upx2px(22), upx: 22 };
} else if (this.size == 'm') {
return { px: uni.upx2px(24), upx: 24 };
} else if (this.size == 'n') {
return { px: uni.upx2px(28), upx: 28 };
} else if (this.size == 'l') {
return { px: uni.upx2px(32), upx: 32 };
} else if (this.size == 'g') {
return { px: uni.upx2px(36), upx: 36 };
}
},
defaultfontsize: function() {
if (this.iconSize) {
return this.iconSize;
}
if (this.size == 'xs') {
return uni.upx2px(20);
} else if (this.size == 's') {
return uni.upx2px(22);
} else if (this.size == 'm') {
return uni.upx2px(24);
} else if (this.size == 'n') {
return uni.upx2px(28);
} else if (this.size == 'l') {
return uni.upx2px(32);
} else if (this.size == 'g') {
return uni.upx2px(36);
}
},
colors: function() {
let color = this.$TestColor(this.fontColor);
return color;
}
},
data() {
return {
customClassTm: '',
customDense: false,
customStyleTm: '',
color_tmeme_computed: ''
};
},
methods: {
setConfigStyle(val) {
this.customStyleTm = val;
},
onclick() {
let t = this;
this.$emit('click', ...arguments);
if(this.openType=='getUserInfo' || this.openType == 'getUserProfile'){
// #ifdef MP-WEIXIN
uni.getUserProfile({
desc: '需要获取用户信息',
lang: 'zh',
complete: function (userProfile) {
if(userProfile.errMsg !='getUserProfile:ok'){
if(t.userProfileError==''||t.userProfileError=='true') return;
if(t.userProfileError!='auto'){
uni.showToast({
title:t.userProfileError,icon:'error',mask:true
})
return;
}
uni.showToast({
title:userProfile.errMsg,icon:'error',mask:true
})
return;
}
t.$emit('getUserInfo', userProfile);
t.$emit('getUserProfile', userProfile);
},
fail: (error) => {
if(t.userProfileError==''||t.userProfileError=='true') return;
if(t.userProfileError!='auto'){
uni.showToast({
title:t.userProfileError,icon:'error',mask:true
})
return;
}
uni.showToast({
title:error
})
}
});
// #endif
}
if (this.url !== '' && typeof this.url === 'string') {
let url = this.url;
if (url[0] !== '/') url = '/' + url;
uni.navigateTo({
url: url
});
}
},
contact() {
this.$emit('contact', ...arguments);
},
error() {
this.$emit('error', ...arguments);
},
getphonenumber() {
this.$emit('getphonenumber', ...arguments);
},
getuserinfo() {
this.$emit('getuserinfo', ...arguments);
},
launchapp() {
this.$emit('launchapp', ...arguments);
},
opensetting() {
this.$emit('opensetting', ...arguments);
}
}
};
</script>
<style lang="scss" scoped>
.tm-button {
vertical-align: middle;
.tm-button-btn button {
background: none;
border: none;
width: 100%;
height: auto;
line-height: 88upx;
height: 88upx;
vertical-align: middle;
// #ifdef H5
transition: all 0.3s;
// #endif
.tm-button-label {
vertical-align: middle;
}
&::after {
border: none;
}
&.fabxs {
width: 48upx;
height: 48upx !important;
line-height: 48upx;
text-align: center;
padding: 0 !important;
}
&.fabs {
width: 64upx;
height: 64upx !important;
line-height: 64upx;
text-align: center;
padding: 0 !important;
}
&.fabm {
width: 90upx;
height: 90upx !important;
line-height: 90upx;
text-align: center;
padding: 0 !important;
}
&.fabn {
width: 110upx;
height: 110upx !important;
line-height: 110upx;
text-align: center;
padding: 0 !important;
}
&.fabl {
width: 140upx;
height: 140upx !important;
line-height: 140upx;
text-align: center;
padding: 0 !important;
}
&.fabg {
width: 180upx;
height: 180upx !important;
line-height: 180upx;
text-align: center;
padding: 0 !important;
}
&.wxs {
min-width: 64upx;
height: 36upx !important;
// line-height: 24upx;
text-align: center;
// padding: 0 !important;
padding: 0 12upx;
}
&.ws {
min-width: 90upx;
height: 48upx !important;
// line-height: 24upx;
text-align: center;
padding: 0 16upx;
}
&.wm {
min-width: 140upx;
height: 64upx !important;
// line-height: 88upx;
text-align: center;
padding: 0 24upx;
}
&.wn {
min-width: 240upx;
height: 72upx !important;
// line-height: 88upx;
text-align: center;
// padding: 0 !important;
padding: 0 32upx;
}
&.wl {
min-width: 280upx;
height: 72upx !important;
// line-height: 88upx;
text-align: center;
padding: 0 32upx;
}
&.wg {
min-width: 400upx;
height: 76upx !important;
// line-height: 88upx;
text-align: center;
padding: 0 32upx;
}
&.plan {
box-shadow: none !important;
// background: transparent !important;
border-width: 1px !important;
border-style: solid;
}
&.titl {
box-shadow: none !important;
background: transparent !important;
border: none;
}
&:active,
&:focus {
opacity: 0.64;
}
&.showValue {
line-height: inherit !important;
padding: 0 !important;
}
&.noGutter {
min-width: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: unset !important;
}
}
&.d-block {
button {
// padding: 30upx 0;
font-size: 32upx;
&.plan {
box-shadow: none !important;
background: transparent !important;
border-width: 1px !important;
border-style: solid;
}
}
&.showValue {
line-height: inherit !important;
}
}
&.d-inline-block {
vertical-align: middle;
}
}
</style>