forked from ccsens_fe/tall-mui-3
6 changed files with 103 additions and 362 deletions
@ -0,0 +1,84 @@ |
|||
<template> |
|||
<view class="my-3" v-if="allMembers && allMembers.length"> |
|||
<view class="flex justify-between"> |
|||
<view class="flex flex-wrap text-center items-center"> |
|||
<u-tag |
|||
:type="member.checked ? 'primary' : 'info'" |
|||
v-for="(member, index) in topMembers" |
|||
:key="member.memberId" |
|||
class="mb-2 mr-3" |
|||
style="width: 60px" |
|||
:text="member.name" |
|||
:closeable="false" |
|||
@click="tagClick(index, member, 'topMembers')" |
|||
/> |
|||
<span class="ml-2" @click="show = !show">...</span> |
|||
</view> |
|||
</view> |
|||
<!-- 折叠起来的 --> |
|||
<view class="flex flex-wrap text-center items-center" v-if="show"> |
|||
<u-tag |
|||
:type="member.checked ? 'primary' : 'info'" |
|||
v-for="(member, index) in bottomMembers" |
|||
:key="member.memberId" |
|||
class="mb-2 mr-3" |
|||
style="width: 60px" |
|||
:text="member.name" |
|||
:closeable="false" |
|||
@click="tagClick(index, member, 'bottomMembers')" |
|||
/> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapState } from 'vuex'; |
|||
|
|||
export default { |
|||
props: { |
|||
checkerList: { |
|||
default: () => [], |
|||
type: Array, |
|||
}, |
|||
}, |
|||
|
|||
data() { |
|||
return { allMembers: [], show: false, topMembers: [], bottomMembers: [] }; |
|||
}, |
|||
|
|||
computed: mapState('role', ['members']), |
|||
|
|||
mounted() { |
|||
if (this.members && this.members.length) { |
|||
this.allMembers = this.members; |
|||
// TODO: 等后台返回默认检查人后修改 |
|||
this.allMembers.forEach(item => { |
|||
item.checked = false; |
|||
}); |
|||
this.topMembers = this.members.slice(0, 3); |
|||
this.bottomMembers = this.members.slice(3); |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
tagClick(index, item, membersType) { |
|||
// 点击选择或取消选择 |
|||
const arr = this.$u.deepClone(this[membersType]); |
|||
arr[index].checked = !arr[index].checked; |
|||
this[membersType] = [...arr]; |
|||
// 将选中的id传给checkerList |
|||
this.$emit('setCheckerList', arr[index].checked, item); |
|||
}, |
|||
|
|||
// 清空所有选中的检查人 |
|||
clearChecked() { |
|||
for (let i = 0; i < this.topMembers.length; i++) { |
|||
this.topMembers[i].checked = false; |
|||
} |
|||
for (let i = 0; i < this.bottomMembers.length; i++) { |
|||
this.bottomMembers[i].checked = false; |
|||
} |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
@ -1,342 +0,0 @@ |
|||
<template> |
|||
<view class="main"> |
|||
<view :style="disabled ? 'background-color:#f5f7fa' : ''" class="input"> |
|||
<input |
|||
:placeholder="placeholder" |
|||
:style="disabled ? 'color:#c0c4cc' : ''" |
|||
@click="showModal" |
|||
class="text-sm" |
|||
disabled |
|||
v-model="_value" |
|||
/> |
|||
<u-icon @click="empty" color="#C0C4CC" name="close-circle-fill" size="32" v-if="clearable && !disabled && showClearable"></u-icon> |
|||
</view> |
|||
<view :class="isShowModal ? 'show' : ''" @tap="hideModal" class="select-modal"> |
|||
<view :style="{ backgroundColor: bgColor }" @tap.stop class="select-dialog"> |
|||
<view class="select-bar bg-white"> |
|||
<view @tap="cancelClick" class="action text-gray">{{ cancelText }}</view> |
|||
<view @tap="confirmClick" class="action text-blue">{{ confirmText }}</view> |
|||
</view> |
|||
<view class="select-content"> |
|||
<view |
|||
:key="index" |
|||
:style="valueIndexOf(item) ? 'color:' + selectColor + ';background-color:' + selectBgColor + ';' : 'color:' + color + ';'" |
|||
@click="select(item)" |
|||
class="select-item" |
|||
v-for="(item, index) in list" |
|||
> |
|||
<view class="title">{{ getLabelKeyValue(item) }}</view> |
|||
<u-icon name="checkbox-mark" v-if="valueIndexOf(item)"></u-icon> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { isShowModal: false, showClearable: false }; |
|||
}, |
|||
props: { |
|||
value: { |
|||
type: [Number, String, Array, Object], |
|||
default: null, |
|||
}, |
|||
placeholder: { |
|||
// 占位符 |
|||
default: '', |
|||
type: String, |
|||
}, |
|||
multiple: { |
|||
// 是否多选 |
|||
default: false, |
|||
type: Boolean, |
|||
}, |
|||
list: { |
|||
default: () => [], |
|||
type: Array, |
|||
}, |
|||
valueKey: { |
|||
// 指定list中valueKey的值作为下拉框绑定内容 |
|||
default: 'value', |
|||
type: String, |
|||
}, |
|||
labelKey: { |
|||
// 指定list中labelKey的值作为下拉框显示内容 |
|||
default: 'label', |
|||
type: String, |
|||
}, |
|||
disabled: { |
|||
default: false, |
|||
type: Boolean, |
|||
}, |
|||
clearable: { |
|||
default: false, |
|||
type: Boolean, |
|||
}, |
|||
cancelText: { |
|||
default: '取消', |
|||
type: String, |
|||
}, |
|||
confirmText: { |
|||
default: '确定', |
|||
type: String, |
|||
}, |
|||
color: { |
|||
default: '#000000', |
|||
type: String, |
|||
}, |
|||
selectColor: { |
|||
default: '#0081ff', |
|||
type: String, |
|||
}, |
|||
bgColor: { |
|||
default: '#F1F1F1', |
|||
type: String, |
|||
}, |
|||
selectBgColor: { |
|||
default: '#FFFFFF', |
|||
type: String, |
|||
}, |
|||
}, |
|||
computed: { |
|||
_value: { |
|||
get() { |
|||
return this.get_value(this.value); |
|||
}, |
|||
set(val) { |
|||
this.$emit('change', val); |
|||
}, |
|||
}, |
|||
}, |
|||
created() {}, |
|||
methods: { |
|||
get_value(val) { |
|||
// 将数组值转换为以,隔开的字符串 |
|||
if (val || val === 0) { |
|||
if (Array.isArray(val)) { |
|||
if (val.length > 0) { |
|||
this.showClearable = true; |
|||
} else { |
|||
this.showClearable = false; |
|||
} |
|||
let chooseAttr = []; |
|||
val.forEach(item => { |
|||
let choose = this.list.find(temp => { |
|||
let val_val = this.getValueKeyValue(temp); |
|||
return item === val_val; |
|||
}); |
|||
chooseAttr.push(choose); |
|||
}); |
|||
let values = chooseAttr.map(temp => this.getLabelKeyValue(temp)).join(','); |
|||
return values; |
|||
} else { |
|||
let choose = this.list.find(temp => { |
|||
let val_val = this.getValueKeyValue(temp); |
|||
return val === val_val; |
|||
}); |
|||
return this.getLabelKeyValue(choose); |
|||
} |
|||
} else { |
|||
console.log('val2', val); |
|||
return ''; |
|||
} |
|||
}, |
|||
select(item) { |
|||
// 点击选项 |
|||
let val = this.getValueKeyValue(item); |
|||
if (this.multiple) { |
|||
let _value = this.value; |
|||
let index = _value.indexOf(val); |
|||
if (index != -1) { |
|||
_value.splice(index, 1); |
|||
this.$emit('change', _value); |
|||
} else { |
|||
_value.push(val); |
|||
this.$emit('change', _value); |
|||
} |
|||
} else { |
|||
this.$emit('change', val); |
|||
this.hideModal(); |
|||
} |
|||
}, |
|||
valueIndexOf(item) { |
|||
let val = this.getValueKeyValue(item); |
|||
if (Array.isArray(this.value)) { |
|||
return this.value.indexOf(val) != -1; |
|||
} else { |
|||
return this.value === val; |
|||
} |
|||
}, |
|||
getLabelKeyValue(item) { |
|||
// 获取label |
|||
return item[this.labelKey]; |
|||
}, |
|||
getValueKeyValue(item) { |
|||
// 获取value |
|||
return item[this.valueKey]; |
|||
}, |
|||
empty() { |
|||
// 清空 |
|||
if (this.multiple) { |
|||
this.$emit('change', []); |
|||
} else { |
|||
this.$emit('change', ''); |
|||
} |
|||
}, |
|||
cancelClick() { |
|||
// 点击取消 |
|||
this.$emit('cancel', this._value); |
|||
this.hideModal(); |
|||
}, |
|||
confirmClick() { |
|||
// 点击确定 |
|||
this.$emit('confirm', this._value); |
|||
this.hideModal(); |
|||
}, |
|||
showModal() { |
|||
// 显示model |
|||
if (!this.disabled) { |
|||
this.isShowModal = true; |
|||
} |
|||
}, |
|||
hideModal() { |
|||
// 隐藏model |
|||
this.isShowModal = false; |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
<style> |
|||
@font-face { |
|||
font-family: 'selectIcon'; |
|||
src: url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.eot?t=1590375117208'); /* IE9 */ |
|||
src: url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.eot?t=1590375117208#iefix') format('embedded-opentype'), |
|||
/* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.svg?t=1590375117208#selectIcon') |
|||
format('svg'); /* iOS 4.1- */ |
|||
} |
|||
|
|||
.selectIcon { |
|||
font-family: 'selectIcon' !important; |
|||
font-size: 16px; |
|||
font-style: normal; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
} |
|||
|
|||
.icongou:before { |
|||
content: '\e61c'; |
|||
} |
|||
|
|||
.iconcross:before { |
|||
content: '\e61a'; |
|||
} |
|||
</style> |
|||
<style lang="scss" scoped> |
|||
.main { |
|||
font-size: 30rpx; |
|||
} |
|||
.bg-white { |
|||
background-color: #ffffff; |
|||
} |
|||
.text-blue { |
|||
color: #0081ff; |
|||
} |
|||
.text-green { |
|||
color: #39b54a; |
|||
} |
|||
.input { |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 28rpx; |
|||
height: 60rpx; |
|||
padding: 10rpx 20rpx; |
|||
border-radius: 8rpx; |
|||
border-style: solid; |
|||
border-width: 1rpx; |
|||
border-color: rgb(220, 223, 230); |
|||
input { |
|||
flex: 1; |
|||
} |
|||
} |
|||
.select-modal { |
|||
position: fixed; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
z-index: 9999; |
|||
opacity: 0; |
|||
outline: 0; |
|||
text-align: center; |
|||
-ms-transform: scale(1.185); |
|||
transform: scale(1.185); |
|||
backface-visibility: hidden; |
|||
perspective: 2000rpx; |
|||
background: rgba(0, 0, 0, 0.6); |
|||
transition: all 0.3s ease-in-out 0s; |
|||
pointer-events: none; |
|||
margin-bottom: -1000rpx; |
|||
&::before { |
|||
content: '\200B'; |
|||
display: inline-block; |
|||
height: 100%; |
|||
vertical-align: bottom; |
|||
} |
|||
.select-dialog { |
|||
position: relative; |
|||
display: inline-block; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
background-color: #f8f8f8; |
|||
overflow: hidden; |
|||
width: 100%; |
|||
border-radius: 0; |
|||
.select-content { |
|||
// background-color: #F1F1F1; |
|||
max-height: 420rpx; |
|||
overflow: auto; |
|||
.select-item { |
|||
padding: 20rpx; |
|||
display: flex; |
|||
.title { |
|||
flex: 1; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.select-modal.show { |
|||
opacity: 1; |
|||
transition-duration: 0.3s; |
|||
-ms-transform: scale(1); |
|||
transform: scale(1); |
|||
overflow-x: hidden; |
|||
overflow-y: auto; |
|||
pointer-events: auto; |
|||
margin-bottom: 0; |
|||
} |
|||
.select-bar { |
|||
padding: 0 20rpx; |
|||
display: flex; |
|||
position: relative; |
|||
align-items: center; |
|||
min-height: 80rpx; |
|||
justify-content: space-between; |
|||
.action { |
|||
display: flex; |
|||
align-items: center; |
|||
height: 100%; |
|||
justify-content: center; |
|||
max-width: 100%; |
|||
} |
|||
} |
|||
|
|||
.uni-input-input, |
|||
.uni-input-placeholder { |
|||
color: #c0c4cc; |
|||
font-size: 28rpx; |
|||
} |
|||
</style> |
Loading…
Reference in new issue