lijuncheng
5 months ago
19 changed files with 1183 additions and 206 deletions
@ -1,11 +1,11 @@ |
|||
VITE_BASE_URL=http://172.22.32.9:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=http://172.22.32.9:81/admin-api |
|||
VITE_BASE_URL=http://172.21.32.14:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=http://172.21.32.14:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"成都1397","value":2},{"text":"长春2379","value":3}]' |
|||
VITE_TENANT='[{"text":"长春1379","value":1}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://172.22.32.9:90' |
|||
VITE_JMREPORT_BASE_URL='http://172.21.32.14:90' |
|||
|
@ -1,7 +1,36 @@ |
|||
<template> |
|||
<view class=""> |
|||
<view class=""> |
|||
<com-blank-view @goScan='openFg' v-if="detailSource.length==0"></com-blank-view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import comBlankView from '@/mycomponents/common/comBlankView.vue' |
|||
export default { |
|||
components: { |
|||
comBlankView |
|||
}, |
|||
data() { |
|||
return { |
|||
detailSource:[] |
|||
}; |
|||
}, |
|||
|
|||
onShow() { |
|||
}, |
|||
|
|||
mounted() { |
|||
|
|||
}, |
|||
methods: { |
|||
openFg(){ |
|||
|
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
|
@ -1,7 +1,36 @@ |
|||
<template> |
|||
<view class=""> |
|||
<view class=""> |
|||
<com-blank-view @goScan='openFg' v-if="detailSource.length==0"></com-blank-view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import comBlankView from '@/mycomponents/common/comBlankView.vue' |
|||
export default { |
|||
components: { |
|||
comBlankView |
|||
}, |
|||
data() { |
|||
return { |
|||
detailSource:[] |
|||
}; |
|||
}, |
|||
|
|||
onShow() { |
|||
}, |
|||
|
|||
mounted() { |
|||
|
|||
}, |
|||
methods: { |
|||
openFg(){ |
|||
|
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
|
@ -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) |
|||
第一次发布 |
@ -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', //暂时不用
|
|||
} |
|||
} |
@ -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) |
|||
} |
|||
} |
@ -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> |
@ -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> |
@ -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' |
|||
//如果dataList传入了数组,则不再调用proxyConfig.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.reqFun需要return 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> |
@ -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" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,132 @@ |
|||
# wz-select-popup |
|||
|
|||
## 示例 |
|||
|
|||
```vue |
|||
<template> |
|||
<view> |
|||
<view class="" style="margin-bottom: 16px;"> |
|||
<view style="margin-bottom: 8px;">names:{{userForm.names}}</view> |
|||
<view style="margin-bottom: 8px;">values:{{userForm.values}}</view> |
|||
<view style="margin-bottom: 8px;">origin:{{userForm.origin}}</view> |
|||
</view> |
|||
<button @click="open">打开</button> |
|||
<wz-select-popup ref="wzSelectPopup" @select="selectCheckbox" /> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { |
|||
simulationReqGetList, |
|||
getDataList |
|||
} from "@/common/mock.js" |
|||
export default { |
|||
data() { |
|||
return { |
|||
userForm: { |
|||
names: [], |
|||
values: [], |
|||
origin:[] |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
open() { |
|||
this.$refs.wzSelectPopup.open({ |
|||
mode: 'checkbox', //radio checkbox 单选、多选 |
|||
// dataList:[], //如果dataList传入了数组则直接使用传入的数组渲染,无需再配置proxyConfig |
|||
selected: this.userForm.values, //已选中的数据 |
|||
proxyConfig: { //组件内部代理请求数据配置 |
|||
reqFun: this.reqGetList, //请求方法,在方法中请返回Promise.resolve([]) |
|||
localPaging: false //前端本地分页 |
|||
}, |
|||
search: { |
|||
type: 'local', //local本地数据搜索 | remote请求接口 |
|||
}, |
|||
fields: { |
|||
label: 'name', |
|||
value: 'code' |
|||
} |
|||
}) |
|||
}, |
|||
selectCheckbox(mode, data) { |
|||
console.log(mode, data) |
|||
this.userForm.names = data.names |
|||
this.userForm.values = data.values |
|||
this.userForm.origin = data.origin |
|||
}, |
|||
reqGetList(data) { |
|||
return simulationReqGetList({ |
|||
pageIndex: data.pageIndex, |
|||
pageSize: data.pageSize, |
|||
name: data.searchValue |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
|
|||
</style> |
|||
``` |
|||
|
|||
## 属性props |
|||
|
|||
| 属性 | 类型 | 默认值 | 说明 | |
|||
| ------- | ------ | ------ | ------------------------------------------------------------ | |
|||
| scrollH | String | 50vh | 滚动内容的高度,不包含搜索框和多选时的底部按钮栏。需要带单位 | |
|||
|
|||
|
|||
## 方法methods |
|||
|
|||
| 方法名 | 说明 | 参数 | |
|||
| ------ | -------- | ----------------------------- | |
|||
| open | 打开弹窗 | [configs](#open方法的configs) | |
|||
| close | 关闭弹窗 | | |
|||
|
|||
### open方法的configs |
|||
|
|||
| 参数名 | 说明 | 类型 | 默认值 | |
|||
| ----------- | ------------------------------------------------------------ | ------------- | -------------------------- | |
|||
| mode | 选择模式radio单选 ,checkbox多选 | String | radio | |
|||
| selected | 已选中的value, 单选传字符串,多选传数组 | String\|Array | [] | |
|||
| dataList | 传入了数组,则直接使用传入的数组渲染,无需再配置proxyConfig | Array | null | |
|||
| proxyConfig | 组件内部代理请求数据配置 | Object | [proxyConfig](#proxyConfig的属性) | |
|||
| search | 搜索配置 | Object | [search](#search的属性) | |
|||
| page | 分页配置,如果是组件内部代理请求会把page的值加入到proxyConfig.reqFun请求参数里 | Object | [page](#page的属性) | |
|||
| fields | 显示和取值的label,value | Object | [fields](#fields的属性) | |
|||
|
|||
#### proxyConfig的属性 |
|||
|
|||
| 参数名 | 说明 | 类型 | 默认值 | 返回值 | |
|||
| ----------- | --------------------------------------------------------- | ------- | ------------------- | --------------------------------------- | |
|||
| reqFun | 向服务器请求数据的Promise方法,会返回页码以及搜索框的value | Promise | Promise.resolve([]) | ({pageIndex, pageSize,searchValue})=>{} | |
|||
| localPaging | 是否本地分页 | Boolean | false | | |
|||
|
|||
#### search的属性 |
|||
|
|||
| 参数名 | 说明 | 类型 | 默认值 | |
|||
| ------ | ------------------------------------------------------------ | ------ | ------ | |
|||
| type | 搜索的类型,local本地搜索, remote向服务器请求。只有使用proxyConfig.reqFun请求才能配置为remote | String | local | |
|||
|
|||
#### page的属性 |
|||
|
|||
| 参数名 | 说明 | 类型 | 默认值 | |
|||
| --------- | ------ | ------ | ------ | |
|||
| pageIndex | 当前页 | Number | 1 | |
|||
| pageSize | 页大小 | Number | 20 | |
|||
|
|||
#### fields的属性 |
|||
|
|||
| 参数名 | 说明 | 类型 | 默认值 | |
|||
| ------ | ------------ | ------ | ------ | |
|||
| label | 显示的字段名 | String | name | |
|||
| value | 取值的字段名 | String | code | |
|||
|
|||
## 事件enevt |
|||
|
|||
| 名称 | 触发时机 | 返回值 | |
|||
| ------ | ------------------------------------------ | ------------------------------------------------------------ | |
|||
| select | 单选点击列表时触发,多选点击确定按钮时触发 | mode等于radio时:(mode, {check,name,code})=>{}<br/>mode等于checkbox时:(mode, {names,values,origin})=>{} | |
|||
| close | popup关闭 | void | |
Loading…
Reference in new issue