1
This commit is contained in:
parent
3c6c07fd11
commit
6708283fa0
@ -12,7 +12,7 @@
|
||||
<image class="line-icon" src="../../static/icons/order-icon1.png" mode="aspectFit"></image>
|
||||
<text class="line-text">{{orderInfo.address}}</text>
|
||||
</view>
|
||||
<view class="line">
|
||||
<view class="line" @click="callPhone(orderInfo.phone)">
|
||||
<image class="line-icon" src="../../static/icons/order-icon2.png" mode="aspectFit"></image>
|
||||
<text class="line-text">{{orderInfo.phone}}</text>
|
||||
</view>
|
||||
@ -20,6 +20,9 @@
|
||||
<image class="line-icon" src="../../static/icons/order-icon3.png" mode="aspectFit"></image>
|
||||
<text class="line-text">{{orderInfo.busiTypeStr}}</text>
|
||||
</view>
|
||||
<view class="line" v-if="orderInfo.adviser">
|
||||
<text class="line-text">服务顾问:{{orderInfo.adviser.nickname}} <text @click="callPhone(orderInfo.adviser.mobile)">电话:{{orderInfo.adviser.mobile}}</text></text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!hideFooter" class="footer">
|
||||
<!-- <view class="btn" :class="{phone: isDetail}">-->
|
||||
@ -78,7 +81,12 @@
|
||||
uni.navigateTo({
|
||||
url: '/pages-order/orderDetail/orderDetail?ticketsId=' + this.orderInfo.ticketsId
|
||||
})
|
||||
}
|
||||
},
|
||||
callPhone(phone){
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone //仅为示例
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -107,7 +115,7 @@
|
||||
|
||||
.orderStatus {
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
&.status_01 {
|
||||
color: #0174F6;
|
||||
@ -124,7 +132,7 @@
|
||||
align-items: center;
|
||||
column-gap: 10rpx;
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// 应用全局配置
|
||||
module.exports = {
|
||||
// baseUrl: 'https://www.nuoyunr.com',
|
||||
// baseUrl: 'http://192.168.1.17:48080',
|
||||
baseUrl: "http://192.168.1.4:48080",
|
||||
baseUrl: 'http://192.168.1.17:48080',
|
||||
// baseUrl: "http://192.168.1.4:48080",
|
||||
imagesUrl: 'http://shequ.0315e.com/static/images/pages/',
|
||||
baseImageUrl: 'https://www.nuoyunr.com/minio/',
|
||||
wsUrl: 'wss://www.nuoyunr.com',
|
||||
|
@ -43,11 +43,11 @@
|
||||
<template v-if="carInfo.showAll">
|
||||
<view style="display: flex;align-items: center">
|
||||
<view class="infoItem" style="flex: 1">
|
||||
<view class="label">年检时间</view>
|
||||
<view class="label">年检到期时间</view>
|
||||
<view class="value">{{ ticketInfo.inspectionDate }}</view>
|
||||
</view>
|
||||
<view class="infoItem" style="flex: 1">
|
||||
<view class="label">保险时间</view>
|
||||
<view class="label">保险到期时间</view>
|
||||
<view class="value">{{ ticketInfo.insuranceDate }}</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -75,15 +75,15 @@
|
||||
<text class="value">{{ ticketInfo.userName }}</text>
|
||||
</view>
|
||||
<view class="infoItem" style="flex: 1">
|
||||
<text class="label">性别</text>
|
||||
<text class="value">{{ ticketInfo.customerInfo.sex === '1' ? '女' : '男' }}</text>
|
||||
<text class="label">联系方式</text>
|
||||
<text class="value">{{ ticketInfo.userMobile || "" }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<template v-if="userInfo.showAll">
|
||||
<view style="display: flex;align-items: center">
|
||||
<view class="infoItem" style="flex: 1">
|
||||
<text class="label">联系方式</text>
|
||||
<text class="value">{{ ticketInfo.userMobile || "" }}</text>
|
||||
<text class="label">性别</text>
|
||||
<text class="value">{{ ticketInfo.customerInfo.sex === '1' ? '女' : '男' }}</text>
|
||||
</view>
|
||||
<view class="infoItem" style="flex: 1">
|
||||
<text class="label">生日</text>
|
||||
@ -610,7 +610,7 @@
|
||||
|
||||
.projDate {
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #858BA0;
|
||||
|
||||
display: flex;
|
||||
@ -622,7 +622,7 @@
|
||||
|
||||
.projDesc {
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #858BA0;
|
||||
}
|
||||
|
||||
@ -676,7 +676,7 @@
|
||||
.projBaseInfo {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
font-size: 24rpx;
|
||||
font-size: 27rpx;
|
||||
color: #999999;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
@ -719,7 +719,7 @@
|
||||
color: #333333;
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ export default {
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '全部订单'
|
||||
title: '全部'
|
||||
},
|
||||
],
|
||||
orderList: [],
|
||||
@ -344,7 +344,7 @@ export default {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
font-size: 24rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
&.actived {
|
||||
color: #0174F6;
|
||||
|
@ -27,9 +27,18 @@
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text class="formLabel">品牌</text>
|
||||
<picker @change="brandChange" :value="brandIndex" :range="brandNamesComputed">
|
||||
<view class="uni-input">{{ brandNamesComputed[brandIndex] }}</view>
|
||||
</picker>
|
||||
<song-data-picker
|
||||
ref="songpicker"
|
||||
style=" width: 55%;"
|
||||
:localdata="brandList"
|
||||
popup-title="请选择品牌"
|
||||
:openSearch="true"
|
||||
@change="onchange"
|
||||
@nodeclick="onnodeclick"
|
||||
></song-data-picker>
|
||||
<!-- <picker @change="brandChange" :value="brandIndex" :range="brandNamesComputed">-->
|
||||
<!-- <view class="uni-input">{{ brandNamesComputed[brandIndex] }}</view>-->
|
||||
<!-- </picker>-->
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text class="formLabel">型号</text>
|
||||
@ -141,8 +150,12 @@ export default {
|
||||
categoryList: [],
|
||||
//可选车辆性质范围
|
||||
natureList: [],
|
||||
//可选车辆品牌范围
|
||||
brandList: []
|
||||
//所有可选车辆品牌
|
||||
brandList: [],
|
||||
//选中的车辆品牌id
|
||||
brandId: '',
|
||||
//选中的车辆品牌名称
|
||||
brandName: 0,
|
||||
};
|
||||
},
|
||||
// 计算属性,将对象数组转换为字符串数组
|
||||
@ -190,6 +203,14 @@ export default {
|
||||
this.getBrandList();
|
||||
},
|
||||
methods: {
|
||||
onchange(e) {
|
||||
this.brandId = e.detail.value[0].id
|
||||
this.brandName = e.detail.value[0].brandName
|
||||
this.car.carBrand = e.detail.value[0].id
|
||||
},
|
||||
onnodeclick(node) {
|
||||
console.log(node,"node")
|
||||
},
|
||||
radioChange(event){
|
||||
this.car.isOwner = event.detail.value
|
||||
},
|
||||
@ -221,8 +242,8 @@ export default {
|
||||
//车辆品牌自动定位
|
||||
this.brandList.forEach((item, index) => {
|
||||
if (item.brandName == driveLicense.brand) {
|
||||
this.brandIndex = index;
|
||||
this.car.carBrand = this.brandList[index].id;
|
||||
this.setCarBrand(this.brandList[index].id,item.brandName)
|
||||
}
|
||||
})
|
||||
//车辆性质自动定位
|
||||
@ -234,6 +255,18 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 设置选中的车辆品牌
|
||||
* @param id
|
||||
* @param name
|
||||
*/
|
||||
setCarBrand(id,name){
|
||||
this.$nextTick(()=>{
|
||||
this.brandId = id
|
||||
this.brandName = name
|
||||
this.$refs.songpicker.inputSelected=[{text:name,value:id}]
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 打开摄像头
|
||||
*/
|
||||
@ -351,6 +384,10 @@ export default {
|
||||
})
|
||||
if (res.code == 200) {
|
||||
console.log('车辆品牌', res.data)
|
||||
res.data.forEach(item => {
|
||||
item.text = item.brandName,
|
||||
item.value = item.id
|
||||
})
|
||||
this.brandList = res.data;
|
||||
if (this.bo2 == true){
|
||||
this.car.carBrand= res.data[0].id;
|
||||
@ -358,7 +395,7 @@ export default {
|
||||
// 如果是修改 遍历当前集合 将index 同步
|
||||
this.brandList.forEach((item, index) => {
|
||||
if (item.id == this.car.carBrand) {
|
||||
this.brandIndex = index;
|
||||
this.setCarBrand(item.id,item.brandName)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -25,12 +25,12 @@
|
||||
</view>
|
||||
<view class="cardInfoBody_footer">
|
||||
<view class="nj">
|
||||
年检时间:<text class="date">{{car.insuranceDate || '未获取到'}}</text>
|
||||
年检时间:<text class="date">{{car.nextInspectionDate || '未获取到'}}</text>
|
||||
<image class="cardInfoBody_footerIcon" src="../../static/icons/icon2.png" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="bx">
|
||||
保险时间:<text class="date">{{car.nextInspectionDate || '未获取到'}}</text>
|
||||
保险时间:<text class="date">{{car.insuranceExpiryDate || '未获取到'}}</text>
|
||||
<image class="cardInfoBody_footerIcon" src="../../static/icons/icon2.png" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
|
@ -8,23 +8,11 @@
|
||||
refresher-enabled @refresherrefresh="onRefresherrefresh" :refresher-triggered="isTriggered">
|
||||
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
|
||||
</reservationOrderVue>
|
||||
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
|
||||
</reservationOrderVue>
|
||||
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
|
||||
</reservationOrderVue>
|
||||
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
|
||||
</reservationOrderVue>
|
||||
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
|
||||
</reservationOrderVue>
|
||||
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
|
||||
</reservationOrderVue>
|
||||
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
|
||||
</reservationOrderVue>
|
||||
<view class="no-data" v-if="orderList.length==0">
|
||||
<image class="" src="@/static/images/nothing.png" ></image>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="no-data" v-if="orderList.length==0">
|
||||
<image class="" src="@/static/images/nothing.png" ></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@ -124,7 +112,7 @@
|
||||
title: item.company.corpName,
|
||||
address: item.company.address,
|
||||
phone: item.company.mobilePhone,
|
||||
busiTypeStr: item.servicePackage?.name,
|
||||
busiTypeStr: item.repairTypeText?item.repairTypeText:"",
|
||||
status: item.bookingStatus
|
||||
}
|
||||
})
|
||||
@ -133,6 +121,7 @@
|
||||
} else {
|
||||
this.orderList = thisDataList
|
||||
}
|
||||
console.log(this.orderList,"demo")
|
||||
//将获取的总条数赋值
|
||||
this.total = res.data.total
|
||||
this.isTriggered = false
|
||||
|
@ -0,0 +1,524 @@
|
||||
<template>
|
||||
<view class="uni-data-tree">
|
||||
<view class="uni-data-tree-input" @click="handleInput">
|
||||
<slot :options="options" :data="inputSelected" :error="errorMessage">
|
||||
<view class="input-value" :class="{ 'input-value-border': border }">
|
||||
<text v-if="errorMessage" class="selected-area error-text">{{ errorMessage }}</text>
|
||||
<view v-else-if="loading && !isOpened" class="selected-area"><uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more></view>
|
||||
<scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true">
|
||||
<view class="selected-list">
|
||||
<view class="selected-item" v-for="(item, index) in inputSelected" :key="index">
|
||||
<text>{{ item.text }}</text>
|
||||
<text v-if="index < inputSelected.length - 1" class="input-split-line">{{ split }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<text v-else class="selected-area placeholder">{{ placeholder }}</text>
|
||||
<view class="arrow-area" v-if="!readonly"><view class="input-arrow"></view></view>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view>
|
||||
<view class="uni-data-tree-dialog" v-if="isOpened">
|
||||
<view class="dialog-caption">
|
||||
<view class="title-area">
|
||||
<text class="dialog-title">{{ popupTitle }}</text>
|
||||
</view>
|
||||
<view class="dialog-close" @click="handleClose">
|
||||
<view class="dialog-close-plus" data-id="close"></view>
|
||||
<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="dialog-caption" v-if="openSearch">
|
||||
<view style="width: 80%; margin: 10px 10%;">
|
||||
<uni-easyinput
|
||||
type="text"
|
||||
suffixIcon="search"
|
||||
v-model="searchWord"
|
||||
placeholder="输入关键字搜索"
|
||||
@iconClick="searchClick"
|
||||
@confirm="searchClick"
|
||||
></uni-easyinput>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="picker-view" style="overflow-y:auto" v-if="showSearchResult">
|
||||
<uni-list-item v-for="(item, index) in searchResult" :key="index" :title="item.text" clickable link @click="clickSearch(item)"></uni-list-item>
|
||||
</view>
|
||||
|
||||
<data-picker-view
|
||||
v-if="!showSearchResult"
|
||||
class="picker-view"
|
||||
ref="pickerView"
|
||||
v-model="value"
|
||||
:localdata="localdata"
|
||||
:preload="preload"
|
||||
:collection="collection"
|
||||
:field="field"
|
||||
:orderby="orderby"
|
||||
:where="where"
|
||||
:step-searh="stepSearh"
|
||||
:self-field="selfField"
|
||||
:parent-field="parentField"
|
||||
:managed-mode="true"
|
||||
@change="onchange"
|
||||
@datachange="ondatachange"
|
||||
></data-picker-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dataPicker from '../uni-data-pickerview/uni-data-picker.js';
|
||||
import DataPickerView from '../uni-data-pickerview/uni-data-pickerview.vue';
|
||||
import uniEasyinput from '../uni-easyinput/uni-easyinput.vue';
|
||||
import uniListItem from '../uni-list-item/uni-list-item.vue';
|
||||
|
||||
/**
|
||||
* uni-data-picker
|
||||
* @description uni-data-picker
|
||||
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-data-picker
|
||||
* @property {String} popup-title 弹出窗口标题
|
||||
* @property {Array} localdata 本地数据,参考
|
||||
* @property {Boolean} border = [true|false] 是否有边框
|
||||
* @property {Boolean} readonly = [true|false] 是否仅读
|
||||
* @property {Boolean} preload = [true|false] 是否预加载数据
|
||||
* @value true 开启预加载数据,点击弹出窗口后显示已加载数据
|
||||
* @value false 关闭预加载数据,点击弹出窗口后开始加载数据
|
||||
* @property {Boolean} step-searh = [true|false] 是否分布查询
|
||||
* @value true 启用分布查询,仅查询当前选中节点
|
||||
* @value false 关闭分布查询,一次查询出所有数据
|
||||
* @property {String|DBFieldString} self-field 分布查询当前字段名称
|
||||
* @property {String|DBFieldString} parent-field 分布查询父字段名称
|
||||
* @property {String|DBCollectionString} collection 表名
|
||||
* @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
|
||||
* @property {String} orderby 排序字段及正序倒叙设置
|
||||
* @property {String|JQLString} where 查询条件
|
||||
* @event {Function} onpopupshow 弹出的选择窗口打开时触发此事件
|
||||
* @event {Function} onpopuphide 弹出的选择窗口关闭时触发此事件
|
||||
*/
|
||||
export default {
|
||||
name: 'UniDataPicker',
|
||||
mixins: [dataPicker],
|
||||
components: {
|
||||
DataPickerView,
|
||||
uniEasyinput,
|
||||
uniListItem
|
||||
},
|
||||
props: {
|
||||
options: {
|
||||
type: [Object, Array],
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
popupTitle: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
heightMobile: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
split: {
|
||||
type: String,
|
||||
default: '/'
|
||||
},
|
||||
openSearch: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isOpened: false,
|
||||
inputSelected: [],
|
||||
searchWord: '',
|
||||
showSearchResult: false,
|
||||
searchDatas: [],
|
||||
searchResult: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.form = this.getForm('uniForms');
|
||||
this.formItem = this.getForm('uniFormsItem');
|
||||
if (this.formItem) {
|
||||
if (this.formItem.name) {
|
||||
this.rename = this.formItem.name;
|
||||
this.form.inputChildrens.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.load();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
closeSearchDom() {
|
||||
this.showSearchResult = false;
|
||||
this.searchWord = '';
|
||||
this.searchResult = [];
|
||||
},
|
||||
clickSearch(item) {
|
||||
this.closeSearchDom();
|
||||
const e = [];
|
||||
const loop = (rows, ids) => {
|
||||
let row = rows.find(x => x.value == ids[0]);
|
||||
e.push(row);
|
||||
if (!row.children) return;
|
||||
loop(row.children, ids.splice(1, ids.length - 1));
|
||||
};
|
||||
loop(this.localdata, item.value.split(','));
|
||||
this.onchange(e);
|
||||
},
|
||||
searchClick() {
|
||||
if (!this.searchWord) {
|
||||
return;
|
||||
}
|
||||
this.searchResult = this.searchDatas.filter(x => x.text.split(' ').join('').includes(this.searchWord));
|
||||
this.showSearchResult = true;
|
||||
},
|
||||
onPropsChange() {
|
||||
this._treeData = [];
|
||||
this.selectedIndex = 0;
|
||||
this.load();
|
||||
},
|
||||
load() {
|
||||
if (this.readonly) {
|
||||
this._processReadonly(this.localdata, this.value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isLocaldata) {
|
||||
this.loadData();
|
||||
this.inputSelected = this.selected.slice(0);
|
||||
this.initSearchDatas();
|
||||
} else if (this.value.length) {
|
||||
this.getTreePath(() => {
|
||||
this.inputSelected = this.selected.slice(0);
|
||||
});
|
||||
}
|
||||
},
|
||||
initSearchDatas() {
|
||||
if (this.openSearch && this.localdata && this.localdata.length > 0) {
|
||||
const loop = (row, values, texts) => {
|
||||
let value = !!values ? `${values},${row.value}` : row.value;
|
||||
let text = !!texts ? `${texts} ${row.text}` : row.text;
|
||||
if (row.children && row.children.length > 0) {
|
||||
row.children.forEach(x => {
|
||||
loop(x, value, text);
|
||||
});
|
||||
} else {
|
||||
this.searchDatas.push({
|
||||
value,
|
||||
text
|
||||
});
|
||||
}
|
||||
};
|
||||
this.searchDatas = [];
|
||||
this.localdata.forEach(x => {
|
||||
loop(x);
|
||||
});
|
||||
}
|
||||
},
|
||||
getForm(name = 'uniForms') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false;
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
show() {
|
||||
this.isOpened = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.pickerView.updateData({
|
||||
treeData: this._treeData,
|
||||
selected: this.selected,
|
||||
selectedIndex: this.selectedIndex
|
||||
});
|
||||
});
|
||||
},
|
||||
hide() {
|
||||
this.isOpened = false;
|
||||
this.closeSearchDom();
|
||||
},
|
||||
handleInput() {
|
||||
if (this.readonly) {
|
||||
return;
|
||||
}
|
||||
this.show();
|
||||
},
|
||||
handleClose(e) {
|
||||
this.hide();
|
||||
},
|
||||
ondatachange(e) {
|
||||
this._treeData = this.$refs.pickerView._treeData;
|
||||
},
|
||||
onchange(e) {
|
||||
this.hide();
|
||||
this.inputSelected = e;
|
||||
this._dispatchEvent(e);
|
||||
},
|
||||
_processReadonly(dataList, valueArray) {
|
||||
var isTree = dataList.findIndex(item => {
|
||||
return item.children;
|
||||
});
|
||||
if (isTree > -1) {
|
||||
if (Array.isArray(valueArray)) {
|
||||
let inputValue = valueArray[valueArray.length - 1];
|
||||
if (typeof inputValue === 'object' && inputValue.value) {
|
||||
inputValue = inputValue.value;
|
||||
}
|
||||
}
|
||||
this.inputSelected = this._findNodePath(inputValue, this.localdata);
|
||||
return;
|
||||
}
|
||||
|
||||
let result = [];
|
||||
for (let i = 0; i < valueArray.length; i++) {
|
||||
var value = valueArray[i];
|
||||
var item = dataList.find(v => {
|
||||
return v.value == value;
|
||||
});
|
||||
if (item) {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
if (result.length) {
|
||||
this.inputSelected = result;
|
||||
}
|
||||
},
|
||||
_filterForArray(data, valueArray) {
|
||||
var result = [];
|
||||
for (let i = 0; i < valueArray.length; i++) {
|
||||
var value = valueArray[i];
|
||||
var found = data.find(item => {
|
||||
return item.value == value;
|
||||
});
|
||||
if (found) {
|
||||
result.push(found);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
_dispatchEvent(selected) {
|
||||
var value = new Array(selected.length);
|
||||
for (var i = 0; i < selected.length; i++) {
|
||||
value[i] = selected[i].value;
|
||||
}
|
||||
|
||||
if (this.formItem) {
|
||||
const item = selected[selected.length - 1];
|
||||
this.formItem.setValue(item.value);
|
||||
}
|
||||
|
||||
this.$emit('change', {
|
||||
detail: {
|
||||
value: selected
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-data-tree {
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: #dd524d;
|
||||
}
|
||||
|
||||
.input-value {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
font-size: 14px;
|
||||
line-height: 38px;
|
||||
padding: 0 5px;
|
||||
overflow: hidden;
|
||||
/* #ifdef APP-NVUE */
|
||||
height: 40px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.input-value-border {
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.selected-area {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
margin-right: auto;
|
||||
/* #ifdef APP-NVUE */
|
||||
width: 40px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.selected-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.selected-item {
|
||||
flex-direction: row;
|
||||
padding: 0 1px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.input-split-line {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.arrow-area {
|
||||
position: relative;
|
||||
margin-left: auto;
|
||||
width: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
transform: rotate(-45deg);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.input-arrow {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-left: 1px solid #999;
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
.uni-data-tree-cover {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.uni-data-tree-dialog {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 20%;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ffffff;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 102;
|
||||
overflow: hidden;
|
||||
/* #ifdef APP-NVUE */
|
||||
width: 750rpx;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.dialog-caption {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.title-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
font-weight: bold;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.dialog-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.dialog-close-plus {
|
||||
width: 16px;
|
||||
height: 2px;
|
||||
background-color: #666;
|
||||
border-radius: 2px;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.dialog-close-rotate {
|
||||
position: absolute;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.picker-view {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* #ifdef H5 */
|
||||
@media all and (min-width: 768px) {
|
||||
.uni-data-tree-cover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-data-tree-dialog {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
height: auto;
|
||||
min-height: 400px;
|
||||
max-height: 50vh;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 20px 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.dialog-caption {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
153
uni_modules/song-data-picker/components/uni-badge/uni-badge.vue
Normal file
153
uni_modules/song-data-picker/components/uni-badge/uni-badge.vue
Normal file
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<text v-if="text" :class="inverted ? 'uni-badge--' + type + ' uni-badge--' + size + ' uni-badge--' + type + '-inverted' : 'uni-badge--' + type + ' uni-badge--' + size"
|
||||
:style="badgeStyle" class="uni-badge" @click="onClick()">{{ text }}</text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Badge 数字角标
|
||||
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=21
|
||||
* @property {String} text 角标内容
|
||||
* @property {String} type = [default|primary|success|warning|error] 颜色类型
|
||||
* @value default 灰色
|
||||
* @value primary 蓝色
|
||||
* @value success 绿色
|
||||
* @value warning 黄色
|
||||
* @value error 红色
|
||||
* @property {String} size = [normal|small] Badge 大小
|
||||
* @value normal 一般尺寸
|
||||
* @value small 小尺寸
|
||||
* @property {String} inverted = [true|false] 是否无需背景颜色
|
||||
* @event {Function} click 点击 Badge 触发事件
|
||||
* @example <uni-badge text="1"></uni-badge>
|
||||
*/
|
||||
export default {
|
||||
name: 'UniBadge',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
inverted: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
text: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
badgeStyle: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
text() {
|
||||
this.setStyle()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setStyle()
|
||||
},
|
||||
methods: {
|
||||
setStyle() {
|
||||
this.badgeStyle = `width: ${String(this.text).length * 8 + 12}px`
|
||||
},
|
||||
onClick() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$bage-size: 12px;
|
||||
$bage-small: scale(0.8);
|
||||
$bage-height: 20px;
|
||||
|
||||
.uni-badge {
|
||||
/* #ifndef APP-PLUS */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
flex-direction: row;
|
||||
height: $bage-height;
|
||||
line-height: $bage-height;
|
||||
color: $uni-text-color;
|
||||
border-radius: 100px;
|
||||
background-color: $uni-bg-color-hover;
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
font-family: 'Helvetica Neue', Helvetica, sans-serif;
|
||||
font-size: $bage-size;
|
||||
padding: 0px 6px;
|
||||
}
|
||||
|
||||
.uni-badge--inverted {
|
||||
padding: 0 5px 0 0;
|
||||
color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-badge--default {
|
||||
color: $uni-text-color;
|
||||
background-color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-badge--default-inverted {
|
||||
color: $uni-text-color-grey;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--primary {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.uni-badge--primary-inverted {
|
||||
color: $uni-color-primary;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--success {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-success;
|
||||
}
|
||||
|
||||
.uni-badge--success-inverted {
|
||||
color: $uni-color-success;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--warning {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-warning;
|
||||
}
|
||||
|
||||
.uni-badge--warning-inverted {
|
||||
color: $uni-color-warning;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--error {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-badge--error-inverted {
|
||||
color: $uni-color-error;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--small {
|
||||
transform: $bage-small;
|
||||
transform-origin: center center;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,468 @@
|
||||
export default {
|
||||
props: {
|
||||
localdata: {
|
||||
type: [Array, Object],
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
collection: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
field: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
orderby: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
where: {
|
||||
type: [String, Object],
|
||||
default: ''
|
||||
},
|
||||
pageData: {
|
||||
type: String,
|
||||
default: 'add'
|
||||
},
|
||||
pageCurrent: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
getcount: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
getone: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
gettree: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
manual: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: [Array, String, Number],
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
preload: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
stepSearh: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
selfField: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
parentField: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
errorMessage: '',
|
||||
loadMore: {
|
||||
contentdown: '',
|
||||
contentrefresh: '',
|
||||
contentnomore: ''
|
||||
},
|
||||
dataList: [],
|
||||
selected: [],
|
||||
selectedIndex: 0,
|
||||
page: {
|
||||
current: this.pageCurrent,
|
||||
size: this.pageSize,
|
||||
count: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isLocaldata() {
|
||||
return this.localdata.length > 0
|
||||
},
|
||||
postField() {
|
||||
return `${this.field}, ${this.parentField} as parent_value`
|
||||
},
|
||||
postWhere() {
|
||||
let result = []
|
||||
let selected = this.selected
|
||||
result.push(`${this.parentField} == null`)
|
||||
if (selected.length) {
|
||||
for (var i = 0; i < selected.length - 1; i++) {
|
||||
result.push(`${this.parentField} == '${selected[i].value}'`)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.where) {
|
||||
return `(${this.where}) && (${result.join(' || ')})`
|
||||
}
|
||||
|
||||
return result.join(' || ')
|
||||
},
|
||||
nodeWhere() {
|
||||
let result = []
|
||||
let selected = this.selected
|
||||
if (selected.length) {
|
||||
result.push(`${this.parentField} == '${selected[selected.length - 1].value}'`)
|
||||
}
|
||||
|
||||
if (this.where) {
|
||||
return `(${this.where}) && (${result.join(' || ')})`
|
||||
}
|
||||
|
||||
return result.join(' || ')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$watch(() => {
|
||||
var al = [];
|
||||
['pageCurrent',
|
||||
'pageSize',
|
||||
'value',
|
||||
'localdata',
|
||||
'collection',
|
||||
'action',
|
||||
'field',
|
||||
'orderby',
|
||||
'where',
|
||||
'getont',
|
||||
'getcount',
|
||||
'gettree'
|
||||
].forEach(key => {
|
||||
al.push(this[key])
|
||||
});
|
||||
return al
|
||||
}, (newValue, oldValue) => {
|
||||
let needReset = false
|
||||
for (let i = 2; i < newValue.length; i++) {
|
||||
if (newValue[i] != oldValue[i]) {
|
||||
needReset = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (newValue[0] != oldValue[0]) {
|
||||
this.page.current = this.pageCurrent
|
||||
}
|
||||
this.page.size = this.pageSize
|
||||
|
||||
this.onPropsChange()
|
||||
})
|
||||
this._treeData = []
|
||||
},
|
||||
methods: {
|
||||
onPropsChange() {
|
||||
this._treeData = []
|
||||
},
|
||||
getCommand(options = {}) {
|
||||
/* eslint-disable no-undef */
|
||||
let db = uniCloud.database()
|
||||
|
||||
const action = options.action || this.action
|
||||
if (action) {
|
||||
db = db.action(action)
|
||||
}
|
||||
|
||||
const collection = options.collection || this.collection
|
||||
db = db.collection(collection)
|
||||
|
||||
const where = options.where || this.where
|
||||
if (!(!where || !Object.keys(where).length)) {
|
||||
db = db.where(where)
|
||||
}
|
||||
|
||||
const field = options.field || this.field
|
||||
if (field) {
|
||||
db = db.field(field)
|
||||
}
|
||||
|
||||
const orderby = options.orderby || this.orderby
|
||||
if (orderby) {
|
||||
db = db.orderBy(orderby)
|
||||
}
|
||||
|
||||
const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current
|
||||
const size = options.pageSize !== undefined ? options.pageSize : this.page.size
|
||||
const getCount = options.getcount !== undefined ? options.getcount : this.getcount
|
||||
const getTree = options.gettree !== undefined ? options.gettree : this.gettree
|
||||
|
||||
const getOptions = {
|
||||
getCount,
|
||||
getTree
|
||||
}
|
||||
if (options.getTreePath) {
|
||||
getOptions.getTreePath = options.getTreePath
|
||||
}
|
||||
|
||||
db = db.skip(size * (current - 1)).limit(size).get(getOptions)
|
||||
|
||||
return db
|
||||
},
|
||||
getTreePath(callback) {
|
||||
if (this.loading) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
|
||||
this.getCommand({
|
||||
field: this.postField,
|
||||
getTreePath: {
|
||||
startWith: `${this.selfField}=='${this.value}'`
|
||||
}
|
||||
}).then((res) => {
|
||||
this.loading = false
|
||||
let treePath = []
|
||||
this._extractTreePath(res.result.data, treePath)
|
||||
this.selected = treePath
|
||||
callback && callback()
|
||||
}).catch((err) => {
|
||||
this.loading = false
|
||||
this.errorMessage = err
|
||||
})
|
||||
},
|
||||
loadData() {
|
||||
if (this.isLocaldata) {
|
||||
this._processLocalData()
|
||||
return
|
||||
}
|
||||
|
||||
if (this.value.length) {
|
||||
this._loadNodeData((data) => {
|
||||
this._treeData = data
|
||||
this._updateBindData()
|
||||
this._updateSelected()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (this.stepSearh) {
|
||||
this._loadNodeData((data) => {
|
||||
this._treeData = data
|
||||
this._updateBindData()
|
||||
})
|
||||
} else {
|
||||
this._loadAllData((data) => {
|
||||
this._treeData = []
|
||||
this._extractTree(data, this._treeData, null)
|
||||
this._updateBindData()
|
||||
})
|
||||
}
|
||||
},
|
||||
_loadAllData(callback) {
|
||||
if (this.loading) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
|
||||
this.getCommand({
|
||||
field: this.postField,
|
||||
gettree: true,
|
||||
startwith: `${this.selfField}=='${this.value}'`
|
||||
}).then((res) => {
|
||||
this.loading = false
|
||||
callback(res.result.data)
|
||||
this.onDataChange()
|
||||
}).catch((err) => {
|
||||
this.loading = false
|
||||
this.errorMessage = err
|
||||
})
|
||||
},
|
||||
_loadNodeData(callback, pw) {
|
||||
if (this.loading) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
|
||||
this.getCommand({
|
||||
field: this.postField,
|
||||
where: pw || this.postWhere,
|
||||
pageSize: 500
|
||||
}).then((res) => {
|
||||
this.loading = false
|
||||
callback(res.result.data)
|
||||
this.onDataChange()
|
||||
}).catch((err) => {
|
||||
this.loading = false
|
||||
this.errorMessage = err
|
||||
})
|
||||
},
|
||||
_updateSelected() {
|
||||
var dl = this.dataList
|
||||
var sl = this.selected
|
||||
for (var i = 0; i < sl.length; i++) {
|
||||
var value = sl[i].value
|
||||
var dl2 = dl[i]
|
||||
for (var j = 0; j < dl2.length; j++) {
|
||||
var item2 = dl2[j]
|
||||
if (item2.value === value) {
|
||||
sl[i].text = item2.text
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_updateBindData(node) {
|
||||
const {
|
||||
dataList,
|
||||
hasNodes
|
||||
} = this._filterData(this._treeData, this.selected)
|
||||
|
||||
let isleaf = this._stepSearh === false && !hasNodes
|
||||
|
||||
if (node) {
|
||||
node.isleaf = isleaf
|
||||
}
|
||||
|
||||
this.dataList = dataList
|
||||
this.selectedIndex = dataList.length - 1
|
||||
|
||||
if (!isleaf && this.selected.length < dataList.length) {
|
||||
this.selected.push({
|
||||
value: null,
|
||||
text: "请选择"
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
isleaf,
|
||||
hasNodes
|
||||
}
|
||||
},
|
||||
_filterData(data, paths) {
|
||||
let dataList = []
|
||||
|
||||
let hasNodes = true
|
||||
|
||||
dataList.push(data.filter((item) => {
|
||||
return item.parent_value === undefined
|
||||
}))
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
var value = paths[i].value
|
||||
var nodes = data.filter((item) => {
|
||||
return item.parent_value === value
|
||||
})
|
||||
|
||||
if (nodes.length) {
|
||||
dataList.push(nodes)
|
||||
} else {
|
||||
hasNodes = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
dataList,
|
||||
hasNodes
|
||||
}
|
||||
},
|
||||
_extractTree(nodes, result, parent_value) {
|
||||
let list = result || []
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let node = nodes[i]
|
||||
|
||||
let child = {}
|
||||
for (let key in node) {
|
||||
if (key !== 'children') {
|
||||
child[key] = node[key]
|
||||
}
|
||||
}
|
||||
if (parent_value !== null) {
|
||||
child.parent_value = parent_value
|
||||
}
|
||||
result.push(child)
|
||||
|
||||
let children = node.children
|
||||
if (children) {
|
||||
this._extractTree(children, result, node.value)
|
||||
}
|
||||
}
|
||||
},
|
||||
_extractTreePath(nodes, result) {
|
||||
let list = result || []
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let node = nodes[i]
|
||||
|
||||
let child = {}
|
||||
for (let key in node) {
|
||||
if (key !== 'children') {
|
||||
child[key] = node[key]
|
||||
}
|
||||
}
|
||||
result.push(child)
|
||||
|
||||
let children = node.children
|
||||
if (children) {
|
||||
this._extractTreePath(children, result)
|
||||
}
|
||||
}
|
||||
},
|
||||
_findNodePath(key, nodes, path = []) {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let {
|
||||
value,
|
||||
text,
|
||||
children
|
||||
} = nodes[i]
|
||||
|
||||
path.push({
|
||||
value,
|
||||
text
|
||||
})
|
||||
|
||||
if (value === key) {
|
||||
return path
|
||||
}
|
||||
|
||||
if (children) {
|
||||
const p = this._findNodePath(key, children, path)
|
||||
if (p.length) {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
path.pop()
|
||||
}
|
||||
return []
|
||||
},
|
||||
_processLocalData() {
|
||||
this._treeData = []
|
||||
this._extractTree(this.localdata, this._treeData)
|
||||
|
||||
var inputValue = this.value
|
||||
if (inputValue === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Array.isArray(inputValue)) {
|
||||
inputValue = inputValue[inputValue.length - 1]
|
||||
if (typeof inputValue === 'object' && inputValue.value) {
|
||||
inputValue = inputValue.value
|
||||
}
|
||||
}
|
||||
|
||||
this.selected = this._findNodePath(inputValue, this.localdata)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,271 @@
|
||||
<template>
|
||||
<view class="uni-data-pickerview">
|
||||
<scroll-view class="selected-area" scroll-x="true" scroll-y="false" :show-scrollbar="false">
|
||||
<view class="selected-list">
|
||||
<view class="selected-item" :class="{'selected-item-active':index==selectedIndex}" v-for="(item,index) in selected"
|
||||
:key="index" v-if="item.text" @click="handleSelect(index)">
|
||||
<text class="">{{item.text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="tab-c">
|
||||
<scroll-view class="list" v-for="(child, i) in dataList" :key="i" v-if="i==selectedIndex" :scroll-y="true">
|
||||
<view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in child" :key="j" @click="handleNodeClick(item, i, j)">
|
||||
<text class="item-text">{{item.text}}</text>
|
||||
<view class="check" v-if="selected.length > i && item.value == selected[i].value"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="loading-cover" v-if="loading">
|
||||
<uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
|
||||
</view>
|
||||
<view class="error-message" v-if="errorMessage">
|
||||
<text class="error-text">{{errorMessage}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dataPicker from "./uni-data-picker.js"
|
||||
|
||||
/**
|
||||
* uni-data-pickerview
|
||||
* @description uni-data-pickerview
|
||||
* @tutorial https://uniapp.dcloud.net.cn/uniCloud/uni-data-picker
|
||||
* @property {Array} localdata 本地数据,参考
|
||||
* @property {Boolean} step-searh = [true|false] 是否分布查询
|
||||
* @value true 启用分布查询,仅查询当前选中节点
|
||||
* @value false 关闭分布查询,一次查询出所有数据
|
||||
* @property {String|DBFieldString} self-field 分布查询当前字段名称
|
||||
* @property {String|DBFieldString} parent-field 分布查询父字段名称
|
||||
* @property {String|DBCollectionString} collection 表名
|
||||
* @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
|
||||
* @property {String} orderby 排序字段及正序倒叙设置
|
||||
* @property {String|JQLString} where 查询条件
|
||||
*/
|
||||
export default {
|
||||
name: 'UniDataPickerView',
|
||||
mixins: [dataPicker],
|
||||
props: {
|
||||
managedMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
created() {
|
||||
if (this.managedMode) {
|
||||
return
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.load()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onPropsChange() {
|
||||
this._treeData = []
|
||||
this.selectedIndex = 0
|
||||
this.load()
|
||||
},
|
||||
load() {
|
||||
if (this.isLocaldata) {
|
||||
this.loadData()
|
||||
} else if (this.value.length) {
|
||||
this.getTreePath((res) => {
|
||||
this.loadData()
|
||||
})
|
||||
}
|
||||
},
|
||||
handleSelect(index) {
|
||||
this.selectedIndex = index
|
||||
},
|
||||
handleNodeClick(item, i, j) {
|
||||
if (item.disable) {
|
||||
return
|
||||
}
|
||||
|
||||
const node = this.dataList[i][j]
|
||||
const {
|
||||
value,
|
||||
text
|
||||
} = node
|
||||
|
||||
if (i < this.selected.length - 1) {
|
||||
this.selected.splice(i, this.selected.length - i)
|
||||
this.selected.push(node)
|
||||
} else if (i === this.selected.length - 1) {
|
||||
this.selected[i] = node
|
||||
}
|
||||
|
||||
if (node.isleaf) {
|
||||
this.onSelectedChange(node, node.isleaf)
|
||||
return
|
||||
}
|
||||
|
||||
const {
|
||||
isleaf,
|
||||
hasNodes
|
||||
} = this._updateBindData()
|
||||
|
||||
if (this.isLocaldata && (!hasNodes || isleaf)) {
|
||||
this.onSelectedChange(node, true)
|
||||
return
|
||||
}
|
||||
|
||||
if (!isleaf && !hasNodes) {
|
||||
this._loadNodeData((data) => {
|
||||
if (!data.length) {
|
||||
node.isleaf = true
|
||||
} else {
|
||||
this._treeData.push(...data)
|
||||
this._updateBindData(node)
|
||||
}
|
||||
this.onSelectedChange(node, node.isleaf)
|
||||
}, this.nodeWhere)
|
||||
return
|
||||
}
|
||||
|
||||
this.onSelectedChange(node, false)
|
||||
},
|
||||
updateData(data) {
|
||||
this._treeData = data.treeData
|
||||
this.selected = data.selected
|
||||
if (!this._treeData.length) {
|
||||
this.loadData()
|
||||
} else {
|
||||
//this.selected = data.selected
|
||||
this._updateBindData()
|
||||
}
|
||||
},
|
||||
onDataChange() {
|
||||
this.$emit('datachange')
|
||||
},
|
||||
onSelectedChange(node, isleaf) {
|
||||
if (isleaf) {
|
||||
this._dispatchEvent()
|
||||
} else if (node) {
|
||||
this.$emit('nodeclick', node)
|
||||
}
|
||||
},
|
||||
_dispatchEvent() {
|
||||
this.$emit('change', this.selected.slice(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-data-pickerview {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: #DD524D;
|
||||
}
|
||||
|
||||
.loading-cover {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(255, 255, 255, .5);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 15px;
|
||||
opacity: .9;
|
||||
z-index: 102;
|
||||
}
|
||||
|
||||
/* #ifdef APP-NVUE */
|
||||
.selected-area {
|
||||
width: 750rpx;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.selected-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
padding: 0 5px;
|
||||
border-bottom: 1px solid #f8f8f8;
|
||||
}
|
||||
|
||||
.selected-item {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
padding: 12px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.selected-item-active {
|
||||
border-bottom: 2px solid #007aff;
|
||||
}
|
||||
|
||||
.selected-item-text {
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.tab-c {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.list {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 12px 15px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.is-disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
flex: 1;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.check {
|
||||
margin-right: 5px;
|
||||
border: 2px solid #007aff;
|
||||
border-left: 0;
|
||||
border-top: 0;
|
||||
height: 12px;
|
||||
width: 6px;
|
||||
transform-origin: center;
|
||||
transition: all 0.3s;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @desc 函数防抖
|
||||
* @param func 目标函数
|
||||
* @param wait 延迟执行毫秒数
|
||||
* @param immediate true - 立即执行, false - 延迟执行
|
||||
*/
|
||||
export const debounce = function(func, wait = 1000, immediate = true) {
|
||||
let timer;
|
||||
console.log(1);
|
||||
return function() {
|
||||
console.log(123);
|
||||
let context = this,
|
||||
args = arguments;
|
||||
if (timer) clearTimeout(timer);
|
||||
if (immediate) {
|
||||
let callNow = !timer;
|
||||
timer = setTimeout(() => {
|
||||
timer = null;
|
||||
}, wait);
|
||||
if (callNow) func.apply(context, args);
|
||||
} else {
|
||||
timer = setTimeout(() => {
|
||||
func.apply(context, args);
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @desc 函数节流
|
||||
* @param func 函数
|
||||
* @param wait 延迟执行毫秒数
|
||||
* @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
|
||||
*/
|
||||
export const throttle = (func, wait = 1000, type = 1) => {
|
||||
let previous = 0;
|
||||
let timeout;
|
||||
return function() {
|
||||
let context = this;
|
||||
let args = arguments;
|
||||
if (type === 1) {
|
||||
let now = Date.now();
|
||||
|
||||
if (now - previous > wait) {
|
||||
func.apply(context, args);
|
||||
previous = now;
|
||||
}
|
||||
} else if (type === 2) {
|
||||
if (!timeout) {
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null;
|
||||
func.apply(context, args)
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,401 @@
|
||||
<template>
|
||||
<view class="uni-easyinput" :class="{'uni-easyinput-error':msg}" :style="{color:inputBorder && msg?'#dd524d':styles.color}">
|
||||
<view class="uni-easyinput__content" :class="{'is-input-border':inputBorder ,'is-input-error-border':inputBorder && msg,'is-textarea':type==='textarea','is-disabled':disabled}"
|
||||
:style="{'border-color':inputBorder && msg?'#dd524d':styles.borderColor,'background-color':disabled?styles.disableColor:'#fff'}">
|
||||
<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')"></uni-icons>
|
||||
<textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{'input-padding':inputBorder}"
|
||||
:name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled"
|
||||
:maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" @input="onInput" @blur="onBlur" @focus="onFocus"
|
||||
@confirm="onConfirm"></textarea>
|
||||
<input v-else :type="type === 'password'?'text':type" class="uni-easyinput__content-input" :style="{
|
||||
'padding-right':type === 'password' ||clearable || prefixIcon?'':'10px',
|
||||
'padding-left':prefixIcon?'':'10px'
|
||||
}"
|
||||
:name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder"
|
||||
:placeholderStyle="placeholderStyle" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" @focus="onFocus"
|
||||
@blur="onBlur" @input="onInput" @confirm="onConfirm" />
|
||||
<template v-if="type === 'password'">
|
||||
<uni-icons v-if="val != '' " class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" :type="showPassword?'eye-slash-filled':'eye-filled'"
|
||||
:size="18" color="#c0c4cc" @click="onEyes"></uni-icons>
|
||||
</template>
|
||||
<template v-else-if="suffixIcon">
|
||||
<uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')"></uni-icons>
|
||||
</template>
|
||||
<template v-else>
|
||||
<uni-icons class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" type="clear" :size="clearSize"
|
||||
v-if="clearable && focused && val " color="#c0c4cc" @click="onClear"></uni-icons>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Field 输入框
|
||||
* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=21001
|
||||
* @property {String| Number} value 输入内容
|
||||
* @property {String } type 输入框的类型(默认text) password/text/textarea/..
|
||||
* @value text 文本输入键盘
|
||||
* @value textarea 多行文本输入键盘
|
||||
* @value password 密码输入键盘
|
||||
* @value number 数字输入键盘,注意iOS上app-vue弹出的数字键盘并非9宫格方式
|
||||
* @value idcard 身份证输入键盘,信、支付宝、百度、QQ小程序
|
||||
* @value digit 带小数点的数字键盘 ,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持
|
||||
* @property {Boolean} clearable 是否显示右侧清空内容的图标控件(输入框有内容,且获得焦点时才显示),点击可清空输入框内容(默认true)
|
||||
* @property {Boolean} autoHeight 是否自动增高输入区域,type为textarea时有效(默认true)
|
||||
* @property {String } placeholder 输入框的提示文字
|
||||
* @property {String } placeholderStyle placeholder的样式(内联样式,字符串),如"color: #ddd"
|
||||
* @property {Boolean} focus 是否自动获得焦点(默认false)
|
||||
* @property {Boolean} disabled 是否不可输入(默认false)
|
||||
* @property {Number } maxlength 最大输入长度,设置为 -1 的时候不限制最大长度(默认140)
|
||||
* @property {String } confirmType 设置键盘右下角按钮的文字,仅在type="text"时生效(默认done)
|
||||
* @property {Number } clearSize 清除图标的大小,单位px(默认15)
|
||||
* @property {String} prefixIcon 输入框头部图标
|
||||
* @property {String} suffixIcon 输入框尾部图标
|
||||
* @property {Boolean} trim 是否自动去除两端的空格
|
||||
* @property {Boolean} inputBorder 是否显示input输入框的边框(默认false)
|
||||
* @property {Object} styles 自定义颜色
|
||||
* @event {Function} input 输入框内容发生变化时触发
|
||||
* @event {Function} focus 输入框获得焦点时触发
|
||||
* @event {Function} blur 输入框失去焦点时触发
|
||||
* @event {Function} confirm 点击完成按钮时触发
|
||||
* @event {Function} iconClick 点击图标时触发
|
||||
* @example <uni-easyinput v-model="mobile"></uni-easyinput>
|
||||
*/
|
||||
|
||||
import {
|
||||
debounce,
|
||||
throttle
|
||||
} from './common.js'
|
||||
|
||||
export default {
|
||||
name: 'uni-easyinput',
|
||||
props: {
|
||||
name: String,
|
||||
value: [Number, String],
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoHeight: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: String,
|
||||
placeholderStyle: String,
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxlength: {
|
||||
type: [Number, String],
|
||||
default: 140
|
||||
},
|
||||
confirmType: {
|
||||
type: String,
|
||||
default: 'done'
|
||||
},
|
||||
// 清除按钮的大小
|
||||
clearSize: {
|
||||
type: [Number, String],
|
||||
default: 15
|
||||
},
|
||||
// 是否显示 input 边框
|
||||
inputBorder: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
prefixIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
suffixIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否自动去除两端的空格
|
||||
trim: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 自定义样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
color: '#333',
|
||||
disableColor: '#eee',
|
||||
borderColor: '#e5e5e5'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
focused: false,
|
||||
errMsg: '',
|
||||
val: '',
|
||||
showMsg: '',
|
||||
border: false,
|
||||
isFirstBorder: false,
|
||||
showClearIcon: false,
|
||||
showPassword: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
msg() {
|
||||
return this.errorMessage || this.errMsg;
|
||||
},
|
||||
// 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,给用户可以传入字符串数值
|
||||
inputMaxlength() {
|
||||
return Number(this.maxlength);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
if (this.errMsg) this.errMsg = ''
|
||||
this.val = newVal
|
||||
if (this.formItem) {
|
||||
this.formItem.setValue(newVal)
|
||||
}
|
||||
},
|
||||
focus(newVal) {
|
||||
this.$nextTick(() => {
|
||||
this.focused = this.focus
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.val = this.value
|
||||
this.form = this.getForm('uniForms')
|
||||
this.formItem = this.getForm('uniFormsItem')
|
||||
if (this.formItem) {
|
||||
if (this.formItem.name) {
|
||||
this.rename = this.formItem.name
|
||||
this.form.inputChildrens.push(this)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
mounted() {
|
||||
// this.onInput = throttle(this.input, 500)
|
||||
this.$nextTick(() => {
|
||||
this.focused = this.focus
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化变量值
|
||||
*/
|
||||
init() {
|
||||
|
||||
},
|
||||
onClickIcon(type) {
|
||||
this.$emit('iconClick', type)
|
||||
},
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getForm(name = 'uniForms') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false;
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
|
||||
onEyes() {
|
||||
this.showPassword = !this.showPassword
|
||||
},
|
||||
onInput(event) {
|
||||
let value = event.detail.value;
|
||||
// 判断是否去除空格
|
||||
if (this.trim) value = this.trimStr(value);
|
||||
if (this.errMsg) this.errMsg = ''
|
||||
this.val = value
|
||||
this.$emit('input', value);
|
||||
},
|
||||
|
||||
onFocus(event) {
|
||||
this.focused = true;
|
||||
this.$emit('focus', event);
|
||||
},
|
||||
onBlur(event) {
|
||||
let value = event.detail.value;
|
||||
// 最开始使用的是监听图标@touchstart事件,自从hx2.8.4后,此方法在微信小程序出错
|
||||
// 这里改为监听点击事件,手点击清除图标时,同时也发生了@blur事件,导致图标消失而无法点击,这里做一个延时
|
||||
setTimeout(() => {
|
||||
this.focused = false;
|
||||
}, 100);
|
||||
this.$emit('blur', event);
|
||||
},
|
||||
onConfirm(e) {
|
||||
this.$emit('confirm', e.detail.value);
|
||||
},
|
||||
onClear(event) {
|
||||
this.val = '';
|
||||
this.$emit('input', '');
|
||||
},
|
||||
fieldClick() {
|
||||
this.$emit('click');
|
||||
},
|
||||
trimStr(str, pos = 'both') {
|
||||
if (pos == 'both') {
|
||||
return str.replace(/^\s+|\s+$/g, '');
|
||||
} else if (pos == 'left') {
|
||||
return str.replace(/^\s*/, '');
|
||||
} else if (pos == 'right') {
|
||||
return str.replace(/(\s*$)/g, '');
|
||||
} else if (pos == 'all') {
|
||||
return str.replace(/\s+/g, '');
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-easyinput {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
position: relative;
|
||||
// padding: 16px 14px;
|
||||
text-align: left;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.uni-easyinput__content {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
min-height: 36px;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
width: auto;
|
||||
line-height: 2;
|
||||
font-size: 14px;
|
||||
// padding-right: 10px;
|
||||
}
|
||||
|
||||
.is-textarea {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.is-textarea-icon {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-textarea {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
width: auto;
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
// padding-right: 10px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 10px;
|
||||
// box-sizing: border-box;
|
||||
min-height: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.input-padding {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.content-clear-icon {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.label-icon {
|
||||
margin-right: 5px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
// 显示边框
|
||||
.is-input-border {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border: 1px solid $uni-border-color;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.uni-easyinput__right {
|
||||
// margin-left: 5px;
|
||||
}
|
||||
|
||||
// 必填
|
||||
.is-required {
|
||||
color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-error-message {
|
||||
position: absolute;
|
||||
bottom: -17px;
|
||||
left: 0;
|
||||
line-height: 12px;
|
||||
color: $uni-color-error;
|
||||
font-size: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uni-error-msg--boeder {
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.is-input-error-border {
|
||||
border-color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-easyinput--border {
|
||||
margin-bottom: 0;
|
||||
padding: 10px 15px;
|
||||
// padding-bottom: 0;
|
||||
border-top: 1px #eee solid;
|
||||
}
|
||||
|
||||
.uni-easyinput-error {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.is-first-border {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.is-disabled {
|
||||
background-color: #eee;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,440 @@
|
||||
<template>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<cell>
|
||||
<!-- #endif -->
|
||||
|
||||
<view
|
||||
:class="{ 'uni-list-item--disabled': disabled }"
|
||||
:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
|
||||
class="uni-list-item"
|
||||
@click.stop="onClick"
|
||||
>
|
||||
<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
|
||||
<view class="uni-list-item__container" :class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column' }">
|
||||
<slot name="header">
|
||||
<view class="uni-list-item__header">
|
||||
<view v-if="thumb" class="uni-list-item__icon"><image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" /></view>
|
||||
<view v-else-if="showExtraIcon" class="uni-list-item__icon"><uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" /></view>
|
||||
</view>
|
||||
</slot>
|
||||
<slot name="body">
|
||||
<view class="uni-list-item__content" :class="{ 'uni-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }">
|
||||
<text v-if="title" class="uni-list-item__content-title" :class="[ellipsis !== 0 && ellipsis <= 2 ? 'uni-ellipsis-' + ellipsis : '']">{{ title }}</text>
|
||||
<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
|
||||
</view>
|
||||
</slot>
|
||||
<slot name="footer">
|
||||
<view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra" :class="{ 'flex--justify': direction === 'column' }">
|
||||
<text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
|
||||
<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" />
|
||||
<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked" @change="onSwitchChange" />
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<uni-icons v-if="showArrow || link" :size="16" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
|
||||
</view>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
</cell>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
|
||||
import uniBadge from '../uni-badge/uni-badge.vue';
|
||||
|
||||
/**
|
||||
* ListItem 列表子组件
|
||||
* @description 列表子组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||
* @property {String} title 标题
|
||||
* @property {String} note 描述
|
||||
* @property {String} thumb 左侧缩略图,若thumb有值,则不会显示扩展图标
|
||||
* @property {String} thumbSize = [lg|base|sm] 略缩图大小
|
||||
* @value lg 大图
|
||||
* @value base 一般
|
||||
* @value sm 小图
|
||||
* @property {String} badgeText 数字角标内容
|
||||
* @property {String} badgeType 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
|
||||
* @property {String} rightText 右侧文字内容
|
||||
* @property {Boolean} disabled = [true|false] 是否禁用
|
||||
* @property {Boolean} clickable = [true|false] 是否开启点击反馈
|
||||
* @property {String} link = [navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈
|
||||
* @value navigateTo 同 uni.navigateTo()
|
||||
* @value redirectTo 同 uni.redirectTo()
|
||||
* @value reLaunch 同 uni.reLaunch()
|
||||
* @value switchTab 同 uni.switchTab()
|
||||
* @property {String | PageURIString} to 跳转目标页面
|
||||
* @property {Boolean} showBadge = [true|false] 是否显示数字角标
|
||||
* @property {Boolean} showSwitch = [true|false] 是否显示Switch
|
||||
* @property {Boolean} switchChecked = [true|false] Switch是否被选中
|
||||
* @property {Boolean} showExtraIcon = [true|false] 左侧是否显示扩展图标
|
||||
* @property {Object} extraIcon 扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
|
||||
* @property {String} direction = [row|column] 排版方向
|
||||
* @value row 水平排列
|
||||
* @value column 垂直排列
|
||||
* @event {Function} click 点击 uniListItem 触发事件
|
||||
* @event {Function} switchChange 点击切换 Switch 时触发
|
||||
*/
|
||||
export default {
|
||||
name: 'UniListItem',
|
||||
components: {
|
||||
uniIcons,
|
||||
uniBadge
|
||||
},
|
||||
props: {
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'row'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
note: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
ellipsis: {
|
||||
type: [Number],
|
||||
default: 0
|
||||
},
|
||||
disabled: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
clickable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showArrow: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
link: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
to: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
showBadge: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showSwitch: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
switchChecked: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
badgeText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
badgeType: {
|
||||
type: String,
|
||||
default: 'success'
|
||||
},
|
||||
rightText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
thumb: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
thumbSize: {
|
||||
type: String,
|
||||
default: 'base'
|
||||
},
|
||||
showExtraIcon: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
extraIcon: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
type: 'contact',
|
||||
color: '#000000',
|
||||
size: 20
|
||||
};
|
||||
}
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
// inject: ['list'],
|
||||
data() {
|
||||
return {
|
||||
isFirstChild: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.list = this.getForm()
|
||||
// 判断是否存在 uni-list 组件
|
||||
if(this.list){
|
||||
if (!this.list.firstChildAppend) {
|
||||
this.list.firstChildAppend = true;
|
||||
this.isFirstChild = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getForm(name = 'uniList') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
onClick() {
|
||||
if (this.to !== '') {
|
||||
this.openPage();
|
||||
return;
|
||||
}
|
||||
if (this.clickable || this.link) {
|
||||
this.$emit('click', {
|
||||
data: {}
|
||||
});
|
||||
}
|
||||
},
|
||||
onSwitchChange(e) {
|
||||
this.$emit('switchChange', e.detail);
|
||||
},
|
||||
openPage() {
|
||||
if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
|
||||
this.pageApi(this.link);
|
||||
} else {
|
||||
this.pageApi('navigateTo');
|
||||
}
|
||||
},
|
||||
pageApi(api) {
|
||||
uni[api]({
|
||||
url: this.to,
|
||||
success: res => {
|
||||
this.$emit('click', {
|
||||
data: res
|
||||
});
|
||||
},
|
||||
fail: err => {
|
||||
this.$emit('click', {
|
||||
data: err
|
||||
});
|
||||
console.error(err.errMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
|
||||
|
||||
.uni-list-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
font-size: $uni-font-size-lg;
|
||||
position: relative;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-list-item--disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.uni-list-item--hover {
|
||||
background-color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-list-item__container {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
padding: $list-item-pd;
|
||||
padding-left: $uni-spacing-row-lg;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
// align-items: center;
|
||||
}
|
||||
|
||||
.container--right {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
// .border--left {
|
||||
// margin-left: $uni-spacing-row-lg;
|
||||
// }
|
||||
|
||||
.uni-list--border {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
/* #ifdef APP-NVUE */
|
||||
border-top-color: $uni-border-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 0.5px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-list--border:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: '';
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: $uni-border-color;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.uni-list-item__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
padding-right: 8px;
|
||||
flex: 1;
|
||||
color: #3b4144;
|
||||
// overflow: hidden;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-item__content--center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.uni-list-item__content-title {
|
||||
font-size: $uni-font-size-base;
|
||||
color: #3b4144;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-item__content-note {
|
||||
margin-top: 6rpx;
|
||||
color: $uni-text-color-grey;
|
||||
font-size: $uni-font-size-sm;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-item__extra {
|
||||
// width: 25%;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-list-item__header {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-list-item__icon {
|
||||
margin-right: 18rpx;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-list-item__icon-img {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
height: $uni-img-size-base;
|
||||
width: $uni-img-size-base;
|
||||
}
|
||||
|
||||
.uni-icon-wrapper {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.flex--direction {
|
||||
flex-direction: column;
|
||||
/* #ifndef APP-NVUE */
|
||||
align-items: initial;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.flex--justify {
|
||||
/* #ifndef APP-NVUE */
|
||||
justify-content: initial;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-list--lg {
|
||||
height: $uni-img-size-lg;
|
||||
width: $uni-img-size-lg;
|
||||
}
|
||||
|
||||
.uni-list--base {
|
||||
height: $uni-img-size-base;
|
||||
width: $uni-img-size-base;
|
||||
}
|
||||
|
||||
.uni-list--sm {
|
||||
height: $uni-img-size-sm;
|
||||
width: $uni-img-size-sm;
|
||||
}
|
||||
|
||||
.uni-list-item__extra-text {
|
||||
color: $uni-text-color-grey;
|
||||
font-size: $uni-font-size-sm;
|
||||
}
|
||||
.uni-ellipsis-1 {
|
||||
/* #ifndef APP-NVUE */
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-ellipsis-2 {
|
||||
/* #ifndef APP-NVUE */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 2;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "29",
|
||||
"name": "LoadMore",
|
||||
"desc": "加载更多",
|
||||
"url": "load-more",
|
||||
"type": "功能组件",
|
||||
"edition": "1.1.5",
|
||||
"path": "https://ext.dcloud.net.cn/plugin?id=29",
|
||||
"update_log": "- 新增 颜色大小等配置项"
|
||||
}
|
File diff suppressed because one or more lines are too long
95
uni_modules/song-data-picker/manifest.json
Normal file
95
uni_modules/song-data-picker/manifest.json
Normal file
@ -0,0 +1,95 @@
|
||||
{
|
||||
"name" : "",
|
||||
"appid" : "",
|
||||
"description": "应用描述",
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": "100",
|
||||
"transformPx": false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus": {
|
||||
"usingComponents": true,
|
||||
"splashscreen": {
|
||||
"alwaysShowBeforeRender": true,
|
||||
"waiting": true,
|
||||
"autoclose": true,
|
||||
"delay": 0
|
||||
},
|
||||
"modules": {
|
||||
"OAuth": {},
|
||||
"Payment": {},
|
||||
"Push": {},
|
||||
"Share": {},
|
||||
"Speech": {},
|
||||
"VideoPlayer": {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute": {
|
||||
/* android打包配置 */
|
||||
"android": {
|
||||
"permissions": [
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_MOCK_LOCATION\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_TASKS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_SMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>",
|
||||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
|
||||
"<uses-permission android:name=\"android.permission.SEND_SMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.RECEIVE_USER_PRESENT\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios": {
|
||||
"UIBackgroundModes": ["audio"]
|
||||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs": {
|
||||
"speech": {
|
||||
"ifly": {}
|
||||
}
|
||||
},
|
||||
"orientation": ["portrait-primary"]
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp": {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin": {
|
||||
"appid": "",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
},
|
||||
"usingComponents": true
|
||||
},
|
||||
"h5": {
|
||||
"template": "template.h5.html",
|
||||
"router": {
|
||||
"mode": "history",
|
||||
"base": "/h5/"
|
||||
}
|
||||
}
|
||||
}
|
13
uni_modules/song-data-picker/package.json
Normal file
13
uni_modules/song-data-picker/package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "song-data-picker",
|
||||
"name": "基于DataPicker(uni-data-picker)的带有搜索功能的选择器",
|
||||
"version": "0.1.2",
|
||||
"description": "在uni官方的DataPicker(uni-data-picker)基础上添加搜索功能",
|
||||
"keywords": [
|
||||
"picker",
|
||||
"级联",
|
||||
"省市区",
|
||||
"地址",
|
||||
"搜索"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user