渠道商

This commit is contained in:
Mr.jiang 2024-08-26 15:41:27 +08:00
parent e84e8483b7
commit ea253e3732
11 changed files with 2980 additions and 109 deletions

View File

@ -86,6 +86,28 @@
}
}
},
{
"path": "pages/my/channelMerchants/myMerchants",
"style": {
"navigationBarTitleText": "我是渠道商",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false
}
}
},
{
"path": "pages/my/channelMerchants/index",
"style": {
"navigationBarTitleText": "申请渠道商",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false
}
}
},
{
"path": "pages/my/applyBroker/myBroker",
"style": {

455
pages/cooperate/hehuo1.vue Normal file
View File

@ -0,0 +1,455 @@
<template>
<view class="hehuo_view">
<view class="advantage-title">门店入驻</view>
<view class="advantage-bor"></view>
<view class="adv_text_view">
<view class="adv_lines">
<view >1您的门店经营多久了?</view>
<radio-group @change="radioChangeJ">
<label class="uni-list-cell uni-list-cell-pd adv_lines-view" v-for="(item, index) in jingying" :key="item.value">
<view>
<radio :value="item.value" color="#019c88" :checked="index === currentJ" />
</view>
<view class="radio-title">{{item.name}}</view>
</label>
</radio-group>
</view>
<view class="adv_lines">
<view >2您的门店面积</view>
<radio-group @change="radioChangeM">
<label class="uni-list-cell uni-list-cell-pd adv_lines-view" v-for="(item, index) in mianji" :key="item.value">
<view>
<radio :value="item.value" color="#019c88":checked="index === currentM" />
</view>
<view class="radio-title">{{item.name}}</view>
</label>
</radio-group>
</view>
<view class="adv_lines">
<view >3您的门店团队有队少人?</view>
<radio-group @change="radioChangeT">
<label class="uni-list-cell uni-list-cell-pd adv_lines-view" v-for="(item, index) in tuandui" :key="item.value">
<view>
<radio :value="item.value" color="#019c88" :checked="index === currentT" />
</view>
<view class="radio-title">{{item.name}}</view>
</label>
</radio-group>
</view>
<view class="adv_lines">
<view >4门店提供的项目有哪些?</view>
<radio-group @change="radioChangeX">
<label class="uni-list-cell uni-list-cell-pd adv_lines-view" v-for="(item, index) in xiangmu" :key="item.value">
<view>
<radio :value="item.value" color="#019c88" :checked="index === currentX" />
</view>
<view class="radio-title">{{item.name}}</view>
</label>
</radio-group>
</view>
</view>
<view class="adv_text_view">
<view class="info-box-item">
<view class="info-box-item-name">姓名</view>
<u-input type="text" v-model="userName" maxlength="11" placeholder="请输入真实姓名" /></u-input>
</view>
<view class="line"></view>
<view class="adv_lines">
<view >手机号</view>
<u-input type="number" v-model="phone" maxlength="11" placeholder="请输入手机号" /></u-input>
</view>
<view class="line"></view>
<view class="adv_lines">
<view>备注</view>
<textarea style="height: 100px; font-size: 28rpx;" v-model="beizhu" name="" maxlength="100" id="" cols="30" rows="10" placeholder="请输入备注~~~~"></textarea>
</view>
<view class="line"></view>
</view>
<view class="push-button">
<view class="que-btn" @tap="save">提交申请</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
beizhu:'',
phone:'',
userName:'',
jingying: [{
value: '一年',
name: '一年',
checked: 'true'
},
{
value: '一到三年',
name: '一到三年'
},
{
value: '三年以上',
name: '三年以上'
},
],
currentJ: 0,
mianji: [{
value: '50平米一下',
name: '50平米一下',
checked: 'true'
},
{
value: '50到200平米',
name: '50到200平米'
},
{
value: '200平米以上',
name: '200平米以上'
},
],
currentM: 0,
tuandui: [{
value: '5-10人',
name: '5-10人',
checked: 'true'
},
{
value: '10-15人',
name: '10-15人'
},
{
value: '15-20人',
name: '15-20人'
},
{
value: '20人以上',
name: '20人以上'
},
],
currentT: 0,
xiangmu: [{
value: '推荐按摩',
name: '推荐按摩',
checked: 'true'
},
{
value: 'SPA',
name: 'SPA'
},
{
value: '足浴',
name: '足浴'
},
],
currentX: 0,
mendianData:'',
mianjiData:'',
tuanduiData:'',
xiangmuData:'',
}
},
mounted() {
},
methods: {
save() {
if(!this.mendianData){
this.mendianData=this.jingying[0].value
}
if(!this.mianjiData){
this.mianjiData=this.mianji[0].value
}
if(!this.tuanduiData){
this.tuanduiData=this.tuandui[0].value
}
if(!this.xiangmuData){
this.xiangmuData=this.xiangmu[0].value
}
if (this.userName === '') {
this.$queue.showToast('请输入姓名')
return;
}
if (this.phone === '' || this.phone.length != 11) {
this.$queue.showToast('请输入正确的手机号!')
return;
}
let userId = this.$queue.getData('userId');
let data = {
userId: userId,
name: this.userName,
phone: this.phone,
remark:this.beizhu,
queone:this.mendianData,
quetwo:this.mianjiData,
quethree:this.tuanduiData,
queforu:this.xiangmuData,
}
this.$Request.postJson('/app/dlssqjl/insertDlssqjl', data).then(res => {
if (res.code == 0) {
uni.hideLoading();
this.$queue.showToast('提交成功!');
setTimeout(d => {
uni.switchTab({
url:'/pages/index/index'
})
}, 1000);
} else {
uni.hideLoading();
this.$queue.showToast(res.msg);
}
});
},
radioChangeX: function(evt) {//
for (let i = 0; i < this.xiangmu.length; i++) {
if (this.xiangmu[i].value === evt.detail.value) {
this.currentX = i;
break;
}
}
this.xiangmuData=evt.detail.value
},
radioChangeT: function(evt) {//
for (let i = 0; i < this.tuandui.length; i++) {
if (this.tuandui[i].value === evt.detail.value) {
this.currentT = i;
break;
}
}
this.tuanduiData=evt.detail.value
},
radioChangeM: function(evt) {//
for (let i = 0; i < this.mianji.length; i++) {
if (this.mianji[i].value === evt.detail.value) {
this.currentM = i;
break;
}
}
this.mianjiData=evt.detail.value
},
radioChangeJ: function(evt) {//
for (let i = 0; i < this.jingying.length; i++) {
if (this.jingying[i].value === evt.detail.value) {
this.currentJ = i;
break;
}
}
this.mendianData=evt.detail.value
},
}
}
</script>
<style lang="less">
@import '../../static/less/index.less';
@import '../../static/css/index.css';
/deep/.uni-radio-input{
width: 20px;
height: 20px;
}
/deep/uni-radio::before{
margin-right: -1px;
}
.push-button{
width: 100%;
height: 48px;
position: fixed;
bottom: 0px;
display: flex;
flex-direction: column;
align-items: center;
margin: 0 auto;
}
.que-btn{
display: inline-block;
width: 90%;
text-align: center;
background: linear-gradient(90deg, #019C88, #28BA92, #35C495);
height: 40px;
border-radius: 28px;
color: #ffffff;
line-height: 40px;
margin-top: 4px;
font-size: 34rpx;
}
.uni-textarea-compute{
}
/deep/.uni-textarea-textarea{
border-radius: 8rpx;
margin-top: 20rpx;
}
.margin-top-view{
width: 150upx;
height: 150upx;
background: #f7f7f7;
}
.advantage-title{
font-size: 32rpx;
font-weight: bold;
margin-top: 60rpx;
margin-left: 30rpx;
}
.advantage-bor{
width: 64px;
height: 6px;
border-radius: 3px;
bottom: 0;
background: linear-gradient(90deg, rgba(234, 248, 245, 0.7), rgba(132, 211, 196, 0.7));
margin-bottom: 80rpx;
}
.adv-xian{
height: 2rpx;
border-bottom: 1px solid #e5e5e5;
}
.radio-title{
margin-left: 5px;
}
.adv_lines-view{
display: flex;
flex-direction: row;
align-items: center;
margin-top: 10px;
}
.adv_lines{
display: flex;
justify-content: space-between;
margin: 20rpx 0;
font-size: 28rpx;
flex-direction: column;
}
.adv_lines
.adv_line{
display: flex;
justify-content: space-between;
height: 50rpx;
line-height: 50rpx;
margin-bottom: 40rpx;
font-size: 28rpx;
}
.adv_input_text{
text-align: right;
line-height: 50rpx;
font-size: 28rpx;
}
.adv_item_view{
display: flex;
justify-content: space-between;
}
.adv_text_view {
width: 95%;
margin-left: 2.5%;
background-color: #fff;
border-radius: 10px;
padding: 20px;
margin-top: 20rpx;
}
.send-msg{
padding: 0 30rpx;
color: #fff;
height: 55rpx;
line-height: 54rpx;
background: linear-gradient(90deg, #019C88, #28BA92, #35C495);
border-radius: 30rpx;
}
.usermain-btn{
background: linear-gradient(to right, #029d88, #1fb38f);
color: #FFFFFF;
margin: 8px 16px;
position: fixed;
bottom: 0px;
width: 90%;
border-radius: 27px;
height: 43px;
line-height: 43px;
font-size: 17px;
text-align: center;
}
.adv_beizhu{
background-color: #f7f7f7;
height: 80rpx;
border-radius: 8rpx;
color: #999;
}
.adv_item_title{
width: 300rpx;
}
.adv_xian {
width: 100%;
border-bottom: 1rpx solid #f7f7f7;
margin-top: 10rpx;
}
.hehuo_view {
width: 100%;
padding-top: 10px;
background-image: url('../../static/cooperate/cooperate5.png');
background-repeat: no-repeat;
background-size: 100% 550rpx;
//display: flex;
//flex-direction: column;
//align-items: center;}
.text_view {
width: 95%;
margin-left: 2.5%;
background-color: #fff;
border-radius: 10px;
padding: 20px;
.audit_message {
color: red;
width: 650rpx;
height: 50rpx;
}
.save_btn1 {
margin: 10rpx;
width: 650rpx;
height: 88rpx;
background: #FFFFFF;
border-radius: 10rpx;
margin-top: 100rpx;
text-align: center;
line-height: 88rpx;
}
.item_view {
margin-top: 30rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.item_title {
font-size: 32rpx;
font-family: PingFang SC Heavy, PingFang SC Heavy-Heavy;
color: #333333;
}
input {
margin-top: 20rpx;
height: 40rpx;
font-size: 24rpx;
font-family: PingFang SC Regular, PingFang SC Regular-Regular;
font-weight: 400;
color: #333333;
}
.xian {
width: 100%;
border-bottom: 1rpx solid #f7f7f7;
margin-top: 10rpx;
}
}
}
}
.line {
width: 100%;
border-bottom: 1rpx solid #f7f7f7;
}
</style>

View File

@ -0,0 +1,275 @@
<template>
<view class="hehuo_view">
<view class="advantage-title">
<image style="width: 35rpx; height: 35rpx; margin-right:10rpx; margin-top: 5rpx;" src="../../../static/technician.png"></image>申请渠道商</view>
<view class="advantage-bor" style="margin-right: 10rpx;"></view>
<view class="text_view">
<view class="item_view">
<view class="item_title">姓名</view>
<u-input type="text" v-model="name" placeholder="请输入姓名" />
<view class="xian"></view>
</view>
<view class="item_view">
<view class="item_title">联系电话</view>
<u-input type="number" v-model="phone" maxlength="11" placeholder="请输入联系电话" />
<view class="xian"></view>
</view>
<view class="item_view">
<view class="item_title" @click.stop="pickerShow">申请渠道</view>
<ch-picker ref="ChPicker" position="bottom" :columns="columns" :defaultIndex="curIndexs" @confirm="pickerChange">
</ch-picker>
<u-input type="text" :disabled="true" v-model="qudao" maxlength="11" placeholder="请选择渠道" />
<view class="xian"></view>
</view>
</view>
<view class="header-view header-padd header-margin">
<view class="d-title title-font">
备注
</view>
<view class="list-pay">
<view class="textarea-pay-list">
<textarea @input="remarks" class="textarea-pay" v-model="remarks" placeholder="请输入备注" name="" maxlength="100"></textarea>
</view>
</view>
</view>
<view class="push-button">
<view class="que-btn" @tap="save">提交申请</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
name: '',
phone: '',
remarks:'',
qudao:'',
curIndexs: [0],
columns: [
[
{label: '暂无接入渠道商',value: '暂无接入渠道商'},
{label: '足球联赛',value: '足球联赛'},
{label: '地推',value: '地推',},
{label: '酒店',value: '酒店'}
],
],
}
},
methods: {
pickerShow() {
this.$refs.ChPicker.show()
},
pickerChange(e) {
console.log(e.columns[0].value);
this.qudao=e.columns[0].value
this.curIndexs = e.indexs
},
getChannel() {
let userId = this.$queue.getData('userId');
this.$Request.getT('/app/artificer/selectAgencyById?userId=' + userId).then(res => {
if (res.code == 0) {
if (res.data == null) {
this.bb = 1;
} else {
this.bb = res.data.status;
this.city = res.data.city;
this.age = res.data.age;
this.headImg = res.data.img;
this.userName = res.data.name;
this.phone = res.data.phone;
}
console.log(this.bb)
// this.auditContent = res.data.auditContent;
}
});
},
save() {
if (this.name === '') {
this.$queue.showToast('请输入姓名')
return;
}
if (this.phone === '' || this.phone.length != 11) {
this.$queue.showToast('请输入正确的手机号!')
return;
}
let userId = this.$queue.getData('userId');
let data = {
remarks: this.remarks,
name: this.name,
phone: this.phone,
}
this.$Request.get('/app/commission/jjr/apply', data).then(res => {
if (res.code == 0) {
uni.hideLoading();
this.$queue.showToast(res.msg);
// setTimeout(d => {
// uni.navigateBack();
// }, 1000);
} else {
uni.hideLoading();
this.$queue.showToast(res.msg);
}
});
},
}
}
</script>
<style lang="less">
@import '../../../static/less/index.less';
@import '../../../static/css/index.css';
/deep/.uni-textarea-textarea{
font-weight: 400;
font-size: 26rpx;
}
/deep/.uni-textarea-placeholder{
font-weight: 400;
font-size: 28rpx;
color: rgb(192, 196, 204);
}
.textarea-pay-list{
width: 100%;
height: 120px;
margin-top: 10px;
}
.textarea-pay{
background-color: #f3f3f3;
width: 100%;
height: 100%;
background: #F3F3F3;
border-radius: 14rpx;
padding: 7px;
}
.list-pay{
width: 100%;
}
.title-font{
font-size:30rpx;
color: #333333;
}
.d-title{
font-size: 15px;
font-family: PingFang SC Heavy, PingFang SC Heavy-Heavy;
color: #333333;
}
.header-view{
background-color: #fff;
border-radius: 11px;
}
.header-padd{
padding:30rpx;
}
.header-margin{
margin:20rpx;
}
.push-button{
width: 100%;
height: 48px;
position: fixed;
bottom: 0px;
display: flex;
flex-direction: column;
align-items: center;
margin: 0 auto;
}
.que-btn{
display: inline-block;
width: 90%;
text-align: center;
background: linear-gradient(90deg, #019C88, #28BA92, #35C495);
height: 40px;
border-radius: 28px;
color: #ffffff;
line-height: 40px;
margin-top: 4px;
font-size: 34rpx;
}
.margin-top-view{
width: 150upx;
height: 150upx;
background: #f7f7f7;
}
.advantage-title{
font-size: 32rpx;
font-weight: bold;
margin-top: 60rpx;
margin-left: 35rpx;
}
.advantage-bor{
width: 96px;
height: 6px;
border-radius: 3px;
bottom: 0;
background: linear-gradient(90deg, rgba(234, 248, 245, 0.7), rgba(132, 211, 196, 0.7));
margin-bottom: 80rpx;
margin-left: 35rpx;
}
.hehuo_view {
width: 100%;
padding-top: 10px;
height: 100vh;
background:#f7f7f7 url(../../../static/cooperate/cooperate6.png)no-repeat ;
background-size: 100%;
position: relative;
display: flex;
flex-direction: column;
//align-items: center;
.text_view {
width: 95%;
margin: 0 auto;
background-color: #fff;
border-radius: 10px;
padding: 20px;
.audit_message {
color: red;
width: 650rpx;
height: 50rpx;
margin-top: 50rpx;
}
.save_btn1 {
width: 650rpx;
height: 88rpx;
background: #FFFFFF;
border-radius: 10rpx;
margin-top: 100rpx;
text-align: center;
line-height: 88rpx;
}
.item_view {
margin-top: 30rpx;
.item_title {
font-size: 32rpx;
font-family: PingFang SC Heavy, PingFang SC Heavy-Heavy;
color: #333333;
}
input {
margin-top: 20rpx;
height: 40rpx;
font-size: 24rpx;
font-family: PingFang SC Regular, PingFang SC Regular-Regular;
font-weight: 400;
color: #333333;
}
.xian {
width: 100%;
border-bottom: 1rpx solid #f7f7f7;
margin-top: 10rpx;
}
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -4,32 +4,11 @@
<image style="width: 35rpx; height: 35rpx; margin-right:10rpx; margin-top: 5rpx;" src="../../static/technician.png"></image>申请合作技师</view>
<view class="advantage-bor" style="margin-right: 10rpx;"></view>
<view class="text_view">
<!-- <view class="item_view">
<view class="item_title">服务城市 </view>
<u-input @click="goCity" type="text" v-model="city" placeholder="请输入服务城市 " />
<view class="item_view">
<view class="item_title" @tap="Cityshow = true">服务城市</view>
<u-input type="text" :disabled="true" v-model="city" placeholder="选择城市" />
<view class="xian"></view>
</view> -->
<uni-forms ref="baseForm" :disabled="true" v-if="city">
<uni-forms-item label="选择城市" required :disabled="true">
<picker class="addRess" :disabled="true" range-key="AreaName" mode="multiSelector">
<view class="uni-input">
<text>{{city}}</text>
</view>
</picker>
</uni-forms-item>
</uni-forms>
<uni-forms ref="baseForm" v-else>
<uni-forms-item label="服务城市" required>
<picker class="addRess" @change="bindPickerChange" @columnchange="pluginclass" :value="pickVal" :range="cityArr"
range-key="AreaName" mode="multiSelector">
<view class="qing" v-if="pickVal2.length==0">请选择城市</view>
<view v-else class="uni-input">
<text>{{cityData}}</text>
</view>
</picker>
</uni-forms-item>
</uni-forms>
</view>
<view class="item_view">
<view class="item_title">姓名</view>
<u-input type="text" v-model="userName" placeholder="请输入姓名" />
@ -135,7 +114,8 @@
</view>
</view>
</view>
<!-- 经验筛选 -->
<u-select v-model="Cityshow" style="height: auto;" :list="cityList" @confirm="getCity"></u-select>
</view>
<view class="push-button">
<view class="que-btn" @tap="save" v-if="bb!=0">提交申请</view>
@ -149,13 +129,9 @@
export default {
data() {
return {
cityList: [],
Cityshow: false,
selected:[],
pickVal: [0, 0, 0], //
pickVal2:[], // 线
cityArr: [], //
hotCitys: ['杭州', '天津', '北京', '上海', '深圳', '广州', '成都', '重庆', '厦门'],
locationValue: '正在定位...',
// auditContent: '',
city: '',
money: '',
teamNumber: '',
@ -166,17 +142,24 @@
back:'',
certification:[],
bb:'1',
cityData:'',
typeId: '',
typeList:[]
}
},
onLoad() {
this.getChannel();
this.loadProvinces();
this.fuwuType()
this.fuwuType();
this.getKTCityList()
},
methods: {
showCityList() {
this.Cityshow = true;
},
getCity(e) {
console.log(e[0].label);
this.city = e[0].label;
this.getKTCityList();
},
gukeBtn(item) {
var index = this.selected.indexOf(item);
if (index === -1) {
@ -201,77 +184,23 @@
}
});
},
loadProvinces() { //
uni.request({
url: 'http://test-api.tiananhub.com/api/province/GetListProvince',
method: 'get',
success: async (res) => {
let {
data
} = res.data
console.log(data)
this.cityArr[0] = data
this.loadCities(data[0].AreaId)
this.$forceUpdate()
},
fail: async (res) => {}
})
},
//
loadCities(AreaId) {
uni.request({
url: 'http://test-api.tiananhub.com/api/province/GetListCity',
data: {
AreaId
},
method: 'get',
success: async (res) => {
let {
data
} = res.data
this.cityArr[1] = data
this.loadAreas(data[0].AreaId)
this.$forceUpdate()
},
fail: async (res) => {}
})
},
//
loadAreas(AreaId) {
uni.request({
url: 'http://test-api.tiananhub.com/api/province/GetListCity',
data: {
AreaId
},
method: 'get',
success: async (res) => {
let {
data
} = res.data
this.cityArr[2] = data
this.$forceUpdate()
},
fail: async (res) => {}
})
},
//
bindPickerChange(data) {
this.pickVal=data.target.value;
this.pickVal2=data.target.value;
console.log("data====",this.pickVal2)
this.cityData=this.cityArr[0][this.pickVal2[0]].AreaName+'-'+this.cityArr[1][this.pickVal2[1]].AreaName+'-'+this.cityArr[2][this.pickVal2[2]].AreaName
},
//
pluginclass(e) {
if (e.detail.column == 0) {
this.loadCities(this.cityArr[0][e.detail.value].AreaId);
}
if (e.detail.column == 1) {
this.loadAreas(this.cityArr[1][e.detail.value].AreaId);
}
getKTCityList(){
this.$Request.getT('/app/trip/selectTripList').then(res => {
if (res.code == 0) {
this.cityList = [];
let isOpen = false
let cityName = uni.getStorageSync('city') ? uni.getStorageSync('city') : '请选择城市'
res.data.forEach((d, index) => {
if (cityName === d.city) {
isOpen = true;
}
let data = {}
data.label = d.city
data.value = index
this.cityList.push(data);
});
}
});
},
//
frontremove(index) {
@ -336,7 +265,7 @@
});
},
save() {
if (this.cityData === '') {
if (this.city === '') {
this.$queue.showToast('请输入服务城市 ')
return;
}
@ -372,7 +301,7 @@
name: this.userName,
phone: this.phone,
age: this.age,
city: this.cityData,
city: this.city,
front: this.front,
back:this.back,
certification:this.certification,

View File

@ -153,7 +153,7 @@
<image style="padding: 3rpx;" src="../../static/my-gong-4.png" mode=""></image>
<span class="my-use-list-text">城市合伙人</span>
</view>
<view class="my-use-list" v-if="blIsJjr=='0'" @click="useToUrl('/pages/my/applyBroker/index')">
<!-- <view class="my-use-list" v-if="blIsJjr=='0'" @click="useToUrl('/pages/my/applyBroker/index')">
<image style="padding: 3rpx;" src="../../static/my-gong-11.png" mode=""></image>
<span class="my-use-list-text">申请经纪人</span>
</view>
@ -176,7 +176,15 @@
<view class="my-use-list" v-if="blIsFxy=='1'" @click="useToUrl('/pages/my/applyDistributor/myDistributor')">
<image style="padding: 3rpx;" src="../../static/my-gong-16.png" mode=""></image>
<span class="my-use-list-text">我是分销员</span>
</view> -->
<!-- <view class="my-use-list" @click="useToUrl('/pages/my/channelMerchants/index')">
<image style="padding: 3rpx;" src="../../static/my-gong-11.png" mode=""></image>
<span class="my-use-list-text">申请渠道商</span>
</view>
<view class="my-use-list" @click="useToUrl('/pages/my/channelMerchants/myMerchants')">
<image style="padding: 3rpx;" src="../../static/my-gong-12.png" mode=""></image>
<span class="my-use-list-text">我是渠道商</span>
</view> -->
<view class="my-use-list" @click="useToUrl('/pages/my/myteam')">
<image style="padding: 3rpx;" src="../../static/my-gong-9.png" mode=""></image>
<span class="my-use-list-text">我的团队</span>

View File

@ -0,0 +1,12 @@
## 1.0.52023-09-19
添加点击切换;
## 1.0.42023-05-05
添加confirm及cancel事件
## 1.0.32023-05-04
优化:减少参数、超出隐藏、样式定义等等
## 1.0.22023-02-20
消除插件外字体颜色造成的影响
## 1.0.12022-07-19
position为center时增加width属性
## 1.0.02022-07-14
初版,但是差一点的手机会卡顿,慎用

View File

@ -0,0 +1,273 @@
<template>
<div ref="pickerView" class="ch-picker-view" @touchstart="touchstart" @touchmove.prevent="touchmove"
@touchend="touchend">
<div class="ch-picker-view__scroll" :style="{
height: `${_itemHeight * visibleCount}px`,
'--background': `linear-gradient(to bottom, #fff 0%, transparent ${_itemHeight*(_getMaskTopCount+0.4)}px, transparent ${_itemHeight*(_getMaskTopCount+1-0.4)}px, #fff 100%)`,
}">
<div class="ch-picker-view__scroll-masktop" :style="{height:`${_itemHeight * _getMaskTopCount}px`}"></div>
<div class="ch-picker-view__scroll-maskbottom" :style="{height:`${_itemHeight*_getMaskBottomCount}px`}"></div>
<div class="ch-picker-view__scroll-box" :style="{
marginTop:`${_itemHeight * _getMaskTopCount}px`,
transform: `translateY(${translateY}px)`,
}">
<div class="ch-picker-view__scroll-box-item textHide-span" :style="[_itemStyle]" v-for="(item,index) in column"
:key="index" @tap="handleColumn(item,index)">
<template v-if="_fieldsMode==='default'">{{item}}</template>
<template v-else-if="_fieldsMode==='json'">{{item[_fields.label]}}</template>
</div>
</div>
</div>
</div>
</template>
<script>
const screenWidth = uni.getSystemInfoSync().screenWidth
export default {
props: {
//
colCount: {
type: Number,
default: 0
},
//
colIndex: {
type: Number,
default: 0
},
//
column: {
type: Array,
default: () => []
},
//
defaultIndex: {
type: Number,
default: 0
},
// value label
fields: {
type: Object,
default: () => {
return {}
}
},
// _itemStyleheight
// px
itemHeight: {
type: [String, Number],
default: 44
},
//
itemStyle: {
type: Object,
default: () => {}
},
// 5,3
visibleCount: {
type: Number,
default: 5
},
},
data() {
return {
touchStartY: 0, // y
deltaY: 0, // ,
translateY: 0, // box
isTouching: false, //
default: {
fieldsValue: 'value',
fieldsLabel: 'label',
},
}
},
computed: {
_fields() {
return {
value: this.fields.value || this.default.fieldsValue,
label: this.fields.label || this.default.fieldsLabel,
}
},
// : default json
_fieldsMode() {
if (this.column && this.column.length && typeof this.column[0] === 'object') {
return 'json'
} else {
return 'default'
}
},
//
_itemHeight() {
return typeof this.itemHeight === 'string' ? parseFloat(this.itemHeight) : this.itemHeight
},
//
_itemStyle() {
return {
...this.itemStyle,
height: `${this._itemHeight}px`,
lineHeight: `${this._itemHeight}px`,
}
},
//
_scrollInnerH() {
return this._itemHeight * (this.column.length - 1)
},
_getMaskTopCount() {
return Math.floor((this.visibleCount - 1) / 2)
},
_getMaskBottomCount() {
return Math.ceil((this.visibleCount - 1) / 2)
}
},
watch: {
defaultIndex: {
handler(nVal, oVal) {
if (this.isTouching) {
return
}
this.translateY = nVal * this._itemHeight * -1
},
immediate: true
},
translateY(nVal, oVal) {
let tIndex = Math.floor(Math.abs(nVal) / this._itemHeight)
tIndex = tIndex > this.column.length - 1 ? this.column.length - 1 : tIndex
this.$emit('change', tIndex)
},
},
mounted() {
// #ifdef H5
//
this.$refs.pickerView.addEventListener('mousewheel', this.mouseHandle, false)
// #endif
},
methods: {
// - start
mouseHandle(e) {
let clientX = e.clientX
let rangeWidth1 = screenWidth / this.colCount * (this.colIndex)
let rangeWidth2 = screenWidth / this.colCount * (this.colIndex + 1)
if (clientX < rangeWidth1 || clientX >= rangeWidth2) {
return
}
if (e.target.className === 'ch-picker-mask') {
return
}
let tTranslateY = this.translateY
if (e.deltaY > 0) {
// console.log('');
tTranslateY -= this._itemHeight
tTranslateY = tTranslateY < this._scrollInnerH * -1 ? this._scrollInnerH * -1 : tTranslateY
} else {
// console.log('');
tTranslateY += this._itemHeight
tTranslateY = tTranslateY > 0 ? 0 : tTranslateY
}
this.translateY = tTranslateY
},
// - end
// - start
touchstart(e) {
this.isTouching = true
let tTouche = e.touches[0]
// console.log('touchstart', tTouche.clientY);
this.touchStartY = tTouche.clientY
this.deltaY = 0
},
touchmove(e) {
this.isTouching = true
let tTouche = e.touches[0]
// console.log('touchmove', tTouche.clientY);
let preDeltaY = this.deltaY
this.deltaY = tTouche.clientY - this.touchStartY
let tDiff = this.deltaY - preDeltaY
this.translateY += tDiff
},
touchend(e) {
// console.log('touchend');
this.isTouching = false
let tTranslateY = 0
let divisor = this.translateY / this._itemHeight
divisor = this.deltaY > 0 ? Math.ceil(divisor) : Math.floor(divisor)
tTranslateY = divisor * this._itemHeight
tTranslateY = tTranslateY > 0 ? 0 : tTranslateY
tTranslateY = tTranslateY < this._scrollInnerH * -1 ? this._scrollInnerH * -1 : tTranslateY
// console.log(tTranslateY);
this.translateY = tTranslateY
},
// - end
handleColumn(item, index) {
this.translateY += (this.defaultIndex - index) * this._itemHeight
}
}
}
</script>
<style lang="scss" scoped>
.ch-picker-view {
display: flex;
align-items: center;
.ch-picker-view__scroll {
position: relative;
width: 100%;
overflow: hidden;
z-index: 1;
&::before {
content: "";
position: absolute;
inset: 0;
background: var(--background);
pointer-events: none;
z-index: 99;
}
.ch-picker-view__scroll-masktop,
.ch-picker-view__scroll-maskbottom {
position: absolute;
width: 100%;
z-index: 1;
border: 0 solid transparent;
border-image: linear-gradient(to right, transparent, #ddd, transparent) 1;
pointer-events: none;
z-index: 101;
}
.ch-picker-view__scroll-masktop {
top: 0;
border-bottom-width: 1px;
}
.ch-picker-view__scroll-maskbottom {
bottom: 0;
border-top-width: 1px;
}
.ch-picker-view__scroll-box {
transition: all 200ms linear;
.ch-picker-view__scroll-box-item {
padding: 0 10rpx;
text-align: center;
}
}
}
.textHide-span {
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
}
}
</style>

View File

@ -0,0 +1,276 @@
<template>
<div v-show="visible" class="ch-picker">
<div class="ch-picker__mask" :class="{'mask-show':maskVisible}" @tap.stop.prevent="maskHandle"></div>
<div class="ch-picker__content" :class="[`ch-picker__content-${position}`,{'show':maskVisible}]"
:style="{'--contentWidth':actWidth}">
<div class="ch-picker__content-toolbar">
<div @tap.stop.prevent="closeHandle">取消</div>
<div @tap.stop.prevent="confirmHandle">确定</div>
</div>
<div class="ch-picker__content-columns">
<div class="ch-picker__content-column" :style="{'--col':columns.length}" v-for="(column,index) in columns"
:key="index">
<ch-picker-view :column="column" :itemHeight="itemHeight" :visibleCount="actVisibleCount"
:itemStyle="itemStyle" :defaultIndex="defaultIndex[index]" :fields="fields" :colCount="columns.length"
:colIndex="index" @change="(e)=>indexChange(index,e)">
</ch-picker-view>
</div>
</div>
</div>
</div>
</template>
<script>
function formatPropSize(size) {
let tUnit = 'px'
let result = ''
if (typeof size === 'string') {
result = parseFloat(size)
tUnit = size.replace(result.toString(), '')
result = `${result}${tUnit}`
} else if (typeof size === 'number') {
result = `${size}${tUnit}`
}
return result
}
export default {
props: {
//
clickMaskClose: {
type: Boolean,
default: true
},
//
columns: {
type: Array,
default: () => []
},
//
defaultIndex: {
type: Array,
default: () => []
},
// top/center/bottom
position: {
type: String,
default: 'bottom'
},
// 5,3
visibleCount: {
type: [String, Number],
default: 5
},
// positioncenter
// px
width: {
type: [String, Number],
default: '60vw'
},
// 使 - start
// itemStyleheight
// px
itemHeight: {
type: [String, Number],
default: 44
},
//
itemStyle: {
type: Object,
default: () => {}
},
//
fields: {
type: Object,
default: () => {
return {}
}
},
},
data() {
return {
visible: false,
maskVisible: false,
curIndexs: new Array(),
visibleCountMax: 5, //
visibleCountMin: 3, //
}
},
computed: {
//
actWidth() {
return formatPropSize(this.width)
},
//
actVisibleCount() {
let result = typeof this.visibleCount === 'string' ? parseFloat(this.visibleCount) : this.visibleCount
result = result > this.visibleCountMax ? this.visibleCountMax : result
result = result < this.visibleCountMin ? this.visibleCountMin : result
return result
},
},
watch: {
defaultIndex: {
handler(nVal, oVal) {
if (typeof nVal !== 'object') {
return
}
this.curIndexs = JSON.parse(JSON.stringify(nVal))
},
deep: true,
immediate: true
},
},
methods: {
show() {
this.visible = true
setTimeout(() => {
this.maskVisible = true
}, 250)
},
hide() {
this.maskVisible = false
setTimeout(() => {
this.visible = false
}, 250)
},
maskHandle() {
if (!this.clickMaskClose) {
return
}
this.hide()
},
closeHandle() {
this.$emit('cancel')
this.hide()
},
confirmHandle() {
let result = this.formatReturn()
this.$emit('confirm', result)
this.hide()
},
formatReturn() {
let tIndexs = []
let tColumns = []
for (let i = 0; i < this.columns.length; i++) {
let tIndex = this.curIndexs[i] || 0
tIndexs.push(tIndex)
tColumns.push(this.columns[i][tIndex])
}
return {
indexs: tIndexs,
columns: tColumns,
}
},
indexChange(index, e) {
// console.log(index, e);
this.$set(this.curIndexs, index, e)
let result = this.formatReturn()
this.$emit('change', result)
}
}
}
</script>
<style lang="scss" scoped>
.ch-picker {
color: initial;
.ch-picker__mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1023;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: all .5s;
&.mask-show {
opacity: 1;
}
}
.ch-picker__content {
position: fixed;
background-color: #fff;
border-radius: 4px;
z-index: 1024;
transition: all .5s;
display: flex;
flex-direction: column;
.ch-picker__content-toolbar {
height: 48px;
padding: 0 15px;
font-size: 13px;
// background-color: #f8f8f8;
display: flex;
justify-content: space-between;
align-items: center;
>div:last-child {
color: #0055ff;
}
}
.ch-picker__content-columns {
padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
display: flex;
align-items: center;
.ch-picker__content-column {
width: calc(100% / var(--col));
flex: 0 0 auto;
}
}
}
.ch-picker__content-top {
top: 0;
left: 0;
width: 100vw;
transform: translateY(-100%);
flex-direction: column-reverse;
&.show {
transform: translateY(0);
}
}
.ch-picker__content-center {
top: 50%;
left: 50%;
width: var(--contentWidth);
transform: translate(-50%, -50%) scale(0);
&.show {
transform: translate(-50%, -50%) scale(1);
}
}
.ch-picker__content-bottom {
bottom: 0;
left: 0;
width: 100vw;
transform: translateY(100%);
&.show {
transform: translateY(0);
}
}
::-webkit-scrollbar {
display: none;
}
}
</style>

View File

@ -0,0 +1,83 @@
{
"id": "ch-picker",
"displayName": "滚动选择器",
"version": "1.0.5",
"description": "滚动选择器,支持实时监听",
"keywords": [
"滚动选择器",
"选择器",
"picker"
],
"repository": "https://gitee.com/ask_flowers_and_trees/ch-picker.git",
"engines": {
"HBuilderX": "^3.4.18"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": "",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "u"
},
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"钉钉": "y",
"快手": "y",
"飞书": "y",
"京东": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,68 @@
## 基本用法
```html
<template>
<view class="content">
<button type="default" @tap="pickerShow">点击显示{{JSON.stringify(curIndexs)}}</button>
<ch-picker ref="ChPicker" position="bottom" :columns="columns" :defaultIndex="curIndexs" @change="pickerChange">
</ch-picker>
</view>
</template>
<script>
export default {
data() {
return {
curIndexs: [2, 1, 1],
columns: [
[{label: 0,value: 0,},{label: 1,value: 1,},{label: 2,value: 2,},{label: 3,value: 3,},],
[{label: 0,value: 0,},{label: 1,value: 1,},{label: 2,value: 2,},{label: 3,value: 3,},],
[{label: 0,value: 0,},{label: 1,value: 1,},{label: 2,value: 2,},{label: 3,value: 3,},]
],
}
},
onLoad() {},
methods: {
pickerShow() {
this.$refs.ChPicker.show()
},
pickerChange(e) {
// console.log(e);
this.curIndexs = e.indexs
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
```
## 启动方式
`this.$refs.ChPicker.show()`
## 属性
| 属性 | 描述 | 类型 | 默认值 |
|--|--|--|--|
| clickMaskClose| 点击遮罩层关闭 | Boolean | true |
| columns| 每一列的数据 | Array| [] |
| defaultIndex| 默认选中值的下标,是数组 | Array | [] |
| position| 悬浮位置 | String | bottom |
| visibleCount| 每列中可见选项的数量最大为5,最小为3 | String, Number | 5 |
| width| position为center时生效不含单位时默认单位是px | String, Number | 60vw |
| itemHeight| 单个选项的高度会覆盖itemStyle内的height单位是px | String, Number | 44 |
| itemStyle| 单个选项样式 | Object | {} |
| fields| 数组属性 | Object | {label: 'label',value: 'value',} |
## 事件
| 属性 | 描述 | 回调参数
|--|--|--|--|
| change| 实时监听,选项发生改变时触发 | {indexs, columns}indexs选中项下标数组columns选中项数组 |
| confirm| 点击确认按钮触发 | {indexs, columns}indexs选中项下标数组columns选中项数组 |
| cancel| 点击取消按钮触发 | - |