| pages.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| pages/MJGL/Gy_MouldFile/Gy_MouldFileList.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| pages/MJGL/shangmudan/MouldUpperBill.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| pages/caigouruku/POStockInBill.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| pages/gongxuOut/Cj_StationOutBill.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| pages/index/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| pages/jishikucunchaxun/table.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| uni_modules/zxz-uni-data-select/changelog.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| uni_modules/zxz-uni-data-select/components/zxz-uni-data-select/zxz-uni-data-select.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| uni_modules/zxz-uni-data-select/package.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| uni_modules/zxz-uni-data-select/readme.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
pages.json
@@ -1323,6 +1323,14 @@ "navigationBarTitleText" : "待我审核", "enablePullDownRefresh": true } }, { "path" : "pages/MJGL/Gy_MouldFile/Gy_MouldFileList", "style" : { "navigationBarTitleText" : "模具档案查询", "enablePullDownRefresh": true } } ], pages/MJGL/Gy_MouldFile/Gy_MouldFileList.vue
New file @@ -0,0 +1,482 @@ <template> <view class="page" id="pageContent"> <view class="search-condition-zone"> <view class="form-item"> <view class="left">模具分类</view> <!-- <uni-data-select v-model="hform.HMouldTypeID" :localdata="HMouldTypeList" @change="" :clear="false" ></uni-data-select> --> <zxz-uni-data-select v-model="hform.HMouldTypeID" dataKey="器具分类名称" dataValue="HItemID" :filterable="true" :localdata="HMouldTypeList" :clear="false" ></zxz-uni-data-select> </view> <view class="form-item"> <view class="left"> 器具编号: </view> <view class="right general"> <input type="text" v-model="hform.HMouldNumber" /> </view> </view> <view class="form-item"> <view class="left"> 器具名称: </view> <view class="right general"> <input type="text" v-model="hform.HMouldName" /> </view> </view> </view> <view class="button-zone"> <button type="default" class="btn-a" size="mini" @tap="cmdSearch">查询</button> <button type="default" class="btn-c" size="mini" @tap="exit">退出</button> </view> <view style="width: 100%;height: 16rpx;background-color: #e5e5e5;"></view> <view class="card-item" v-for="(item, index) in showList" :key="index"> <uni-card :title="item['单据号']" :extra="'日期:' + item['日期'].split('T')[0]" @tap="showDetail = showDetail==index?-1:index"> <view class="card-detail"> <!-- 动态生成所有非空字段 --> <view class="detail" v-for="(value, key,keyIndex) in item" :key="key" v-if="keyIndex<=10 && shouldShowField(key, value)" > <text>{{ formatFieldName(key) }}:</text>{{ value }} </view> </view> <view class="card-detail" v-if="showDetail == index"> <view class="detail" v-for="(value, key,keyIndex) in item" :key="key" v-if="keyIndex>=15 && shouldShowField(key, value)" > <text>{{ formatFieldName(key) }}:</text>{{ value }} </view> </view> <view class="more" v-if="showDetail == index && operations != index"> <view class="part" style="border-right: 1px solid #eee;"> <uni-icons type="top" style="color: #888;margin-right: 10rpx;" size="14"></uni-icons>收起 </view> <view class="part" @tap.stop="operations = operations==index?-1:index"> <uni-icons type="more-filled" style="color: #888;margin-right: 10rpx;" size="14"></uni-icons>操作 </view> </view> <view class="more" v-if="showDetail != index && operations != index"> <view class="part" style="border-right: 1px solid #eee;"> <uni-icons type="bottom" style="color: #888;margin-right: 10rpx;" size="14"></uni-icons>更多信息 </view> <view class="part" @tap.stop="operations = operations==index?-1:index"> <uni-icons type="more-filled" style="color: #888;margin-right: 10rpx;" size="14"></uni-icons>操作 </view> </view> <view class="op" v-if="operations == index"> <button class="op5" size="mini" plain @tap.stop="operations = -1">取消操作</button> </view> </uni-card> </view> <view class="over" v-if="listData.length == 0">暂无数据</view> <view class="over" v-if="listData.length != 0 && listData.length != showList.length">加载中...</view> <view class="over" v-if="listData.length != 0 && listData.length == showList.length">已到底</view> </view> </template> <script> import { CommonUtils } from '@/utils/common' import { getUserInfo } from '@/utils/auth' import dayjs, { Dayjs } from 'dayjs' export default { data() { return { showDetail: -1, operations : -1, HMouldTypeList: [ { HItemID: 0, 器具分类名称: "全部" }, ], hform: { HMouldTypeID:0, HMouldNumber: '', HMouldName:'' }, sWhere: '', listData: [], showList: [], page: 1, } }, onReachBottom: function() { this.page++ setTimeout(() => { this.showList = this.showList.concat(this.getPage(this.page, this.listData)) }, 100) }, onPullDownRefresh: function() { this.cmdSearch() setTimeout(() => { uni.stopPullDownRefresh(); }, 1000); }, computed: { }, methods: { // 判断哪些字段需要显示 shouldShowField(key, value) { // 排除不需要显示的字段 const excludeKeys = ['单据号', '日期']; // 这些字段已经在其他地方显示了 // 判断key是否全英文(不包含中文) const isAllEnglish = /^[a-zA-Z]+$/.test(key); // 判断key是否包含"ID"(不区分大小写) const containsID = key.toUpperCase().includes('ID'); return !excludeKeys.includes(key) && !isAllEnglish && // 排除全英文的key !containsID && // 排除包含ID的key // value !== null && value !== undefined // && // value !== ''; }, // 格式化字段名显示 formatFieldName(key) { // 你可以根据需求自定义显示名称 const nameMap = { '物料代码': '物料代码', '物料名称': '物料名称', '规格型号': '规格型号', // ... 其他字段映射 }; return nameMap[key] || key; }, exit() { uni.navigateBack() }, getPage(page, list) { let sindex = (parseInt(page) - 1) * 20 let eindex = parseInt(page) * 20 let newList = list.slice(sindex, eindex) return newList }, async cmdSearch() { let sWhere = ' ' if (this.hform.HMouldName != "") { sWhere += " and 模具名称 like '%" + this.hform.HMouldName + "%'" } if (this.hform.HMouldNumber != "") { sWhere += " and 模具编号 like '%" + this.hform.HMouldNumber + "%'" } if (this.hform.HMouldTypeID != "0") { sWhere += " and HMouldTypeID = '" + this.hform.HMouldTypeID + "'" } try { let res = await CommonUtils.doRequest2Sync({ url: '/Gy_Mould/list1', data: { "sWhere": sWhere, "ModRightNameSelect":"Gy_MouldFileList", "user": getUserInfo()["Czymc"] }, }) if (!res) { return } let { data, count, Message } = res.data if (count > 0) { this.listData = res.data.data this.showList = this.getPage(this.page, this.listData) } else { uni.showToast({ icon: 'none', title: Message }) } } catch (err) { console.warn(err); uni.showToast({ title: '接口请求失败:' + err, icon: 'none' }) } }, //模具档案分类获取接口 async mouldTypeSearch() { try { let res = await CommonUtils.doRequest2Sync({ url: '/Gy_ModelType/list', data: { "sWhere": '', "ModRightNameSelect":"Gy_MouldTypeList", "user": getUserInfo()["Czymc"] }, }) if (!res) { return } let { data, count, Message } = res.data if (count > 0) { console.log(res.data.data) this.HMouldTypeList.push(...res.data.data) } else { uni.showToast({ icon: 'none', title: Message }) } } catch (err) { console.warn(err); uni.showToast({ title: '接口请求失败:' + err, icon: 'none' }) } }, }, async onShow() { await this.mouldTypeSearch(); this.$nextTick(() => { this.cmdSearch() }) }, } </script> <style lang="scss" scoped> .page { box-sizing: border-box; display: flex; flex-direction: column; gap: 20rpx; padding: 20rpx 0; position: relative; .button-zone { height: auto; box-sizing: border-box; padding-top: 20rpx; display: flex; flex-direction: row; justify-content: space-between; flex-wrap: wrap; button { border-radius: 50rpx; width: 180rpx; height: 66rpx; line-height: 66rpx; font-size: 28rpx; } .btn-a { background-color: #3a78ff; color: #fff; } .btn-c { background-color: #ff5722; color: #fff; } } .search-condition-zone { height: auto; box-sizing: border-box; padding: 0 60rpx; display: flex; flex-direction: column; gap: 20rpx; .form-item { display: flex; flex-direction: row; gap: 20rpx; align-items: center; font-size: 28rpx; .left { width: 4rem; } .right { flex: 1; padding: 8rpx 16rpx; .search { width: 28rpx; height: 28rpx; } input { font-size: 28rpx; } .uni-combox { padding: 0; margin: 0; ::v-deep .uni-combox__input { font-size: 28rpx; height: auto; } } } .general { border-radius: 22rpx; border: 1px solid #acacac; } .disabled { border-radius: 22rpx; border: 1px solid #e4e4e4; background-color: #e4e4e4; } } } .info-list-zone { overflow-y: auto; .card-item { .card-detail { width: 100%; display: flex; flex-wrap: wrap; justify-content: space-between; line-height: 120%; .detail { // width: 50%; font-size: 26rpx; margin-bottom: 12rpx; color: #555; margin-right: 20rpx; text { color: #999; font-size: 26rpx; } } } } } .daterange { display: flex; flex-direction: row; gap: 10rpx; justify-content: center; align-items: center; } .more { color: #888; font-size: 24rpx; display: flex; border-top: 1px solid #eee; padding-top: 20rpx; .part { width: 50%; text-align: center; } } .op { display: flex; justify-content: space-between; gap: 20rpx; margin-top: 20rpx; flex-wrap: wrap; align-content: flex-start; button { margin: 0; flex-shrink: 0; padding: 0; width: 150rpx; flex-basis: 150rpx; font-size: 25rpx; } .op1 { border: 1px solid #41a863; color: #41a863; } .op2 { border: 1px solid #d98d00; color: #d98d00; } .op3 { border: 1px solid #3a78ff; color: #3a78ff; } .op4 { border: 1px solid #da0000; color: #da0000; } .op5 { border: 1px solid #888; color: #888; } } .pagination-zone { position: fixed; bottom: 0; box-sizing: border-box; background-color: #fff; box-shadow: 0 2rpx 10rpx 2rpx rgba(0, 0, 0, 0.4); padding: 20rpx 40rpx 20rpx 40rpx; display: flex; flex-direction: column; gap: 20rpx; justify-content: space-between; width: 100%; } } </style> pages/MJGL/shangmudan/MouldUpperBill.vue
@@ -939,25 +939,25 @@ }) } // 如果是事业一处组织,校验器具数量 if (uni.getStorageSync('OrganizationID') === "100007" && uni.getStorageSync('Organization') === "事业一处") { const zeroQtyItem = this.listData.find(item => { // 考虑0、null、undefined等异常情况 const qty = Number(item.器具数量) || 0; return qty <= 0; }); // if (uni.getStorageSync('OrganizationID') === "100007" && uni.getStorageSync('Organization') === "事业一处") { // const zeroQtyItem = this.listData.find(item => { // // 考虑0、null、undefined等异常情况 // const qty = Number(item.器具数量) || 0; // return qty <= 0; // }); if (zeroQtyItem) { // 找到第一个数量异常项的位置(索引+1) const index = this.listData.indexOf(zeroQtyItem) + 1; const code = zeroQtyItem.器具编码 || '未知编码'; uni.showToast({ title: `第${index}行【${code}】器具数量为0,请检查`, icon: 'none', duration: 3000 }); return; } } // if (zeroQtyItem) { // // 找到第一个数量异常项的位置(索引+1) // const index = this.listData.indexOf(zeroQtyItem) + 1; // const code = zeroQtyItem.器具编码 || '未知编码'; // uni.showToast({ // title: `第${index}行【${code}】器具数量为0,请检查`, // icon: 'none', // duration: 3000 // }); // return; // } // } if (!this.hform.HEmpName) { uni.showToast({ title: '请选择操作员', pages/caigouruku/POStockInBill.vue
@@ -158,7 +158,12 @@ <view v-if="tabs == 2"> <view class="list" v-for="(item,index) in Materlist" :key="index"> <uni-card :title="item.物料名称" :extra="item.物料代码" style="margin: 10px;" @tap="delMater(item)"> <uni-card :title="item.物料名称" style="margin: 10px;" @tap="delMater(item, $event)"> <!-- 物料代码作为可点击链接 --> <view class="card-header" @tap.stop="gotoInventoryQuery(item.物料代码)"> <text class="link-text">物料代码:{{item.物料代码}}</text> </view> <view class="card-detail"> <view class="detail"> <text>源单单号:</text>{{item.源单单号}} @@ -187,8 +192,7 @@ <view class="detail" v-if="item.单价"> <text>单价:</text>{{item.单价}} </view> <view class="detail" v-if="materMeta[0].HWHName && /兴达/.test(hform.HStockOrgName )"> <view class="detail" v-if="materMeta[0].HWHName && /兴达/.test(hform.HStockOrgName)"> <text>仓库:</text>{{materMeta[0].HWHName}} </view> </view> @@ -1536,7 +1540,30 @@ }, }); }, gotoInventoryQuery(HMaterNumber) { console.log('跳转到库存查询,物料代码:', HMaterNumber); // 使用uni.navigateTo跳转到新页面 uni.navigateTo({ url: `/pages/jishikucunchaxun/table?OperationType=2&HMaterNumber=${HMaterNumber}`, success: (res) => { console.log('跳转成功'); }, fail: (err) => { console.error('跳转失败:', err); // 如果页面不存在,可以跳转到默认页面 uni.showToast({ title: '功能正在开发中', icon: 'none' }); } }); }, delMater(item) { if (event && event.target.classList && event.target.classList.contains('link-text')) { return; // 如果是链接点击,不执行删除 } uni.showModal({ title: '提示', content: '确认要删除 "' + item.物料名称 + '" 所有扫码记录?删除后将不可恢复!', @@ -2014,6 +2041,10 @@ color: #fff; } } /* 添加链接样式 */ .link-text { color: #3a78ff; /* 蓝色,类似超链接 */ } .list { width: 100%; @@ -2036,6 +2067,7 @@ color: #999; font-size: 26rpx; } } } pages/gongxuOut/Cj_StationOutBill.vue
@@ -107,7 +107,7 @@ <view class="tick-wrapper"> <view class="form-item"> <view class="title">工时:</view> <view class="title">工时(小时):</view> <view class="right"> <input v-model="hform.HWorkTimes" placeholder="请输入工时" @blur="HWorkTimesChange" :disabled="hform.HIsTimeFlag!=1"/> </view> @@ -121,7 +121,7 @@ </checkbox-group> </view> </view> <view class="form-item"> <view class="form-item" v-show="false"> <view class="title">开工时间:</view> <view class="right"> <uni-datetime-picker v-model="hform.HRelBeginTime" @change="HRelBeginTimeChange" v-if="hform.HIsTimeFlag==1" :hide-second="true"> @@ -129,7 +129,7 @@ </uni-datetime-picker> </view> </view> <view class="form-item"> <view class="form-item" v-show="false"> <view class="title">完工时间:</view> <view class="right"> <uni-datetime-picker v-model="hform.HRelEndTime" @change="HRelEndTimeChange" v-if="hform.HIsTimeFlag==1" :hide-second="true"> pages/index/index.vue
@@ -309,9 +309,9 @@ }, { img: '../../static/icon/icon8.png', text: '上模单', url: `/pages/MJGL/shangmudan/MouldUpperBill`, id: 35, text: '模具档案查询', url: `/pages/MJGL/Gy_MouldFile/Gy_MouldFileList`, id: 36, hidden: false, }, ], pages/jishikucunchaxun/table.vue
@@ -244,7 +244,8 @@ } }, onLoad() { onLoad(options) { this.hform.HBarCode = options.HMaterNumber || ''; this.getWHInfo() this.getStockPlaceInfo() @@ -253,7 +254,6 @@ }) }, onReady() { // #ifndef MP-WEIXIN let query = uni.createSelectorQuery().in(this) query.select("#scroll-content").boundingClientRect((data) => { this.pageMeta.scrollContentTop = data.top @@ -263,11 +263,6 @@ this.pageMeta.bottomBtnTop = data.top console.log('this.pageMeta.bottomBtnTop: ',this.pageMeta.bottomBtnTop); }).exec() // #endif // #ifdef MP-WEIXIN // 微信不支持 uni.createSelectorQuery().in(this) // #endif }, } </script> uni_modules/zxz-uni-data-select/changelog.md
New file @@ -0,0 +1,49 @@ ## 1.0.20(2024-05-09) 1.修复APP点击下拉框无法关闭 ## 1.0.19(2024-04-29) 1.修复点击多个下拉框无法关闭 2.优化多选类型支持一次选择多个 3.修复小程序点击有个蓝色底 4.优化下拉菜单溢出屏幕底部时改为向上弹出 ## 1.0.15(2023-11-24) 1.优化多选选中样式(tianheng20**qq.com网友提供) 2.优化chang事件(chang事件中将返回所选中的对象) ## 1.0.14(2023-10-25) 优化vue3延时添加未渲染问题,处理37;分号警告问题 ## 1.0.13(2023-10-12) 优化mixinDatacomResData报错和defValue报错 ## 1.0.12(2023-09-27) 修复搜索输入内容的时候下拉框的箭头会跑到文本框前面去 优化当有选中项时不显示清除按钮 ## 1.0.11(2023-09-05) 更换change事件执行顺序 修复多选更改值时未即时更改下拉框选项 修复单选搜索框选中了 修复多选筛选输入时点击其他未清空筛选值 ## 1.0.10(2023-08-29) 修复单选搜索回显问题 ## 1.0.9(2023-08-28) 更新文档 ## 1.0.8(2023-08-28) 更新文档 ## 1.0.7(2023-08-16) 修复组件禁用bug 修复数据回显问题 添加多选搜索功能 ## 1.0.6(2023-08-05) 修复清空值多选下拉列表还是被选中bug ## 1.0.5(2023-07-10) 修复多选初始化异步数据不显示问题 ## 1.0.4(2023-07-07) 修复微信小程序多选显示兼容问题 ## 1.0.3(2023-07-06) 修复bug 多选情况下 初始化之后重新选择第一个不显示 ## 1.0.2(2023-07-06) 更新VUE3兼容 ## 1.0.1(2023-06-30) 添加多选合并功能 ## 1.0.0(2023-06-16) 添加下拉框检索,多选功能,自定义数据 ## 1.0.4(2023-06-16) 添加下拉框检索,多选功能,自定义数据 uni_modules/zxz-uni-data-select/components/zxz-uni-data-select/zxz-uni-data-select.vue
New file @@ -0,0 +1,823 @@ <template> <view class="uni-stat__select"> <!-- hide-on-phone --> <span v-if="label" class="uni-label-text">{{label + ':'}}</span> <view class="uni-stat-box" :class="{'uni-stat__actived': current}"> <view class="uni-select" :style="{height:multiple?'100%':' 35px'}" :class="{'uni-select--disabled':disabled}"> <view class="uni-select__input-box" :style="{height:multiple?'100%':'35px'}" @click="toggleSelector"> <view class="" style="display: flex;flex-wrap: wrap;width: 100%;" v-if="multiple&¤t.length>0"> <view class="tag-calss" v-for="(item,index) in collapseTags?current.slice(0,collapseTagsNum):current" :key="item[dataValue]"> <span class="text">{{item[dataKey]}}</span> <view class="" @click.stop="delItem(item)"> <uni-icons type="clear" style="margin-left: 4px;" color="#c0c4cc" /> </view> </view> <view v-if="current.length>collapseTagsNum&&collapseTags" class="tag-calss"> <span class="text">+{{current.length-collapseTagsNum}}</span> </view> <input v-if="filterable&&!disabled" @input="inputChange" class="uni-select__input-text" type="text" style="font-size: 12px;height: 52rpx;margin-left: 6px;width: auto;" placeholder="请输入" v-model="filterInput"> </view> <view v-else-if="current&¤t.length>0&&!showSelector" class="uni-select__input-text"> {{current}} </view> <input v-else-if="filterable&&showSelector" :focus="isFocus" @input="inputChange" :disabled="disabled" @click.stop="" class="uni-select__input-text" type="text" style="font-size: 12px;position: absolute;z-index: 1;" :placeholder="placeholderOld" v-model="filterInput"> <view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view> <uni-icons v-if="(current.length>0 && clear&&!disabled)||(currentArr.length>0&&clear&&!disabled)" type="clear" color="#c0c4cc" size="24" style="position: absolute;right: 0;" @click="clearVal" /> <uni-icons style="right: 0;position: absolute;" v-else :type="showSelector? 'top' : 'bottom'" size="14" color="#999" /> </view> <view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" /> <view class="uni-select__selector" :class="isDown?'uni-select__selector__down':'uni-select__selector__upwards'" v-if="showSelector"> <view class="uni-popper__arrow"></view> <scroll-view scroll-y="true" class="uni-select__selector-scroll"> <view class="uni-select__selector-empty" v-if="filterMixinDatacomResData.length === 0"> <span>{{emptyTips}}</span> </view> <view v-else :class="['uni-select__selector-item', {'uni-select_selector-item_active' :multiple && currentArr.includes(item[dataValue])}]" style="display: flex;justify-content: space-between;align-items: center;" v-for="(item,index) in filterMixinDatacomResData" :key="index" @click="change(item)"> <span :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</span> <uni-icons v-if="multiple&¤tArr.includes(item[dataValue])" type="checkmarkempty" color="#007aff" /> </view> </scroll-view> </view> </view> </view> </view> </template> <script> /** * DataChecklist 数据选择器 * @description 通过数据渲染的下拉框组件 * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select * @property {String} collapseTagsNum 多选时选中值按文字的形式展示的数量 * @property {String} collapseTags 多选时是否将选中值按文字的形式展示 * @property {String} dataKey 作为 key 唯一标识的键名 * @property {String} dataValue 作为 value 唯一标识的键名 * @property {Array} multiple 是否多选 * @property {Array} filterable 是否开启搜索 * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}] * @property {Boolean} clear 是否可以清空已选项 * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效 * @property {String} label 左侧标题 * @property {String} placeholder 输入框的提示文字 * @property {Boolean} disabled 是否禁用 * @event {Function} change 选中发生变化触发 */ export default { name: "uni-stat-select", mixins: [uniCloud.mixinDatacom || {}], props: { collapseTagsNum: { type: Number, default: 1 }, collapseTags: { type: Boolean, default: false }, dataKey: { type: [String], default: 'text' }, dataValue: { type: [String], default: 'value' }, multiple: { type: Boolean, default: false }, filterable: { type: Boolean, default: false }, localdata: { type: Array, default () { return [] } }, // #ifndef VUE3 value: { type: [String, Number, Array], default: '' }, // #endif // #ifdef VUE3 modelValue: { type: [String, Number, Array], default: '' }, // #endif label: { type: String, default: '' }, placeholder: { type: String, default: '请选择' }, emptyTips: { type: String, default: '无选项' }, clear: { type: Boolean, default: true }, defItem: { type: Number, default: 0 }, disabled: { type: Boolean, default: false }, // 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}" format: { type: String, default: '' }, }, data() { return { showSelector: false, current: [], mixinDatacomResData: [], apps: [], channels: [], cacheKey: "uni-data-select-lastSelectedValue", placeholderOld: "", currentArr: [], filterInput: "", isFocus: false, windowHeight:0, isDown:true,//下拉框是否朝下 }; }, created() { this.windowHeight=uni.getSystemInfoSync().windowHeight if (this.multiple) { // #ifndef VUE3 this.currentArr = this.value || [] // #endif // #ifdef VUE3 this.currentArr = this.modelValue || [] // #endif if (this.current.length > 0) { this.current = [] } // #ifndef VUE3 if (this.value && this.value.length > 0 && this.filterMixinDatacomResData.length > 0) { this.current = this.value.map(item => { let current = this.mixinDatacomResData.find(e => e[this.dataValue] == item ) return { ...current } }) } // #endif // #ifdef VUE3 if (this.modelValue && this.modelValue.length > 0 && this.filterMixinDatacomResData.length > 0) { this.current = this.modelValue.map(item => { let current = this.mixinDatacomResData.find(e => e[this.dataValue] == item ) return { ...current } }) } // #endif } else { // #ifndef VUE3 if (this.value || this.value == 0) { this.current = this.formatItemName(this.filterMixinDatacomResData.find(e => e[this.dataValue] == this.value )) } // #endif // #ifdef VUE3 if (this.modelValue || this.value == 0) { this.current = this.formatItemName(this.filterMixinDatacomResData.find(e => e[this.dataValue] == this.modelValue )) } // #endif } this.placeholderOld = this.placeholder this.debounceGet = this.debounce(() => { this.query(); }, 300); if (this.collection && !this.localdata.length) { this.debounceGet(); } }, computed: { filterMixinDatacomResData() { if (this.filterable && this.filterInput) { return this.mixinDatacomResData.filter(e => e[this.dataKey].includes(this.filterInput)) } else { return this.mixinDatacomResData } }, typePlaceholder() { const text = { 'opendb-stat-app-versions': '版本', 'opendb-app-channels': '渠道', 'opendb-app-list': '应用' } const common = this.placeholder const placeholder = text[this.collection] return placeholder ? common + placeholder : common }, valueCom() { // #ifdef VUE3 return this.modelValue; // #endif // #ifndef VUE3 return this.value; // #endif } }, watch: { localdata: { immediate: true, handler(val, old) { if (Array.isArray(val) && old !== val) { this.mixinDatacomResData = val || [] } } }, valueCom: { handler(newVal, oldVal) { // console.log(newVal, oldVal); this.initDefVal() }, deep: true, immediate: true }, mixinDatacomResData: { immediate: true, handler(val) { if (val.length) { this.initDefVal() } } }, }, methods: { getIsDown(){ const query = uni.createSelectorQuery().in(this); const _this=this query .select(".uni-stat-box") .boundingClientRect((data) => { if(_this.windowHeight-data.top>200){ _this.isDown=true }else{ _this.isDown=false } }) .exec(); }, debounce(fn, time = 100) { let timer = null return function(...args) { if (timer) clearTimeout(timer) timer = setTimeout(() => { fn.apply(this, args) }, time) } }, // 执行数据库查询 query() { this.mixinDatacomEasyGet(); }, // 监听查询条件变更事件 onMixinDatacomPropsChange() { if (this.collection) { this.debounceGet(); } }, initDefVal() { let defValue = '' if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) { defValue = this.valueCom } else { let strogeValue if (this.collection) { strogeValue = this.getCache() } if (strogeValue || strogeValue === 0) { defValue = strogeValue } else { let defItem = '' if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) { defItem = this.mixinDatacomResData[this.defItem - 1][this.dataValue] } defValue = defItem } if (defValue || defValue === 0) { this.emit(defValue) } } if (this.multiple) { const mixinDatacomResData = this.mixinDatacomResData || [] if (!defValue) defValue = [] this.current = defValue.map(item => { const current = mixinDatacomResData.find(e => { return e[this.dataValue] == item }) return { ...current } }) this.currentArr = this.current.map(e => e[this.dataValue]) if (defValue.length < 1) { this.currentArr = [] } } else { const def = this.mixinDatacomResData.find(item => item[this.dataValue] === defValue) this.current = def ? this.formatItemName(def) : '' } }, /** * @param {[String, Number]} value * 判断用户给的 value 是否同时为禁用状态 */ isDisabled(value) { let isDisabled = false; this.mixinDatacomResData.forEach(item => { if (item[this.dataValue] === value) { isDisabled = item.disable } }) return isDisabled; }, inputChange(e) { this.$emit('inputChange', e.detail.value) }, clearVal() { if (this.disabled) { return } if (this.multiple) { this.current = [] this.currentArr = [] this.emit([]) } else { this.current = "" this.currentArr = [] this.emit('') } if (this.collection) { this.removeCache() } this.placeholderOld = this.placeholder this.filterInput = "" }, change(item) { if (!item.disable) { if (this.multiple) { if (!this.current) { this.current = [] } if (!this.currentArr) { this.currentArr = [] } if (this.currentArr.includes(item[this.dataValue])) { let index = this.current.findIndex(e => { return e[this.dataValue] == item[this.dataValue] }) this.current.splice(index, 1) this.currentArr.splice(index, 1) this.emit(this.current) } else { this.current.push(item) this.currentArr.push(item[this.dataValue]) this.emit(this.current) } this.filterInput = "" } else { this.showSelector = false this.current = this.formatItemName(item) if (this.filterable) { this.filterInput = item[this.dataKey] } this.emit(item[this.dataValue]) } } }, delItem(item) { if (this.disabled) { return } if (this.currentArr.includes(item[this.dataValue])) { let index = this.current.findIndex(e => { return e[this.dataValue] == item[this.dataValue] }) this.current.splice(index, 1) this.currentArr.splice(index, 1) this.emit(this.current) } }, emit(val) { if (this.multiple) { this.$emit('input', this.currentArr) this.$emit('update:modelValue', this.currentArr) const currentArr = this.mixinDatacomResData.filter(item => this.currentArr.includes(item[this .dataValue])) this.$emit('change', currentArr) } else { this.$emit('input', val) this.$emit('update:modelValue', val) const current = this.mixinDatacomResData.find(item => val == item[this.dataValue]) console.log(current); this.$emit('change', current) } if (this.collection) { this.setCache(val); } }, toggleSelector() { if (this.disabled) { return } // if (this.filterable && this.filterInput && this.mixinDatacomResData.findIndex(e => { // return e[this.dataKey] == this // .filterInput // }) < 0) { // if (!this.multiple) { // this.filterInput = "" // } // } this.getIsDown() this.showSelector = !this.showSelector this.isFocus = this.showSelector if (this.filterable && this.current && this.showSelector) { if (!this.multiple) { this.placeholderOld = this.current // this.filterInput = "" } } else if (this.filterable && !this.current && !this.showSelector) { if (this.placeholderOld != this.placeholder) { if (!this.multiple) { this.current = this.placeholderOld } } } this.filterInput = "" }, formatItemName(item) { if (!item) { return "" } let text = item[this.dataKey] let value = item[this.dataValue] let { channel_code } = item channel_code = channel_code ? `(${channel_code})` : '' if (this.format) { // 格式化输出 let str = ""; str = this.format; for (let key in item) { str = str.replace(new RegExp(`{${key}}`, "g"), item[key]); } return str; } else { return this.collection.indexOf('app-list') > 0 ? `${text}(${value})` : ( text ? text : `未命名${channel_code}` ) } }, // 获取当前加载的数据 getLoadData() { return this.mixinDatacomResData; }, // 获取当前缓存key getCurrentCacheKey() { return this.collection; }, // 获取缓存 getCache(name = this.getCurrentCacheKey()) { let cacheData = uni.getStorageSync(this.cacheKey) || {}; return cacheData[name]; }, // 设置缓存 setCache(value, name = this.getCurrentCacheKey()) { let cacheData = uni.getStorageSync(this.cacheKey) || {}; cacheData[name] = value; uni.setStorageSync(this.cacheKey, cacheData); }, // 删除缓存 removeCache(name = this.getCurrentCacheKey()) { let cacheData = uni.getStorageSync(this.cacheKey) || {}; delete cacheData[name]; uni.setStorageSync(this.cacheKey, cacheData); }, } } </script> <style lang="scss"> $uni-base-color: #6a6a6a !default; $uni-main-color: #333 !default; $uni-secondary-color: #909399 !default; $uni-border-3: #e5e5e5; /* #ifndef APP-NVUE */ @media screen and (max-width: 500px) { .hide-on-phone { display: none; } } /* #endif */ .uni-stat__select { display: flex; align-items: center; // padding: 15px; // cursor: pointer; width: 100%; flex: 1; box-sizing: border-box; } .uni-stat-box { width: 100%; flex: 1; } .uni-stat__actived { width: 100%; flex: 1; // outline: 1px solid #2979ff; } .uni-label-text { font-size: 14px; font-weight: bold; color: $uni-base-color; margin: auto 0; margin-right: 5px; } .uni-select { font-size: 14px; border: 1px solid $uni-border-3; box-sizing: border-box; border-radius: 4px; padding: 0 5px; padding-left: 10px; position: relative; /* #ifndef APP-NVUE */ display: flex; user-select: none; /* #endif */ flex-direction: row; align-items: center; border-bottom: solid 1px $uni-border-3; width: 100%; flex: 1; height: 35px; min-height: 35px; &--disabled { background-color: #f5f7fa; cursor: not-allowed; } } .uni-select__label { font-size: 16px; // line-height: 22px; min-height: 35px; height: 35px; padding-right: 10px; color: $uni-secondary-color; } .uni-select__input-box { width: 100%; height: 35px; position: relative; /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex: 1; flex-direction: row; align-items: center; .tag-calss { font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; font-weight: 400; -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent; font-size: 12px; border: 1px solid #d9ecff; border-radius: 4px; white-space: nowrap; height: 24px; padding: 0 4px 0px 8px; line-height: 22px; box-sizing: border-box; margin: 2px 0 2px 6px; display: flex; max-width: 100%; align-items: center; background-color: #f4f4f5; border-color: #e9e9eb; color: #909399; .text { font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; font-weight: 400; -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent; font-size: 12px; white-space: nowrap; line-height: 22px; color: #909399; overflow: hidden; text-overflow: ellipsis; } } } .uni-select__input { flex: 1; font-size: 14px; height: 22px; line-height: 22px; } .uni-select__input-plac { font-size: 14px; color: $uni-secondary-color; } .uni-select__selector__down { top: calc(100% + 12px); .uni-popper__arrow { transform: rotateX(0deg); top: -6px; } } .uni-select__selector__upwards { bottom: calc(100% + 12px); .uni-popper__arrow { transform: rotateX(180deg); bottom: -6px; } } .uni-select__selector { /* #ifndef APP-NVUE */ box-sizing: border-box; /* #endif */ position: absolute; left: 0; width: 100%; background-color: #FFFFFF; border: 1px solid #EBEEF5; border-radius: 6px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); z-index: 3; padding: 4px 0; } .uni-select__selector-scroll { /* #ifndef APP-NVUE */ max-height: 200px; box-sizing: border-box; /* #endif */ } .uni-select__selector-empty, .uni-select__selector-item { /* #ifndef APP-NVUE */ display: flex; // cursor: pointer; /* #endif */ line-height: 35px; font-size: 14px; text-align: center; /* border-bottom: solid 1px $uni-border-3; */ padding: 0px 10px; } .uni-select__selector-item:hover { background-color: #f9f9f9; } .uni-select__selector-empty:last-child, .uni-select__selector-item:last-child { /* #ifndef APP-NVUE */ border-bottom: none; /* #endif */ } .uni-select_selector-item_active { color: #409eff; font-weight: bold; background-color: #f5f7fa; border-radius: 3px; } .uni-select__selector__disabled { opacity: 0.4; cursor: default; } /* picker 弹出层通用的指示小三角 */ .uni-popper__arrow, .uni-popper__arrow::after { position: absolute; display: block; width: 0; height: 0; border-color: transparent; border-style: solid; border-width: 6px; } .uni-popper__arrow { filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); left: 10%; margin-right: 3px; border-top-width: 0; border-bottom-color: #EBEEF5; } .uni-popper__arrow::after { content: " "; top: 1px; margin-left: -6px; border-top-width: 0; border-bottom-color: #fff; } .uni-select__input-text { // width: 280px; width: 90%; color: $uni-main-color; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; overflow: hidden; } .uni-select__input-placeholder { color: $uni-base-color; font-size: 12px; } .uni-select--mask { position: fixed; top: 0; bottom: 0; right: 0; left: 0; z-index: 2; } </style> uni_modules/zxz-uni-data-select/package.json
New file @@ -0,0 +1,86 @@ { "id": "zxz-uni-data-select", "displayName": "zxz-uni-data-select 下拉框选择器(添加下拉框检索,多选功能,多选搜索功能,自定义数据)", "version": "1.0.20", "description": "通过数据驱动的下拉框选择器(添加下拉框检索,多选功能,多选搜索功能,自定义数据)", "keywords": [ "uni-ui", "select", "uni-data-select", "下拉框", "下拉选择框" ], "repository": "", "engines": { "HBuilderX": "^3.1.1" }, "directories": { "example": "../../temps/example_temps" }, "dcloudext": { "sale": { "regular": { "price": "0.00" }, "sourcecode": { "price": "0.00" } }, "contact": { "qq": "" }, "declaration": { "ads": "无", "data": "无", "permissions": "无" }, "npmurl": "", "type": "component-vue" }, "uni_modules": { "dependencies": ["uni-load-more"], "encrypt": [], "platforms": { "cloud": { "tcb": "y", "aliyun": "y", "alipay": "n" }, "client": { "App": { "app-vue": "y", "app-nvue": "y" }, "H5-mobile": { "Safari": "y", "Android Browser": "y", "微信浏览器(Android)": "y", "QQ浏览器(Android)": "y" }, "H5-pc": { "Chrome": "y", "IE": "y", "Edge": "y", "Firefox": "y", "Safari": "y" }, "小程序": { "微信": "y", "阿里": "y", "百度": "y", "字节跳动": "y", "QQ": "y", "京东": "y" }, "快应用": { "华为": "y", "联盟": "y" }, "Vue": { "vue2": "y", "vue3": "y" } } } } } uni_modules/zxz-uni-data-select/readme.md
New file @@ -0,0 +1,37 @@ ## DataSelect 下拉框选择器 <strong style="color:orangered;"><em>先导入示例项目</em></strong> 看看是否满足需求,然后再下载插件,有问题可以加微<strong style="color:orangered;"><em>weiyila520</em></strong> > **组件名:zxz-uni-data-select** > 代码块: `zxz-uni-data-select` 本插件基于官方插件 [uni-data-select](https://ext.dcloud.net.cn/plugin?id=7993) 进行二次开发拓展功能,支持uni-data-select本身功能不变(表单验证等) <h1>拓展功能</h1> <ol> <li>支持多选功能</li> <li>支持选项禁用</li> <li>支持自定义显示值</li> <li>支持搜索</li> <li>支持多选时将选中值按文字形式展示</li> <li>支持下拉菜单溢出屏幕底部时自动改为向上弹出</li> <li>监听搜索输入事件</li> </ol> <h2>API</h2> ### zxz-uni-data-select Props | 属性名 | 类型 | 默认值 | 说明 | | - | - | - | - | | v-model | String、Array、Number |- | 选中项绑定值 | | multiple | Boolean | false | 是否多选 | | disabled | Boolean |false | 是否禁用 | | dataKey | String |"key" | 作为 key 唯一标识的键名 | | dataValue | String | "value" | 作为 value 唯一标识的键名 | | filterable | Boolean | false | 是否开启搜索 | | collapseTags | Boolean | false | 多选时是否将选中值按文字的形式展示 | |collapseTagsNum|Number | 1 | 多选时选中值按文字的形式展示的数量 | | localdata | Array |- | 下拉列表本地数据 | |label | String | - | 左侧标题 | |placeholder | String | "请选择" | 输入框的提示文字 | |emptyTips | String |"无选项" | 无选项提示 | |clear | Boolean | true | 是否清空 | |format | String | - | 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}"| |@inputChange | event | event(String) | 搜索输入事件 |