封裝一個小程序選擇器(可多選、單選、搜索)

組件

<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>

效果

效果:

企業微信截圖_17483173394654.png

企業微信截圖_17483173487807.png

個人站點鏈接

我的博客鏈接:https://blog.yimengtut.online/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907670.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907670.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907670.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2.1HarmonyOS NEXT開發工具鏈進階:DevEco Studio深度實踐

HarmonyOS NEXT開發工具鏈進階&#xff1a;DevEco Studio深度實踐 在HarmonyOS NEXT全棧自研的技術體系下&#xff0c;DevEco Studio作為一站式開發平臺&#xff0c;通過深度整合分布式開發能力&#xff0c;為開發者提供了從代碼編寫到多端部署的全流程支持。本章節將圍繞多設…

LLMs之Tool:Workflow Use的簡介、特點、安裝和使用方法、以及案例應用

LLMs之Tool&#xff1a;Workflow Use的簡介、特點、安裝和使用方法、以及案例應用 目錄 Workflow Use的簡介 1、Workflow Use的特點 2、Workflow Use的愿景和路線圖 Workflow Use的安裝和使用方法 1、安裝 2、使用方法 查看所有命令 從 Python 中使用&#xff1a; 啟動…

二分法算法技巧-思維提升

背景&#xff1a; 在寫力扣題目“搜素插入位置 ”時&#xff0c;發現二分法的一個細節點&#xff0c;打算記錄下來&#xff0c;先看一張圖&#xff1a; 我們知道&#xff0c;排序數組&#xff0c;更高效的是二分查找法~~~而二分法就是切割中間&#xff0c;定義left是最開始的&…

Python 訓練營打卡 Day 40

訓練和測試的規范寫法 一、黑白圖片的規范寫法&#xff0c;以MNIST數據集為例 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms # 用于加載MNIST數據集 from torch.utils.data import DataLoader # 用于創建…

數據結構之棧:原理與常用方法

1. 棧的定義 Stack是Vector的一個子類&#xff0c;它實現標準的后進先出堆棧。Stack只定義了創建空堆棧的默認構造方法。&#xff08;實際上是實現了List接口&#xff0c;因為Vector是List的子類&#xff09;。 Stack() // 創建一個空棧 2. 棧的基本操作 // 壓棧操作 publi…

鴻蒙OSUniApp 開發支持圖片和視頻的多媒體展示組件#三方框架 #Uniapp

使用 UniApp 開發支持圖片和視頻的多媒體展示組件 前言 在現代移動應用中&#xff0c;圖片和視頻已成為內容展示的主流形式。一個優秀的多媒體展示組件不僅能提升用戶體驗&#xff0c;還能增強產品的互動性和視覺沖擊力。隨著鴻蒙&#xff08;HarmonyOS&#xff09;生態的不斷…

STM32CubeMX,arm-none-eabi-gcc簡單試用

在windows下&#xff0c;為stm32系列單片機編程&#xff0c;keil有了免費的試用版&#xff0c;有很多開發板示例&#xff0c;給學習單片機編程帶來很大的方便。 STM32CubeMX提供了stm32單片機的功能設置&#xff0c;在輸出方式上給出了幾種方式&#xff0c;有mdk&#xff08;k…

灌水論壇系統總體設計文檔

一、實驗題目 灌水論壇系統 二、實驗目的 旨在通過一個相對完整且功能豐富的Web應用實例&#xff0c;全面地實踐和鞏固Web開發所需的各項核心技術和工程方法&#xff0c;從而提升其綜合應用能力和解決實際開發問題的能力。它不僅僅是完成一個軟件&#xff0c;更是一個學習、…

Android 13中 配置簽名文件與內置相應的Apk

目錄 1.問題場景 2.實現思路 3.將測試代碼做成APK并配置簽名 4.將apk內置到系統當中的方法 1.問題場景 在展訊平臺中Android13的源碼已知的情況下&#xff0c;客戶寫了一個測試類用于調用系統中的一些接口來檢驗一些功能。為了方便調試排查問題我首先的思路是將客戶寫的測試…

HarmonyOS 5 應用開發導讀:從入門到實踐

一、HarmonyOS 5 概述 HarmonyOS 5 是華為推出的新一代分布式操作系統&#xff0c;其核心設計理念是"一次開發&#xff0c;多端部署"。與傳統的移動操作系統不同&#xff0c;HarmonyOS 5 提供了更強大的跨設備協同能力&#xff0c;支持手機、平板、智能穿戴、智慧屏…

