Browse Source

修改重复扫描没有提示 2024/7/12 13:56:17

hella_vue3
zhang_li 3 months ago
parent
commit
305a135735
  1. 2
      src/mycomponents/detail/comDetailCard.vue
  2. 4
      src/pages/package/record/overPackageRecord.vue
  3. 282
      src/pages/package/record/splitPackageRecord.vue
  4. 19
      src/pages/productPutaway/job/productPutawayDetail.vue
  5. 9
      src/pages/purchaseReturn/coms/comReturnJobCard.vue
  6. 4
      src/pages/purchaseReturn/job/returnDetail.vue
  7. 2
      src/pages/purchaseReturn/job/returnJob.vue
  8. 5
      src/pages/repleinsh/record/directRepleinshRecord.vue
  9. 8
      src/uni_modules/wz-select-popup/changelog.md
  10. 22
      src/uni_modules/wz-select-popup/components/wz-select-popup/util/defaultConfig.js
  11. 74
      src/uni_modules/wz-select-popup/components/wz-select-popup/util/index.js
  12. 130
      src/uni_modules/wz-select-popup/components/wz-select-popup/wz-list.vue
  13. 90
      src/uni_modules/wz-select-popup/components/wz-select-popup/wz-search.vue
  14. 357
      src/uni_modules/wz-select-popup/components/wz-select-popup/wz-select-popup.vue
  15. 82
      src/uni_modules/wz-select-popup/package.json

2
src/mycomponents/detail/comDetailCard.vue

