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.

264 lines
6.8 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view @click="onclick" class=" tm-checkbox " :class="[dense?'':'pa-20',inline?'d-inline-block ':'fulled']">
<view class="flex-start fulled">
<slot name="default" :checkData="{label:label,checked:changValue}" :on="onclick">
<view :style="{width: sizes.wk,height: sizes.wk}" class="tm-checkbox-boey relative d-inline-block"
:class="[black?'bk':'','flex-shrink mr-10 ',
changValue?'ani':'',
changValue?color_tmeme+' border-'+(borderColor||color_tmeme)+'-a-1':'border-'+(borderColor||color_tmeme)+'-a-1',
disabled?'grey-lighten-2 border-grey-lighten-1-a-1':'',
round==='rounded'?'rounded':'round-'+round]"
>
<view :class="[changValue?'ani_toMaxToMin_on':'']" class="absolute flex-center" style="width: 100%;height: 100%;">
<tm-icons dense v-show="model === 'normal'" :size="sizes.gou" :color="disabled?'opacity-5 white':'white'" :name="changValue?icon:' '"></tm-icons>
<view v-show="model === 'round'&&changValue" class=" rounded d-inline-block"
:class="[disabled?'opacity-5 white':'white']"
:style="{width: sizes.yuan,height: sizes.yuan}"></view>
</view>
</view>
</slot>
<view v-if="label" :class="[black?'bk':'','px-10 ','flex-start fulled']" :style="{minHeight: sizes.wk}" class=" tm-checkbox-boey-label ">
<view class="flex-center fulled-height ">
<slot name="label" :label="{label:label,checked:changValue}">
<text class=" text-size-n">{{label}}</text>
</slot>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* 单选框
* @description 可以单独或者在tm-groupradio中使用。
* @property {Boolean} value = [true|false] 如果想双向绑定需要value.snyc等同v-model。推荐v-model.
* @property {Function} input 等同value.snyc和v-model和change
* @property {Function} change 变化是会返回 {index,checked,value:name携带的数据}
* @property {Boolean} disabled = [true|false] 默认false,禁用
* @property {String} color = [primary|blue] 默认primary,主题色名称。
* @property {String} border-color = [] 默认 '',边线主题色默认同color可不填。
* @property {String} model = [normal|round] 默认normal, 内部normal打勾round:内部为圆点
* @property {String} icon = [icon-check] 默认icon-check,自定义选中时的图标。
* @property {String|Number} round = [2|rounded] 默认2, 圆角rounded时即圆形。
* @property {String|Number} size = [] 默认32, 大小单位upx
* @property {String|Boolean} dense = [true|false] 默认false, 是否去除外间隙。
* @property {String} label = [] 默认"", 文右边显示的选项文字
* @property {String|Boolean} black = [true|false] 默认false, 暗黑模式
* @property {String|Boolean} inline = [true|false] 默认false, 是否内联模式
* @property {String | Array | Object | Number} name = [] 默认 "", 选中时携带的自定义数据会通过change带回。
* @example <tm-radio v-model="checked" label="按个计算"></tm-radio>
*/
import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
export default {
components:{tmIcons},
name:'tm-radio',
model:{
prop: 'value',
event: 'input'
},
props:{
//是否内联模式
inline:{
type:Boolean,
default:true
},
// 禁用。
disabled:Boolean,
// 使用时::checked.sync 需要带sync
value:Boolean,
color:{
type:String,
default:'primary'
},
borderColor: {
type: String,
default: ''
},
// 内部normal打勾round:内部为圆点
model:{
type:String,
default:'round'
},
// 自定义选中时的图标。
icon:{
type:String,
default:'icon-check'
},
// 外部形状:== rounded时即圆形。
round:{
type:String|Number,
default:'rounded'
},
// 单位upx
size:{
type:String|Number,
default:38
},
// 是否去除外间隙。
dense:{
type:Boolean|String,
default:false
},
// 名称。
label:{
type:String,
default:''
},
black:{
type:Boolean|String,
default:false
},
name:{
type:String|Array|Object|Number,
default:''
},
// 跟随主题色的改变而改变。
fllowTheme:{
type:Boolean|String,
default:true
}
},
data() {
return {
};
},
mounted() {
},
watch:{
value:function(newval,oldval){
if(newval !== oldval){
this.change();
}
}
},
computed:{
color_tmeme: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;
},
changValue:{
get:function(){
return this.value;
},
set:function(newValue){
this.$emit('input',newValue )
// 如果不想用v-model. 直接使用value,需要:value.sync
this.$emit('update:value',newValue )
}
},
sizes:function(){
return {
wk:uni.upx2px(this.size)+'px',
gou:uni.upx2px(this.size/3*2)+'px',
yuan:uni.upx2px(this.size/2)+'px',
}
}
},
methods: {
onclick(e){
let t= this;
if(this.disabled) return;
this.changValue = true;
},
change() {
let box = [];
let selfIndex;
let __uid = this._uid;
let t = this;
function findchild(p,index){
let preat = p;
if(preat.$options?.name==='tm-radio'){
if(preat._uid!==__uid){
if(preat.changValue===true && preat.changValue === t.changValue){
preat.changValue = false;
}
}else if(preat._uid===__uid){
box.push({index:index,name:preat.name,checked:preat.changValue})
selfIndex = index;
}
}else{
if(preat.$children.length>0){
preat.$children.forEach(item=>{
findchild(item,index++);
})
}
}
};
let preat = this.$tm.getParentAls('tm-groupradio', this.$parent);
// 如果不在tm-groupradio里面将不作反选。并且始终为true.
if(preat){
findchild(preat,0);
t.$emit('change',{index:selfIndex,checked:t.changValue,name:t.name});
preat.change(box)
}else{
this.$emit('change',{index:0,checked:this.changValue,name:this.name});
}
}
},
}
</script>
<style lang="scss" scoped>
.tm-checkbox{
vertical-align: middle;
.tm-checkbox-boey,.tm-checkbox-boey-label{
vertical-align: middle;
}
.ani {
animation: ani 0.2s linear;
}
.ani_toMaxToMin_on {
animation: ani_toMaxToMin_on 0.35s linear;
}
@keyframes ani_toMaxToMin_on {
0% {
transform: scale(0.7);
opacity:0.7;
}
50% {
transform: scale(1.5)
}
100% {
transform: scale(1);
opacity:1;
}
}
@keyframes ani {
0% {
transform: scale(0.9)
}
50% {
transform: scale(1.1)
}
100% {
transform: scale(0.9)
}
}
}
</style>