C語言創意編程:用趣味實例玩轉基礎語法(4)

文章目錄 0. 前言1. &#x1f308; 彩虹文字生成器1.1 程序效果展示1.2 完整代碼解析1.3 關鍵技術詳解1.3.1 Windows控制臺API1.3.2 顏色編碼1.3.3 安全輸入1.3.4 跨平臺考慮 2. &#x1f3b5; 簡易音樂播放器2.1 程序效果展示2.2 完整代碼解析2.3 關鍵技術詳解2.3.1 Windows B…

【專題】神經網絡期末復習資料(題庫)

神經網絡期末復習資料&#xff08;題庫&#xff09; 鏈接&#xff1a;https://blog.csdn.net/Pqf18064375973/article/details/148332887?sharetypeblogdetail&sharerId148332887&sharereferPC&sharesourcePqf18064375973&sharefrommp_from_link 【測試】 Th…

Python訓練營打卡 Day41

簡單CNN 知識回顧 數據增強卷積神經網絡定義的寫法batch歸一化&#xff1a;調整一個批次的分布&#xff0c;常用與圖像數據特征圖&#xff1a;只有卷積操作輸出的才叫特征圖調度器&#xff1a;直接修改基礎學習率 卷積操作常見流程如下&#xff1a; 1. 輸入 → 卷積層 → Batch…

leetcode216.組合總和III:回溯算法中多條件約束下的狀態管理

一、題目深度解析與組合約束條件 題目描述 找出所有相加之和為n的k個數的組合&#xff0c;且滿足以下條件&#xff1a; 每個數只能使用一次&#xff08;范圍為1到9&#xff09;所有數字均為唯一的正整數組合中的數字按升序排列 例如&#xff0c;當k3&#xff0c;n9時&#…

Java面試實戰:從Spring到大數據的全棧挑戰

Java面試實戰&#xff1a;從Spring到大數據的全棧挑戰 在某家知名互聯網大廠&#xff0c;嚴肅的面試官正在面試一位名叫謝飛機的程序員。謝飛機以其搞笑的回答和對Java技術棧的獨特見解而聞名。 第一輪&#xff1a;Spring與微服務的探索 面試官&#xff1a;“請你談談Spring…

基于vue框架的動物園飼養管理系統a7s60(程序+源碼+數據庫+調試部署+開發環境)帶論文文檔1萬字以上,文末可獲取,系統界面在最后面。

系統程序文件列表 項目功能&#xff1a;飼養員,健康登記,工作進度,動物信息,進食信息,動物健康,動物醫治,飼料信息,工作留言 開題報告內容 基于Vue框架的動物園飼養管理系統開題報告 一、研究背景與意義 &#xff08;一&#xff09;研究背景 隨著城市化進程加快和公眾對生…

docker鏡像與dockerfile

一、docker鏡像 1.什么是鏡像 容器解決應用開發、測試和部署的問題&#xff0c;而鏡像解決應用部署環境問題。鏡像是一個只讀的容器模板&#xff0c; 打包了應用程序和應用程序所依賴的文件系統以及啟動容器的配置文件&#xff0c;是啟動容器的基礎。鏡像所打 包的文件內容就是…

流媒體基礎解析:音視頻封裝格式與傳輸協議

在視頻處理與傳輸的完整流程中&#xff0c;音視頻封裝格式和傳輸協議扮演著至關重要的角色。它們不僅決定了視頻文件的存儲方式&#xff0c;還影響著視頻在網絡上的傳輸效率和播放體驗。今天&#xff0c;我們將深入探討音視頻封裝格式和傳輸協議的相關知識。 音視頻封裝格式 什…

普中STM32F103ZET6開發攻略(一)

各位看官老爺們&#xff0c;點擊關注不迷路喲。你的點贊、收藏&#xff0c;一鍵三連&#xff0c;是我持續更新的動力喲&#xff01;&#xff01;&#xff01; 目錄 普中STM32F103ZET6開發攻略 1. GPIO端口實驗——點亮LED燈 1.1 實驗目的 1.2 實驗原理 1.3 實驗環境和器材…

AWS API Gateway 配置WAF(中國區)

問題 需要給AWS API Gateway配置WAF。 AWS WAF設置 打開AWS WAF首頁&#xff0c;開始創建和配置WAF&#xff0c;如下圖&#xff1a; 設置web acl名稱&#xff0c;然后開始添加aws相關資源&#xff0c;如下圖&#xff1a; 選擇資源類型&#xff0c;但是&#xff0c;我這里出…