@ -94,7 +94,7 @@ onMounted(() => {
detailOptions.value = getDetailOption()
}
if (scanOptions.value.length == 0) {
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, props.settingParam.allowModifyLocation)
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false)
}
nextTick((res) => {
collapse.value.init()

4
src/pages/package/record/overPackageRecord.vue

@ -215,7 +215,7 @@ const setData = (result) => {
scanPopupGetFocus()
} else {
const detail = item.subList.find((r) => {
if (r.packingNumber == balance.packingNumber && r.batch == balance.batch && r.locationCode == balance.locationCode && r.inventoryStatus == balance.inventoryStatus) {
if (r.packingNumber == pack.number && r.batch == balance.batch && r.locationCode == balance.locationCode && r.inventoryStatus == balance.inventoryStatus) {
return r
}
})
@ -228,7 +228,7 @@ const setData = (result) => {
item.subList.push(newDetail)
scanPopupGetFocus()
} else if (detail.scaned == true) {
showErrorMessage(`箱码[${balance.packingNumber}批次[${balance.batch}]已经在列表中`)
showErrorMessage(`箱码[${detail.packingNumber}批次[${balance.batch}]已经在列表中`)
}
}
calcHandleQty1()

282
src/pages/package/record/splitPackageRecord.vue

@ -1,7 +1,7 @@
<template>
<view class="page-wraper">
<view class="">
<com-blank-view @goScan='getBusinessType' v-if="detailSource.length==0"></com-blank-view>
<com-blank-view @goScan="getBusinessType" v-if="detailSource.length == 0"></com-blank-view>
</view>
<view class="page-wraper" v-if="detailSource.length > 0">
@ -9,73 +9,51 @@
<scroll-view scroll-y="true" class="page-main-scroll">
<view class="detail-list" v-for="(item, index) in detailSource" :key="item.id">
<view class="">
<record-com-detail-card :dataContent="item" @removeItem="removeItem(index,item)"
@updateData="updateData" @removePack='updateData' :isShowToLocation="false">
</record-com-detail-card>
<record-com-detail-card :dataContent="item" @removeItem="removeItem(index, item)" @updateData="updateData" @removePack="updateData" :isShowToLocation="false"> </record-com-detail-card>
</view>
</view>
<view class="uni-flex uni-row" style="margin-left: 30rpx;margin-top: 10rpx; ">
<text style="font-size: 35rpx; margin-right: 20rpx;">拆出数量 :</text>
<uni-number-box @change="calcQty($event,splitCount)" :value="splitCount">
</uni-number-box>
<view class="uni-flex uni-row" style="margin-left: 30rpx; margin-top: 10rpx">
<text style="font-size: 35rpx; margin-right: 20rpx">拆出数量 :</text>
<uni-number-box @change="calcQty($event, splitCount)" :value="splitCount"> </uni-number-box>
<uom :uom="detailSource[0].uom"></uom>
</view>
</scroll-view>
</view>
<view class="page-footer">
<view class="uni-flex u-col-center space-between padding_10"
style="background-color:ghostwhite; width: 100%; ">
<view class="">
</view>
<view class="uni-flex u-col-center space-between padding_10" style="background-color: ghostwhite; width: 100%">
<view class=""> </view>
<view class="uni-flex uni-row">
<button class="btn_single_commit" hover-class="btn_commit_after" @click="commit">提交</button>
</view>
</view>
</view>
<win-scan-button @goScan='openScanPopup'></win-scan-button>
<win-scan-button @goScan="openScanPopup"></win-scan-button>
</view>
<winComScanBalance ref="scanPopup" @getBalance='getScanResult' :bussinessCode="typeCode">
</winComScanBalance>
<winComScanBalance ref="scanPopup" @getBalance="getScanResult" :bussinessCode="typeCode"> </winComScanBalance>
<comMessage ref="comMessage"></comMessage>
</view>
</template>
<script>
import {
goHome,
showConfirmMsg
} from '@/common/basic.js';
import {
splitPackageRecordSubmit
} from '@/api/request2.js';
import {
calc
} from '@/common/calc.js';
import {
getInventoryStatusDesc,
getDirectoryItemArray
} from '@/common/directory.js';
import {
getBusinessType,
createItemInfo,
createDetailInfo,
calcHandleQty
} from '@/common/record.js';
import { goHome, showConfirmMsg } from '@/common/basic.js'
import { splitPackageRecordSubmit } from '@/api/request2.js'
import { calc } from '@/common/calc.js'
import { getInventoryStatusDesc, getDirectoryItemArray } from '@/common/directory.js'
import { getBusinessType, createItemInfo, createDetailInfo, calcHandleQty } from '@/common/record.js'
import winScanButton from '@/mycomponents/scan/winScanButton.vue'
import winScanPack from '@/mycomponents/scan/winScanPack.vue'
import requiredLocation from '@/mycomponents/location/requiredLocation.vue'
import recordComDetailCard from '@/mycomponents/record/recordComDetailCard.vue'
import comBlankView from '@/mycomponents/common/comBlankView.vue'
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue"
import winScanPackAndLocation from "@/mycomponents/scan/winScanPackAndLocation.vue"
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue'
import winScanPackAndLocation from '@/mycomponents/scan/winScanPackAndLocation.vue'
import recommendBalance from '@/mycomponents/balance/recommendBalance.vue'
import comPackageRecord from '@/pages/package/coms/comPackageRecord.vue'
import winComScanBalance from '@/mycomponents/scan/winComScanBalance.vue'
@ -99,43 +77,30 @@
return {
id: '',
detailSource: [], //
fromLocationCode: "",
toLocationCode: "",
fromLocationCode: '',
toLocationCode: '',
fromLocationAreaTypeList: [],
inInventoryStatus: "", //
outInventoryStatus: "", //
inInventoryStatus: '', //
outInventoryStatus: '', //
businessType: {},
dataContent: {},
currentItemCode: "",
toPackingNumber: "",
itemCode:"",
currentItemCode: '',
toPackingNumber: '',
itemCode: '',
splitCount: 1,
typeCode:"SplitPackage"
};
typeCode: 'SplitPackage'
}
},
onLoad(option) {
<<<<<<< Updated upstream
uni.setNavigationBarTitle({
title: option.title
})
var typeCode = "SplitPackage"
getBusinessType(typeCode, res => {
if (res.success) {
this.businessType = res.businessType;
this.fromLocationAreaTypeList = res.fromLocationAreaTypeList;
this.showFromLocationPopup();
} else {
this.showErrorMessage(res.message)
}
});
=======
this.getBusinessType();
>>>>>>> Stashed changes
this.getBusinessType()
},
//
onNavigationBarButtonTap(e) {
if (e.index === 0) {
goHome();
goHome()
}
},
//
@ -146,28 +111,28 @@
mounted() {},
methods: {
getBusinessType() {
getBusinessType(this.typeCode, res => {
getBusinessType(this.typeCode, (res) => {
if (res.success) {
this.businessType = res.businessType;
this.fromInventoryStatuses = getDirectoryItemArray(res.fromInventoryStatuses);
this.businessType = res.businessType
this.fromInventoryStatuses = getDirectoryItemArray(res.fromInventoryStatuses)
this.fromLocationAreaTypeList = res.fromLocationAreaTypeList
this.openScanPopup();
this.openScanPopup()
} else {
this.showErrorMessage(res.message)
}
});
})
},
openScanPopup() {
if (this.businessType) {
if (this.detailSource.length > 0) {
showConfirmMsg("拆包信息还没提交,是否要重新扫描?",res=>{
showConfirmMsg('拆包信息还没提交,是否要重新扫描?', (res) => {
if (res) {
this.clearData();
this.$refs.scanPopup.openScanPopup(this.businessType);
this.clearData()
this.$refs.scanPopup.openScanPopup(this.businessType)
}
})
} else {
this.$refs.scanPopup.openScanPopup(this.businessType);
this.$refs.scanPopup.openScanPopup(this.businessType)
}
} else {
this.getBusinessType()
@ -175,82 +140,74 @@
},
getScanResult(result) {
this.setData(result);
this.setData(result)
},
setData(result) {
let balance = result.balance;
let label = result.label;
let pack = result.package;
this.fromPackUnit = pack.packUnit;
this.fromPack = pack;
const { balance } = result
const { label } = result
const pack = result.package
this.fromPackUnit = pack.packUnit
this.fromPack = pack
if (this.fromLocationCode && this.fromLocationCode != balance.locationCode) {
this.showErrorMessage("箱码[" + balance.packingNumber + "批次[" + balance.batch + "]在库位[" + this
.fromLocationCode + "]没有库存余额")
return;
this.showErrorMessage(`箱码[${balance.packingNumber}批次[${balance.batch}]在库位[${this.fromLocationCode}]没有库存余额`)
return
}
var item = this.detailSource.find(res => {
const item = this.detailSource.find((res) => {
if (res.itemCode == balance.itemCode) {
return res
}
})
if (item == undefined) {
if (this.itemCode != "" && this.itemCode != balance.itemCode) {
this.showErrorMessage("请扫描物料为【" + this.itemCode + "】的箱码")
return;
if (this.itemCode != '' && this.itemCode != balance.itemCode) {
this.showErrorMessage(`请扫描物料为【${this.itemCode}】的箱码`)
return
}
var itemp = createItemInfo(balance, pack);
const itemp = createItemInfo(balance, pack)
itemp.handleQty = 0
let newDetail = createDetailInfo(balance, pack); //
const newDetail = createDetailInfo(balance, pack) //
newDetail.handleQty = 0
newDetail.scaned = false
itemp.subList.push(newDetail);
itemp.subList.push(newDetail)
this.detailSource.push(itemp)
this.itemCode = balance.itemCode;
this.itemCode = balance.itemCode
this.fromLocationCode = balance.locationCode
this.closeScanPopup()
} else {
var detail = item.subList.find(r => {
if (r.packingNumber == balance.packingNumber &&
r.batch == balance.batch &&
r.locationCode == balance.locationCode &&
r.inventoryStatus == balance.inventoryStatus) {
return r;
const detail = item.subList.find((r) => {
if (r.packingNumber == balance.packingNumber && r.batch == balance.batch && r.locationCode == balance.locationCode && r.inventoryStatus == balance.inventoryStatus) {
return r
}
})
if (detail == undefined) {
let newDetail = createDetailInfo(balance, pack);
const newDetail = createDetailInfo(balance, pack)
newDetail.handleQty = 0
item.subList.push(newDetail);
item.subList.push(newDetail)
this.closeScanPopup()
} else {
if (detail.scaned == true) {
this.showErrorMessage("箱码[" + balance.packingNumber + "批次[" + balance.batch + "]已经在列表中")
}
} else if (detail.scaned == true) {
this.showErrorMessage(`箱码[${balance.packingNumber}批次[${balance.batch}]已经在列表中`)
}
}
this.calcHandleQty();
this.calcHandleQty()
},
calcHandleQty() {
calcHandleQty(this.detailSource)
this.$forceUpdate();
this.$forceUpdate()
},
showErrorMessage(message) {
this.$refs.comMessage.showErrorMessage(message, res => {
this.$refs.comMessage.showErrorMessage(message, (res) => {
if (res) {
}
});
})
},
updateData() {
this.calcHandleQty();
for (var i = 0; i < this.detailSource.length; i++) {
let item = this.detailSource[i];
this.calcHandleQty()
for (let i = 0; i < this.detailSource.length; i++) {
const item = this.detailSource[i]
if (item.qty == 0) {
this.detailSource.splice(i, 1)
}
@ -262,34 +219,33 @@
closeScanPopup() {
if (this.$refs.scanPopup != undefined) {
this.$refs.scanPopup.closeScanPopup();
this.$refs.scanPopup.closeScanPopup()
}
},
scanPopupGetFocus() {
if (this.$refs.scanPopup != undefined) {
this.$refs.scanPopup.getfocus();
this.$refs.scanPopup.getfocus()
}
},
commit() {
if (this.detailSource.length > 0 && this.detailSource[0].subList.length > 0) {
if (this.splitCount == 0) {
this.showErrorMessage("拆出数量不能等于0")
return;
this.showErrorMessage('拆出数量不能等于0')
return
}
if (this.splitCount > this.detailSource[0].qty) {
this.showErrorMessage("拆出数量不能大于库存数量")
return;
this.showErrorMessage('拆出数量不能大于库存数量')
return
}
uni.showLoading({
title: "提交中....",
title: '提交中....',
mask: true
});
})
var params = this.setParams();
console.log("提交" + JSON.stringify(params))
const params = this.setParams()
console.log(`提交${JSON.stringify(params)}`)
// splitPackageRecordSubmit(params).then(res => {
// uni.hideLoading()
// if (res.data) {
@ -323,96 +279,92 @@
// this.showErrorMessage(error)
// })
} else {
this.showErrorMessage("没有要提交的数据")
this.showErrorMessage('没有要提交的数据')
}
},
setParams() {
var subList = []
var creator = this.$store.state.user.id
this.detailSource.forEach(item => {
item.subList.forEach(detail => {
var subItem = {};
const subList = []
const creator = this.$store.state.user.id
this.detailSource.forEach((item) => {
item.subList.forEach((detail) => {
const subItem = {}
Object.assign(subItem, detail)
subItem.itemCode = subItem.itemCode;
subItem.itemName = detail.package.itemName;
subItem.itemDesc1 = detail.package.itemDesc1;
subItem.itemDesc2 = detail.package.itemDesc2;
subItem.itemCode = subItem.itemCode
subItem.itemName = detail.package.itemName
subItem.itemDesc1 = detail.package.itemDesc1
subItem.itemDesc2 = detail.package.itemDesc2
subItem.fromInventoryStatus = subItem.inventoryStatus;
subItem.toInventoryStatus = subItem.inventoryStatus;
subItem.fromInventoryStatus = subItem.inventoryStatus
subItem.toInventoryStatus = subItem.inventoryStatus
subItem.fromQty = subItem.qty
subItem.toQty = subItem.qty
subItem.fromPackingNumber = subItem.packingNumber;
subItem.toPackingNumber = subItem.packingNumber;
subItem.fromPackingNumber = subItem.packingNumber
subItem.toPackingNumber = subItem.packingNumber
subItem.fromBatch = subItem.batch;
subItem.toBatch = subItem.batch;
subItem.fromLocationCode = subItem.fromLocationCode;
subItem.package = ""
subItem.Records = ""
subItem.fromBatch = subItem.batch
subItem.toBatch = subItem.batch
subItem.fromLocationCode = subItem.fromLocationCode
subItem.package = ''
subItem.Records = ''
subList.push(subItem)
})
})
this.dataContent.subList = subList;
this.dataContent.creator = creator;
return this.dataContent;
this.dataContent.subList = subList
this.dataContent.creator = creator
return this.dataContent
},
showMessage(message) {
this.$refs.comMessage.showMessage(message, res => {
if (res) {}
});
this.$refs.comMessage.showMessage(message, (res) => {
if (res) {
}
})
},
showScanMessage(message) {
this.$refs.comMessage.showScanMessage(message);
this.$refs.comMessage.showScanMessage(message)
},
afterCloseMessage() {
this.scanPopupGetFocus();
this.scanPopupGetFocus()
},
closeScanMessage() {
this.scanPopupGetFocus();
this.scanPopupGetFocus()
},
showCommitSuccessMessage(hint, pointData) {
this.$refs.comMessage.showSuccessMessage(hint, res => {
this.clearData();
this.$refs.comMessage.showSuccessMessage(hint, (res) => {
this.clearData()
if (pointData.length > 0) {
uni.navigateTo({
url: `/pages/point/index?points=${JSON.stringify(pointData)}`
});
})
}
})
},
clearData() {
this.detailSource = []
this.fromLocationCode = '';
this.currentItemCode = ""
this.fromLocationCode = ''
this.currentItemCode = ''
this.dataContent = {}
this.itemCode=""
this.itemCode = ''
this.splitCount = 1
},
calcQty(val) {
this.splitCount =val;
this.splitCount = val
// if(val<=0){
// this.showErrorMessage("0")
// }
},
}
}
}
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>

19
src/pages/productPutaway/job/productPutawayDetail.vue

@ -274,9 +274,26 @@ const getScanResult = (result) => {
} else if (!itemDetail.cancleScanedHiht && itemDetail.scaned) {
showErrorMessage(`箱码【${packingNumber}】,批次【${batch}】库位【${result.fromLocationCode}】已经扫描`)
} else {
// itemDetail.cancleScanedHiht = false
// addDetail(itemDetail, result)
// return
//
const itemStatus = getInventoryStatusName(itemDetail.inventoryStatus)
const balanceStatus = getInventoryStatusName(result.balance.inventoryStatus)
if (itemDetail.inventoryStatus != result.balance.inventoryStatus) {
// if (this.jobContent.allowModifyInventoryStatus == "TRUE") {
showQuestionMessage(`实际库存状态[${balanceStatus}]与推荐库存状态[${itemStatus}]不一致,是否继续上架?`, (res) => {
if (res) {
itemDetail.cancleScanedHiht = false
addDetail(itemDetail, result)
return
} else {
scanPopupGetFocus()
}
})
} else {
itemDetail.cancleScanedHiht = false
addDetail(itemDetail, result)
}
}
}
} catch (e) {

9
src/pages/purchaseReturn/coms/comReturnJobCard.vue

@ -7,14 +7,17 @@
<script setup lang="ts">
import jobComMainCard from '@/mycomponents/job/jobComMainCard.vue'
import jobComMainDetailCard from '@/mycomponents/job/jobComMainDetailCard.vue'
const props = defineProps({
dataContent: {
type: Object,
default: {}
},
isShowToLocation: {
type: Boolean,
default: true
}
})
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

4
src/pages/purchaseReturn/job/returnDetail.vue

@ -210,6 +210,10 @@ const getScanResult = (result) => {
itemDetail.scaned = true
itemDetail.handleQty = Number(result.label.qty)
itemDetail.toInventoryStatus = itemDetail.inventoryStatus
itemDetail.balance = {
packQty: Number(result.package.packQty),
uom: result.package.uom
}
calcHandleQty1()
}
scanPopupGetFocus()

2
src/pages/purchaseReturn/job/returnJob.vue

@ -4,7 +4,7 @@
<job-filter ref="filter" otherTitle="ASN" @switchChangeToday="switchChangeToday" @switchChangeWait="switchChangeWait" @onScanNumber="getScanNumber" @onScanAsnNumber="getScanAsnNumber" :checkedToday="checkedToday" :checkedWaitTask="checkedWaitTask"> </job-filter>
<view v-if="jobList.length > 0" class="u-m-20">
<u-swipe-action :show="item.show" :index="index" v-for="(item, index) in jobList" :key="index" :options="item.status == '2' ? detailGiveupOptions : detailOptions" bg-color="rgba(255,255,255,0)" class="u-m-b-20" @click="swipeClick">
<com-return-job-card :dataContent="item" @click="openJobDetail(item)"></com-return-job-card>
<com-return-job-card :dataContent="item" @click="openJobDetail(item)" :isShowToLocation="false"></com-return-job-card>
</u-swipe-action>
<return-job-list-popup ref="jobListPopup" @selectedItem="selectedItem"></return-job-list-popup>
<return-info-popup ref="jobInfoPopup"></return-info-popup>

5
src/pages/repleinsh/record/directRepleinshRecord.vue

@ -206,7 +206,7 @@ const setData = (result) => {
fromLocationCode.value = balance.locationCode.scanPopupGetFocus()
} else {
const detail = item.subList.find((r) => {
if (r.packingNumber == balance.packingNumber && r.batch == balance.batch && r.locationCode == balance.locationCode && r.inventoryStatus == balance.inventoryStatus) {
if (r.packingNumber == pack.number && r.batch == balance.batch && r.locationCode == balance.locationCode && r.inventoryStatus == balance.inventoryStatus) {
return r
}
})
@ -222,7 +222,7 @@ const setData = (result) => {
item.subList.push(newDetail)
scanPopupGetFocus()
} else if (detail.scaned == true) {
showErrorMessage(`箱码[${balance.packingNumber}批次[${balance.batch}]已经在列表中`)
showErrorMessage(`箱码[${detail.packingNumber}批次[${balance.batch}]已经在列表中`)
}
}
calcHandleQty(detailSource.value)
@ -379,6 +379,7 @@ const showMessage = (message) => {
const showErrorMessage = (message) => {
comMessageRef.value.showErrorMessage(message, (res) => {
if (res) {
scanPopupGetFocus()
}
})
}

8
src/uni_modules/wz-select-popup/changelog.md

@ -0,0 +1,8 @@
## 1.0.11(2023-11-15)
reqFun只允许传入Promise
## 1.0.10(2023-11-13)
去除默认值
## 1.0.1(2023-11-13)
更新插件依赖
## 1.0.0(2023-11-13)
第一次发布

22
src/uni_modules/wz-select-popup/components/wz-select-popup/util/defaultConfig.js

@ -0,0 +1,22 @@
export default {
mode: 'radio', //radio checkbox 单选、多选
showType: 'text', //暂时不用 text image 纯文字、图文
selected: '', //已选中的
dataList: null, //如果dataList传入了数组则直接使用传入的数组渲染,无需再配置proxyConfig
proxyConfig: { //组件内部代理请求数据配置
reqFun: Promise.resolve(), //请求方法
localPaging: false //前端本地分页,如果使用的是dataList默认是本地分页
},
page: { //如果是组件内部代理请求会把page的值加入到请求参数里
pageIndex: 1, //当前页
pageSize: 20 //页大小
},
search: {
type: 'local', //搜索的类型,local本地搜索, remote向服务器请求。只有使用proxyConfig.reqFun请求才能配置为remote
},
fields: { //显示的key,value
label: 'name',
value: 'code',
image: 'image', //暂时不用
}
}

74
src/uni_modules/wz-select-popup/components/wz-select-popup/util/index.js

@ -0,0 +1,74 @@
/**深度合并对象*/
export const deepMerge = function(target = {}, source = {}) {
target = deepClone(target); //深度克隆
if (typeof target !== 'object' || typeof source !== 'object') return false; //判断类型
for (let prop in source) {
if (!source.hasOwnProperty(prop)) continue; //检测属性是否为对象的自有属性
if (prop in target) { //prop 中是否有 target 属性
if (typeof target[prop] !== 'object') {
target[prop] = source[prop];
} else {
if (typeof source[prop] !== 'object') {
target[prop] = source[prop];
} else {
if (target[prop].concat && source[prop].concat) {
target[prop] = target[prop].concat(source[prop]); //合并
} else {
target[prop] = deepMerge(target[prop], source[prop]); //递归
}
}
}
} else {
target[prop] = source[prop];
}
}
return target;
}
const isArray = function(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
/**深度合并对象*/
export const deepClone = function(obj) {
// 对常见的“非”值,直接返回原来值
if ([null, undefined, NaN, false].includes(obj)) return obj;
if (typeof obj !== "object" && typeof obj !== 'function') {
//原始类型直接返回
return obj;
}
let o = isArray(obj) ? [] : {};
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
}
}
return o;
};
let timeout = null
/**
* 防抖原理一定时间内只有最后一次操作再过wait毫秒后才执行函数
*
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
export const debounce = function(func, wait = 500, immediate = false) {
// 清除定时器
if (timeout !== null) clearTimeout(timeout)
// 立即执行,此类情况一般用不到
if (immediate) {
const callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, wait)
if (callNow) typeof func === 'function' && func()
} else {
// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
timeout = setTimeout(() => {
typeof func === 'function' && func()
}, wait)
}
}

130
src/uni_modules/wz-select-popup/components/wz-select-popup/wz-list.vue

@ -0,0 +1,130 @@
<template>
<view class="wz-list">
<view :class="item.check?'check-item':'list-item'" v-for="(item,index) in list" :key="index"
@click="$emit('checkList',item)">
<view class="" v-if="isShowIcon">
<uni-icons v-if="item.check" type="checkbox-filled" color="#007aff" size="24"></uni-icons>
<uni-icons v-else type="circle" color="#999" size="24"></uni-icons>
</view>
({{index+1}})
<view class="uni-flex" style="flex-direction: column; font-size: 32rpx;">
<view class="list-item-text">ERP料号 : {{item.itemCode}}</view>
<view class="list-item-text">名称 : {{item.itemName}}</view>
<view class="list-item-text">描述 : {{item.itemDesc1}}</view>
</view>
</view>
<view class="loadmore" @click="$emit('loadmore')">
<view v-if="page.loading == 'loading'" class="icon">
<uni-icons type="spinner-cycle" size="24"></uni-icons>
</view>
<view class="">{{loadmore[page.loading]}}</view>
</view>
</view>
</template>
<script>
export default {
name: 'wz-list',
props: {
list: {
type: Array,
default: () => []
},
isShowIcon: {
type: Boolean,
default: true
},
page: {
type: Object,
default: () => {
return {
loading: 'loading', //loading|loadmore|nomore
isEmpty: false
}
}
},
fields: {
type: Object,
default: () => {
return {
label: 'name',
value: 'code',
image: 'image'
}
}
}
},
data() {
return {
loadmore: {
loading: '正在加载',
loadmore: '点击或上拉加载更多',
nomore: '没有更多了'
}
}
},
onLoad() {
},
methods: {
}
}
</script>
<style scoped lang="scss">
.wz-list {
@mixin wz-line ($line) {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box; //
-webkit-box-orient: vertical; //
-webkit-line-clamp: $line;
}
.list-item {
display: flex;
align-items: center;
color: $uni-text-color-grey;
padding: $uni-spacing-col-base;
margin-bottom: $uni-spacing-col-sm;
background-color: #fff;
.list-item-text {
@include wz-line(2);
margin-left: 4px;
margin-bottom: 1px
}
}
.check-item {
@extend .list-item;
color: $uni-text-color;
}
.loadmore {
display: flex;
justify-content: center;
align-items: center;
font-size: $uni-font-size-sm;
padding: 8px;
@keyframes rotateInfinite {
form {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.icon {
animation: rotateInfinite infinite 1s linear;
}
}
}
</style>

90
src/uni_modules/wz-select-popup/components/wz-select-popup/wz-search.vue

@ -0,0 +1,90 @@
<template>
<view class="wz-search">
<view class="search-input">
<uni-icons color="#808080" size="22" type="search"></uni-icons>
<view class="right">
<input :value="value" :placeholder="placeholder" @input="change" />
</view>
<uni-icons v-if="value || value === 0 || value === '0'" color="#808080" size="22" type="clear"
@click="clear">
</uni-icons>
</view>
<view class="search-button">
<button class="button" @click="searchData">搜索</button>
</view>
</view>
</template>
<script>
export default {
name: 'wz-search',
props: {
value: {},
placeholder: {
type: String,
default: '请输入搜索关键字'
}
},
data() {
return {
searchVal: ''
}
},
methods: {
change({
detail
}) {
this.$emit('input', detail.value)
},
clear() {
this.$emit('clear')
this.$emit('input', '')
},
searchData() {
this.$emit('search', this.value)
}
}
}
</script>
<style scoped lang="scss">
.wz-search {
display: flex;
align-items: center;
font-size: $uni-font-size-base;
.search-input {
flex: 1;
display: flex;
align-items: center;
height: 32px;
padding: 0 8px;
border: 1px solid $uni-border-color;
border-radius: 100px;
.right {
flex: 1;
width: 100%;
margin: 0 4px;
}
}
.search-button {
margin-left: 8px;
.button {
padding: 0;
font-size: inherit;
background-color: transparent;
color: inherit;
width: 100%;
height: 32px;
line-height: 32px;
&::after {
border: 0;
}
}
}
}
</style>

357
src/uni_modules/wz-select-popup/components/wz-select-popup/wz-select-popup.vue

@ -0,0 +1,357 @@
<template>
<view>
<u-popup ref="popup" v-model="showPopup" border-radius="15" style="width: 100%;" mode="center">
<view class="select-popup-content">
<view class="uni-flex" style="display: flex; width: 100%;justify-content: center; ">
<view class="" style=" font-size: 35rpx; margin: 20rpx; font-weight: bold;">
{{title}}
</view>
</view>
<u-line></u-line>
<view class="popup-search">
<wz-search v-model="searchValue" @search="searchData('search')" @clear="searchData('clear')" @input="change"/>
</view>
<scroll-view class="popup-scroll-y" :scroll-top="scroll.newTop" scroll-y
:style="{'--popup-scroll-height': scrollH}" @scrolltolower="scrolltolower" @scroll="viewScroll">
<wz-list :list="dataList" :fields="popConfig.fields" :page="pageStatus" @checkList="checkList"
@loadmore="scrolltolower" :isShowIcon="false" />
</scroll-view>
<view v-if="popConfig.mode =='checkbox'" class="footer-button">
<view class="button-item">
<button class="button" @click="close">取消</button>
</view>
<view class="button-item">
<button class="button" type="primary" @click="checkboxConfirm">确定</button>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import wzSearch from "./wz-search.vue"
import wzList from "./wz-list.vue"
import {
deepMerge,
deepClone,
debounce
} from "./util/index.js"
import defaultConfig from "./util/defaultConfig.js"
let allDataList = null
/**
* 下拉选择弹窗
* @function open 打开弹窗
* @property {String} scrollH 滚动内容的高度不包含搜索框和多选时的底部按钮栏需要带单位
* @property {String} popType = popup弹出方向默认bottom 请查看uni-popup文档
*/
export default {
name: "wz-select-popup",
components: {
wzSearch,
wzList
},
props: {
scrollH: {
type: String,
default: '50vh'
},
popType: {
type: String,
default: 'bottom'
},
title: {
type: String,
default: '物料查询'
},
},
data() {
return {
dataList: [],
searchValue: '',
pageStatus: {
loading: '', //loading|loadmore|nomore
isEmpty: false
},
scroll: {
oldTop: 0,
newTop: 0
},
popConfig: {},
showPopup:false
};
},
mounted() {
this.popConfig = deepClone(defaultConfig)
},
destroyed() {
allDataList = null
},
methods: {
viewScrollTop() {
// view
this.scroll.newTop = this.scroll.oldTop
this.$nextTick(function() {
this.scroll.newTop = 0
});
},
viewScroll(e) {
debounce(() => {
this.scroll.oldTop = e.detail.scrollTop
}, 100)
},
change(data){
console.log("输入",data)
this.searchData("search")
},
searchData(type) {
const {
search,
fields,
proxyConfig
} = this.popConfig
this.pageStatus.loading == 'loading'
this.pageStatus.isEmpty = false
this.popConfig.page.pageIndex = 1
this.dataList = []
this.viewScrollTop()
if (search.type === 'local' && proxyConfig.localPaging) {
if (type === 'clear') {
this.listInit(allDataList)
return
}
this.dataList = allDataList?.filter(v => v[fields.label].includes(this.searchValue))
} else {
this.proxyRequest()
}
},
/**
* 打开弹窗选择器
* @function
* @param {Object} configs 弹出层配置
* @prmam {String} configs.mode 选择模式radio单选 | checkbox多选 默认是radio
* @param {String | Array} configs.selected 已选中的value,单选传字符串多选传数组
*
* @param {Array} dataList 如果dataList传入了数组则直接使用传入的数组渲染无需再配置proxyConfig
*
* @param {Object} configs.proxyConfig 组件内部代理请求数据配置
* @param {Function} proxyConfig.reqFun 请求数据的方法
* @param {Boolean} proxyConfig.localPaging 是否本地分页
*
* @param {Object} configs.search //
* @param {String} search.type = local组件内部排序搜索 | remote请求接口会把输入的搜索文字传入proxyConfig.reqFun
*
* @param {Object} configs.page 分页的页码参数
* @param {Number} page.pageIndex 当前页
* @param {Number} page.pageSize 页大小
*
* @param {Object} configs.fields 传入选项数据的key value
* @param {String} fields.label 用于显示文字的key
* @param {String} fields.value 用于取值的key
*/
open(configs = {}) {
const {
dataList,
...config
} = configs || {}
if (config) {
this.popConfig = deepMerge(this.popConfig, config)
}
this.dataList=[]
this.searchValue=""
this.listInit(dataList)
this.showPopup =true;
},
/**列表数据初始化*/
listInit(dataList) {
this.pageStatus.loading = 'loading'
//dataListproxyConfig.reqFun
if (dataList && dataList instanceof Array) {
console.warn('直接使用传入的dataList')
allDataList = deepClone(dataList)
this.popConfig.proxyConfig.localPaging = true
this.getLocalPagingData()
return
}
if (this.popConfig.proxyConfig.reqFun instanceof Function) {
// if (Object.prototype.toString.call(this.popConfig.proxyConfig.reqFun) != '[object Promise]') {
// throw 'proxyConfig.reqFunreturn Promise.resolve()'
// }
this.proxyRequest()
}
},
/**组件代理请求*/
proxyRequest() {
console.log("请求proxyRequest")
const {
proxyConfig,
page
} = this.popConfig
this.pageStatus.loading = 'loading'
proxyConfig.reqFun({
...page,
searchValue: this.searchValue
}).then(list => {
list.items.forEach(res=>{
res.code =res.itemCode
res.name =res.itemName;
})
if (proxyConfig.localPaging) { //
allDataList = list.items
this.getLocalPagingData()
return
}
this.pageStatus.loading = 'loadmore'
// if (!list.items || list.items.length != page.pageSize) {
// this.pageStatus.loading = 'nomore'
// this.pageStatus.isEmpty = true
// }
if (!list.items || list.items.length ==0) {
this.pageStatus.loading = 'nomore'
this.pageStatus.isEmpty = true
}
this.handleSelected(list.items)
this.dataList = this.dataList.concat(list.items)
})
},
close() {
this.showPopup =false;
this.$emit('close')
setTimeout(() => {
this.allDataList = null
this.pageStatus.isEmpty = false
this.pageStatus.loading = 'loading'
this.popConfig = defaultConfig
this.dataList = []
}, 500)
},
/**上拉触底*/
scrolltolower() {
if (!this.pageStatus.isEmpty && this.pageStatus.loading != 'loading') {
this.popConfig.page.pageIndex++
if (this.popConfig.proxyConfig.localPaging) {
this.getLocalPagingData()
} else {
this.proxyRequest()
}
}
},
/**前端本地分页*/
getLocalPagingData() {
const {
pageIndex,
pageSize
} = this.popConfig.page
const list = allDataList.slice(pageSize * (pageIndex - 1), pageSize + (pageSize * (pageIndex - 1)))
this.pageStatus.loading = 'loadmore'
this.handleSelected(list)
this.dataList = this.dataList.concat(list)
if (!list || list.length != pageSize) {
this.pageStatus.loading = 'nomore'
this.pageStatus.isEmpty = true
}
},
/**多选点击确定*/
checkboxConfirm() {
const list = this.dataList.filter(v => v.check)
const data = {
names: [],
values: []
}
const {
fields,
mode
} = this.popConfig
list.forEach(v => {
data.names.push(v[fields.label])
data.values.push(v[fields.value])
})
this.$emit('select', mode, {
...data,
origin: list,
})
this.close()
},
/**选择*/
checkList(data, index) {
const {
mode,
fields
} = this.popConfig
if (mode == 'radio') {
this.dataList.forEach(v => {
v.check = v[fields.value] == data[fields.value] ? true : false
})
this.$emit('select', mode, data)
this.close()
} else {
data.check = !data.check
}
},
/**处理已选中的选项*/
handleSelected(list) {
const {
selected,
fields
} = this.popConfig
list?.forEach(item => {
const valueCode = item.itemCode
const isChecked = selected instanceof Array ? selected.includes(valueCode) : selected ==
valueCode
item.check = isChecked ? true : false
})
},
}
}
</script>
<style lang="scss" scoped>
.select-popup-content {
background-color: #fff;
.popup-search {
font-size: $uni-font-size-base;
padding: 4px $uni-spacing-row-base;
border-bottom: 1px solid $uni-border-color;
}
.footer-button {
display: flex;
justify-content: space-between;
align-items: center;
text-align: center;
.button-item {
flex: 1;
padding: 4px 16px;
.button {
width: 100%;
height: 36px;
line-height: 36px;
font-size: $uni-font-size-base;
}
}
}
.popup-scroll-y {
height: var(--popup-scroll-height);
padding: $uni-spacing-col-sm $uni-spacing-col-base;
box-sizing: border-box;
background-color: $uni-bg-color-grey;
}
}
</style>

82
src/uni_modules/wz-select-popup/package.json

@ -0,0 +1,82 @@
{
"id": "wz-select-popup",
"displayName": "popup弹窗选择器",
"version": "1.0.11",
"description": "popup弹窗选择器支持单选,多选,组件内部代理请求,自定义label,value显示,分页加载,",
"keywords": [
"wz-select-popup"
],
"repository": "",
"engines": {
"HBuilderX": "^3.96"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": ["uni-icons", "uni-popup"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "u"
},
"App": {
"app-vue": "y",
"app-nvue": "u",
"app-uvue": "n"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "y",
"IE": "u",
"Edge": "y",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "y",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
Loading…
Cancel
Save