組件
<template><view class="popup" v-show="show"><view class="bg" @tap="cancelMultiple"></view><view class="selectMultiple"><view class="multipleBody"><view class="title"><view class="close" @tap="cancelMultiple">取消</view><view class="name"><!-- cancelButton="none" 不展示取消按鈕--><uni-search-bar@input="updateList"@confirm="onSearchConfirm"cancelButton="none"></uni-search-bar></view><view class="confirm" @tap="confirmMultiple">確認</view></view><view class="list"><view class="mask mask-top"></view><view class="mask mask-bottom"></view><scroll-view class="diet-list" scroll-y="true"><view v-for="(item, index) in list" :class="['item', item.selected ? 'checked' : '']" @tap="onChange(index, item)"><span style="font-size: 16px;">{{item.label}}</span><view class="icon" v-show="item.selected"><icon type="success_no_circle" size="16" color="#2D8DFF"/></view></view></scroll-view></view></view></view></view>
</template><script>
export default {name:"my-curry-multi-select",data() {return {// 選中值value: [],// 選中列表selected: [],// 列表數據list: [],originList: [],};},props: {// 是否顯示show: {type: Boolean,default: false},// 標題title: {type: String,default: ''},//數據列表columns: {type: Array,default: []},// 默認選中defaultIndex: {type: Array,default: [],},isMultiSelect: {type: Boolean,default: true},},watch: {// 監聽是否顯示show(val) {if(val) {this.openMultiple();}}},methods: {sortListWithSelectedFirst(list) {return list.slice().sort((a, b) => {const aSelected = a.selected ? 1 : 0;const bSelected = b.selected ? 1 : 0;return bSelected - aSelected;});},updateList(str) {this.list.map(e => {this.originList.map(item => {if (e.selected && item.value === e.value) {item.selected = true}})})if (str === null || str === undefined || str === '') {this.list = JSON.parse(JSON.stringify(this.originList))} else {const filtered = this.originList.filter(e => e.label.indexOf(str) > -1 || e.selected);this.list = this.sortListWithSelectedFirst(filtered);}},// 新增:處理搜索確認事件onSearchConfirm(e) {const searchValue = e.value || e;// 先更新列表this.updateList(searchValue);// 如果有搜索內容且搜索結果不為空,自動選擇第一個未選中的項目if (searchValue && this.list.length > 0) {// 找到第一個未選中的項目const firstUnselectedIndex = this.list.findIndex(item => !item.selected);if (firstUnselectedIndex !== -1) {// 自動選擇第一個未選中的項目this.onChange(firstUnselectedIndex, this.list[firstUnselectedIndex]);}}},// 列點擊事件onChange(index, item) {// 單選if (!this.isMultiSelect) {this.value = [];this.selected = [];this.value.push(item.value.toString());this.selected.push({label: item.label,value: item.value,});return this.$emit("confirm", {selected: this.selected, value: this.value});}// 是否已選中if(this.value.indexOf(item.value.toString()) >= 0) {this.list[index].selected = false;} else {this.list[index].selected = true;}// 篩選已勾選數據this.value = [];this.selected = [];this.list.forEach((col_item, col_index) => {if(col_item.selected) {this.value.push(col_item.value.toString());this.selected.push({label: col_item.label,value: col_item.value,});}});this.list = this.sortListWithSelectedFirst(this.list);this.$emit("change", {selected: this.selected, value: this.value});},// 彈出框開啟觸發事件openMultiple() {// 初始化列表數據,默認勾選數據this.value = this.defaultIndex;this.columns.forEach((item, index) => {this.$set(item, "selected", false);if(this.value.indexOf(item.value.toString()) >= 0) {item.selected = true;}});this.originList = Object.assign([], this.columns);this.list = this.sortListWithSelectedFirst(JSON.parse(JSON.stringify(this.originList)));},// 確認confirmMultiple() {this.$emit("confirm", {selected: this.selected, value: this.value});},// 關閉/取消cancelMultiple() {this.$emit("cancel");},}
}
</script><style scoped lang="scss">
.popup {width: 100%;height: 100vh;position: fixed;z-index: 99999;left: 0;top: 0;.bg {width: 100%;height: 100%;background-color: rgba(black, .5);}
}
.selectMultiple {transition: none !important;will-change: transform;width: 100%;position: absolute;left: 0;top: 0;height: 50vh;background-color: white;border-radius: 0 0 20rpx 20rpx;box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);overflow: hidden;.multipleBody {width: 100%;height: 100%;padding: 30rpx;box-sizing: border-box;display: flex;flex-direction: column;.title {flex-shrink: 0;font-size: 28rpx;display: flex;flex-direction: row;align-items: center; /* 添加這一行 */.close {width: 80rpx;text-align: left;opacity: .5;}.name {width: 530rpx;text-align: center;overflow: hidden;display: -webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;}.confirm {width: 80rpx;text-align: right;color: #2D8DFF;}}.list {flex: 1;overflow: hidden;width: 100%;padding-top: 30rpx;position: relative;.mask {width: 100%;height: 60rpx; // 減小漸變區域position: absolute;left: 0;z-index: 2;pointer-events: none;&.mask-top {top: 30rpx;background-image: linear-gradient(to bottom, #fff, rgba(#fff, 0));}&.mask-bottom {bottom: 0;background-image: linear-gradient(to bottom, rgba(#fff, 0), #fff);}}.diet-list {height: 100%;max-height: none;}.item {display: flex;justify-content: space-between;align-items: center;padding: 20rpx 0;border-bottom: 1px solid rgba(#000, 0.05);span {flex: 1;font-size: 30rpx;text-align: center;}.icon {width: 32rpx;height: 32rpx;}&.checked {color: #2D8DFF;}&:last-child {border-bottom: none;margin-bottom: 60rpx;}&:first-child {margin-top: 60rpx;}}}}
}
</style>
使用
<template><view class="container"><view><uni-forms ref="taskForm" :model="taskForm" labelWidth="80px"><!-- 任務類型單選 --><uni-forms-item label="任務類型" name="type"><view class="item"><view :class="['select', taskForm.type ? 'selected' : '']"@tap="openTypeSelectionBox(taskForm.type)">{{ taskForm.type ? getTaskTypeName(taskForm.type) : '請選擇任務類型' }}</view><!-- 如果有內容顯示關閉圖標 --><uni-icons v-if="taskForm.type !== ''" type="clear" size="24" color="#c0c4cc" class="close-btn"@tap="clearType"></uni-icons><!-- 如果沒有內容顯示下拉圖標 --><uni-icons v-else type="pulldown" size="24" color="#c0c4cc" class="close-btn"@tap="openTypeSelectionBox(taskForm.type)"></uni-icons><my-curry-multi-select title="請選擇" :show="taskTypeShow" :columns="taskTypeList":defaultIndex="defaultTaskTypeIndex":isMultiSelect="false"@confirm="confirmType($event)"@cancel="taskTypeShow = false"></my-curry-multi-select></view></uni-forms-item><!-- 負責人多選 --><uni-forms-item label="負責人" name="personInChargeIds"><view class="item"><view :class="['select', (Array.isArray(taskForm.personInChargeIds) && taskForm.personInChargeIds.length > 0) ? 'selected' : '']"@tap="openPersonInChargeIdsMultiSelectionBox(taskForm.personInChargeIds)">{{ (Array.isArray(taskForm.personInChargeIds) && taskForm.personInChargeIds.length > 0)? getUserNamesByIds(taskForm.personInChargeIds): '請選擇負責人' }}</view><uni-icons v-if="Array.isArray(taskForm.personInChargeIds) && taskForm.personInChargeIds.length > 0"type="clear" size="24" color="#c0c4cc" class="close-btn"@tap="clearPersonInChargeIds"></uni-icons><uni-icons v-else type="pulldown" size="24" color="#c0c4cc" class="close-btn"@tap="openPersonInChargeIdsMultiSelectionBox(taskForm.personInChargeIds)"></uni-icons><my-curry-multi-select title="請選擇" :show="taskTaskPersonInChargesShow":columns="userList":defaultIndex="defaultTaskPersonInChargesIndex":isMultiSelect="true"@confirm="confirmPersonInChargeIds($event)"@cancel="taskTaskPersonInChargesShow = false"></my-curry-multi-select></view></uni-forms-item></uni-forms><button type="primary" @click="submit">提交</button></view></view>
</template><script>
import myCurryMultiSelect from "@/components/curry-multi-select/my-curry-multi-select.vue";export default {components: {myCurryMultiSelect},data() {return {// 當前正選擇哪個任務類型元素defaultTaskTypeIndex: [],// 任務類型列表,單選taskTypeList: [{"label": "指派任務", "value": 1},{"label": "設計任務", "value": 2},{"label": "代辦", "value": 2}],// 是否展示任務類型下拉選項taskTypeShow: false,// 當前正選擇哪些任務負責人元素defaultTaskPersonInChargesIndex: [],// 是否展示任務負責人下拉選項taskTaskPersonInChargesShow: false,// 用戶列表,多選userList: [{ value: 1, label: '張三' },{ value: 2, label: '李四' },{ value: 3, label: '王五' },],// 表單數據taskForm: {taskTitle: '',insertUser: '',type: 2,personInChargeIds: [1,2],personInChargeId: null,taskContent: '',requiredCompletionTime: '',actualCompletionTime: '',weight: '',weightScore: '',timeoutStatus: '0',participants: [],taskPictureUrl: [],taskFileUrl: [],useSchedule: '1',standardWorkingHours: '',},// 表單驗證規則rules: {type: {rules: [{required: true, errorMessage: '任務類型不能為空'}]},personInChargeIds: {rules: [{required: true,errorMessage: '負責人不能為空',validateFunction: (rule, value) => {return Array.isArray(value) && value.length > 0;}}]},},}},onLoad() {},created() {},onReady() {this.$refs.taskForm.setRules(this.rules)},methods: {// =====單選====// 打開任務類型選擇框openTypeSelectionBox(val) {console.log('執行了openTypeSelectionBox,展開選擇框時val值是:', val)this.defaultTaskTypeIndex = val !== '' ? [String(val)] : [];console.log('this.defaultTaskTypeIndex',this.defaultTaskTypeIndex)this.taskTypeShow = true;},// 清空類型選擇框clearType() {this.defaultTaskTypeIndex = [];this.taskForm.type = '';},// 獲取任務類型名稱,把值轉換為名稱顯示出來getTaskTypeName(value) {const option = this.taskTypeList.find(item => String(item.value) === String(value));return option ? option.label : '請選擇任務類型';},// 確認選擇任務類型confirmType(e) {// e是一個數組this.taskForm.type = e.value[0];this.taskTypeShow = false;},// =====多選====// 打開負責人多選框openPersonInChargeIdsMultiSelectionBox(val) {console.log('執行了openPersonInChargeIdsMultiSelectionBox,展開選擇框時val值是:', val)this.defaultTaskPersonInChargesIndex = Array.isArray(val) ? val.map(item => String(item)) : [];console.log('this.defaultTaskPersonInChargesIndex', this.defaultTaskPersonInChargesIndex)this.taskTaskPersonInChargesShow = true;},// 清空負責人選擇框clearPersonInChargeIds() {this.defaultTaskPersonInChargesIndex = [];this.taskForm.personInChargeIds = null; // 繼續保持你的設定},// 獲取任務負責人名稱,把值轉換為名稱顯示出來getUserNamesByIds(values) {if (!Array.isArray(values) || values.length === 0) return '請選擇負責人';const labels = values.map(value => {const option = this.userList.find(item => String(item.value) === String(value));return option ? option.label : value;});return labels.join(',');},// 確認選擇任務負責人confirmPersonInChargeIds(e) {// e是一個數組this.taskForm.personInChargeIds = e.value;this.taskTaskPersonInChargesShow = false;},// 提交表單submit() {console.log('提交時表單數據是:', this.taskForm)// 就是上面這個寫法有一個問題,就是提交的時候,選擇框的綁定的都是字符串。就是是數值,也是轉為字符串的。但是前段字符串,后端用Long也能接收。所以問題不大。this.$refs.taskForm.validate().then(res => {this.$modal.msgSuccess("修改成功")})},}
}
</script><style lang="scss">
.item {width: 100%;padding: 0;position: relative;display: flex;align-items: center;height: 35px;.select {flex-grow: 1;border: 1px solid #dadbde;padding: 4px 9px;border-radius: 4px;font-size: 12px;box-sizing: border-box;color: #6a6a6a;line-height: 25px;height: 100%;overflow: hidden;&.selected {color: black;font-size: 15px;}}.close-btn {position: absolute;right: 6px;top: 50%;transform: translateY(-50%);color: red;cursor: pointer;}
}
</style>
效果
效果:
個人站點鏈接
我的博客鏈接:https://blog.yimengtut.online/