微信小程序原生JS智能粘贴功能 编辑与删除
功能要求:智能识别,并且所有识别的内容都可单独修改,智能识别框可收起和展开,列表可单条右滑删除(图未展示),识别框与列表页都可一键清除
效果:
WXML代码
<view class="page">
<view class='shouqi' wx:if="{{showsmall||showClear}}">
<view class='text' bindtap="showbig">请输入或者粘贴信息,可自动识别</view>
<image src="https://file.baimipay.cn/biaodan2x.png" bindtap="addressList"></image>
</view>
<view class='address-wrap' wx:if="{{showbig&&!showClear}}">
<view class='smart-address'>
<view class='smart-top'>
<view class='flex-3'>
<view class="paste">
<view class="paste-title">智能粘贴</view>
<image src="https://file.baimipay.cn/icon_zhankai.png" bindtap="showbig" class='zhankai'></image>
</view>
<view class='c9 ft12 mt10'>不同信息用空格隔开,不同订单请换行添加</view>
</view>
<view class='flex-1 tar' bindtap='addressList'>
<image src="https://file.baimipay.cn/biaodan2x.png"></image>
</view>
</view>
<view class='smart-bottom' hidden='{{imageSrc}}'>
<textarea class='textarea-css' placeholder-class="input-placeholder" placeholder="楼栋-单元-门牌号 货物信息 手机号(选填) 例如:6-2-103 十斤车厘子 15711111111" bindinput='handleInputList' value='{{copyText}}' focus maxlength="1000"/>
<view class='clearknow'>
<view wx:if='{{copyText}}' data-name='copyText' bindtap='handleClearInput'>清除</view>
<view wx:if='{{copyText}}' bindtap='pasteAvailableText'>识别</view>
</view>
</view>
</view>
</view>
<view class='addressInfo-title'>
<text style='width:220rpx;'>地址</text>
<text style='width:310rpx;'>货物信息</text>
<text>手机号</text>
</view>
<view wx:if='{{!listData.length}}' class='kong'>
空
</view>
<view class='wrap' wx:if='{{!showClear}}'>
<view wx:for='{{listData}}' wx:key='index' class='addressInfo {{index== isTouchMove? "touch-move-active" : ""}}' auto-height bindtouchstart='TouS' bindtouchmove='TouM' catchtouchend='TouE' data-index="{{index}}">
<view class='content'>
<textarea bindinput="handleInputAddress" class='flex-1 site-input' placeholder-class='cc' value='{{item.unitAddress}}' placeholder='请填写楼栋号' maxlength="12" data-index="{{index}}" auto-height></textarea>
<textarea bindinput="handleInputInfo" style="max-width:300rpx;" class='flex-1 site-input' placeholder-class='cc' value='{{item.deliverInfo}}' placeholder='请填写货物信息' maxlength="150" data-index="{{index}}" auto-height></textarea>
<textarea bindinput="handleInputPhone" class='flex-1 site-input' placeholder-class='cc' value='{{item.phone}}' placeholder='请填写手机号' maxlength="13" data-index="{{index}}" auto-height></textarea>
</view>
<view class='del' catchtap='delAddress' data-index='{{index}}'>
删除
</view>
</view>
</view>
<view wx:else>
<view wx:for='{{listData}}' wx:key='index' class='addressInfo {{index== isTouchMove? "touch-move-active" : ""}}' auto-height bindtouchstart='TouS' bindtouchmove='TouM' catchtouchend='TouE' data-index="{{index}}">
<view class='content'>
<view class='flex-1 site-input' auto-height>{{item.unitAddress}}</view>
<view style="max-width:310rpx;" class='flex-1 site-input' auto-height>{{item.deliverInfo}}</view>
<view class='flex-1 site-input' auto-height>{{item.phone}}</view>
</view>
</view>
</view>
<view class="submit">
<button class="submit-btn clear" catchtap='{{showClear?"":"showClear"}}' style='color:#333;'>
清除
</button>
<button class="submit-btn {{listData.length?'':'disable'}}" catchtap='{{showClear?"":"submit"}}'>
下一步({{listData.length}})
</button>
</view>
</view>
<!-- 弹出层 -->
<view class='popup-view' wx:if="{{showClear}}">
<view class='popup'>
<view class='popup-title'>确定全部清除?</view>
<view class='dialogbtn'>
<view bindtap="onCloseFlag" class='headbtn'>取消</view>
<view bindtap="subClear" class='headbtn sub'>确定</view>
</view>
</view>
</view>
JS代码
const app = getApp();
import Common from '../../../api/common.js'
import Address from "../../../api/address.js"
import Head from "../../../api/header.js"
Page({
/**
* 页面的初始数据
*/
data: {
syncName: app.globalData.syncName, //缓存标识
listData:[],
copyText: '',
addressId: '',
userNameFocus: false,
mobileFocus: false,
addressFocus: false,
isShow: true,
iosPhone: false, //手机机型
showsmall:false,
showbig:true,
isTouchMove: -1,
showClear:false
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
wx.setNavigationBarTitle({
title: '填写送货信息'
})
if (wx.getStorageSync(`${this.data.syncName}headAddress`)){
const listData = wx.getStorageSync(`${this.data.syncName}headAddress`)
this.setData({
listData
})
}
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
console.log(this.data.listData)
},
onUnload: function () {
// wx.removeStorageSync(`${this.data.syncName}headAddress`)
},
submit() {
const msg = this.checkMsg();
if (msg) {
app.commonTip(msg);
return false;
}
let listData = this.data.listData
let num = 0
for (let i in listData){
num++
listData[i].numMark=num
}
wx.setStorageSync(`${this.data.syncName}headAddress`, listData)
wx.navigateTo({
url: '../../../packageA/head/index',
})
},
// 识别文字
postTest(text) {
console.log('识别文字')
Head.filterAddress(text).then(res => {
let listData = this.data.listData
if (listData.length==0){
this.setData({
listData: res.arrayMsg
})
}else{
console.log(listData)
// listData=listData.concat(res.arrayMsg)
//listData = listData.unshift(res.arrayMsg)
for (let i = res.arrayMsg.length-1;i>=0; i--){
listData = [res.arrayMsg[i], ...listData];
}
this.setData({
listData,
})
console.log(listData)
}
}).catch(msg => {
console.error(msg);
})
wx.hideLoading();
},
handleInputList(e) {
this.setData({
copyText: e.detail.value
})
},
//处理粘贴文本
pasteAvailableText() {
wx.showLoading({
title: '智能识别中...',
mask: true
})
this.postTest(this.data.copyText)
},
handleClearInput(e) {
// debugger
const attrName = e.currentTarget.dataset.name;
this.setData({
[`${attrName}`]: ''
})
app.commonTip('已清除')
},
hadnleCancel() {
this.handleIsShowCropper();
this.clearImageSrc();
},
addressList(){
wx.navigateTo({
url: '../../../packageA/head/address_list/index',
})
},
showbig(){
this.setData({
showsmall: !this.data.showsmall,
showbig: !this.data.showbig
})
},
handleInputInfo(e){
const index = e.currentTarget.dataset.index
let listData = this.data.listData
listData[index].deliverInfo = e.detail.value
this.setData({
listData: listData
})
},
handleInputAddress(e) {
// debugger
const index = e.currentTarget.dataset.index
let listData = this.data.listData
listData[index].unitAddress = e.detail.value
this.setData({
listData: listData
})
},
handleInputPhone(e) {
const index = e.currentTarget.dataset.index
let listData = this.data.listData
listData[index].phone = e.detail.value
this.setData({
listData: listData
})
},
TouS(e) { //用户手指触摸
var index = e.currentTarget.dataset.index
if (e.touches.length == 1) {
this.setData({
startX: e.touches[0].clientX,
startY: e.touches[0].clientY,
})
}
},
TouM(e) { //用户拖动
var index = e.currentTarget.dataset.index
// console.log(index)
if (e.touches.length == 1) {
let moveX = e.touches[0].clientX;
let moveY = e.touches[0].clientY;
let disX = this.data.startX - moveX;
let disY = this.data.startY - moveY;
const isScrolling = Math.abs(disX) < Math.abs(disY) ? 1 : 0;
//isScrolling为1时,表示纵向滑动,0为横向滑动
if (disX > 30 && isScrolling == 0) {
this.setData({
isTouchMove: index
})
} else if (disX < 0 && index == this.data.isTouchMove) {
if (isScrolling == 0) {
this.setData({
isTouchMove: -1
})
}
}
}
},
TouE(e) {
var index = e.currentTarget.dataset.index;
if (this.data.disX < 120) {
this.setData({
isTouchMove: -1
})
}
},
delAddress(e) { //删除地址
const index = e.currentTarget.dataset.index
const that = this
this.setData({
isTouchMove: -1
})
wx.showModal({
title: '提示',
content: '是否删除',
success: function (res) {
if (res.confirm) {
let listData = that.data.listData
listData.splice(index, 1);
that.setData({
listData
})
console.log(that.data.listData)
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
},
checkMsg() {
let msg = '';
let listData=this.data.listData
var regPos1 = /(^(\d{3,4}-)\d{7,8}$)/; //电话号码
var regPos2 = /^1[3|4|5|7|8][0-9]{9}$/; //手机号码
for (let i in listData){
if (listData[i].unitAddress==''){
msg = '请填写地址';
}
if (listData[i].deliverInfo == '' || listData[i].deliverInfo == null) {
msg = '请填写货物信息';
}
if (listData[i].phone != '' && listData[i].phone != null) {
if (!(regPos1.test(listData[i].phone)) && !(regPos2.test(listData[i].phone))) {
msg = '手机号格式错误,请重新填写';
listData[i].phone = ''
}
}
this.setData({
listData
})
}
if (this.data.listData.length > 50) msg = '最多50条';
if (this.data.listData.length == 0) msg = '请填写货物信息';
return msg;
},
//清除弹框
showClear(){
this.setData({
showClear: true
})
},
//关闭弹窗
onCloseFlag() {
this.setData({
showClear: false
})
},
//确定清除
subClear(){
this.setData({
listData: [],
showClear: false
})
app.commonTip('已清除')
}
})
WXSS代码
page{
padding-bottom:200rpx;
box-sizing: border-box;
background-color: #f6f6f6;
}
.wrap {
}
.input-wrap {
width: 100vw;
display: flex;
position: relative;
padding: 0 30rpx;
font-size: 32rpx;
height: 96rpx;
background-color: #fff;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
.input-wrap>view:first-child {
width: 60%;
}
.input-wrap>view:last-child {
width: 40%;
}
.input-v {
width: 100%;
display: flex;
flex-direction: row;
padding-left: 10rpx;
margin-top: 10rpx;
height: 76rpx;
font-size: 30rpx;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
}
.input-v:first-child{
padding-right: 10rpx;
}
.input-v input {
width: 80%;
}
.input-v.flex-2 input {
display: inline-block;
overflow: hidden;
width: 220rpx;
height: 74rpx;
margin-top: 1rpx;
}
.input-v.flex-3 input {
display: inline-block;
overflow: hidden;
width: 320rpx;
height: 74rpx;
margin-top: 1rpx;
}
.input-v + .input-v {
border-left: 1rpx solid #eee;
}
.name-phone-icon {
margin-right: 6rpx;
}
.picker-click-dom {
padding: 10rpx 30rpx;
position: relative;
height: 76rpx;
line-height: 76rpx;
display: block;
background-color: #fff;
border-bottom: 1rpx solid #eee;
font-size: 30rpx;
}
.picker {
width: 100%;
height: 76rpx;
line-height: 76rpx;
}
.picker-more {
width: 14rpx;
height: 24rpx;
position: absolute;
right: 30rpx;
top: 42rpx;
}
.textarea {
height: 100%;
width: 92%;
font-size: 30rpx;
}
.textarea-view {
position: relative;
background-color: #fff;
padding: 24rpx 20rpx 0 30rpx;
display: flex;
font-size: 30rpx;
height: 220rpx;
box-sizing: border-box;
}
.text-icon {
position: absolute;
right: 20rpx;
top: 20rpx;
z-index: 100;
background-color: #fff;
}
.textarea-length-tip {
position: absolute;
right: 28rpx;
bottom: 20rpx;
z-index: 100;
color: #999;
}
.address-wrap {
padding: 20rpx;
}
.smart-address {
margin: 0 auto;
/* height: 420rpx; */
background-color: #fff;
}
.smart-top {
display: flex;
flex-direction: row;
align-items: center;
height: 90rpx;
padding: 28rpx 38rpx 10rpx 20rpx;
border-bottom: 1rpx solid #E8E9EA;
}
.smart-left {
float: left;
overflow: hidden;
}
.smartleft-address {
color: #f40;
font-size: 28rpx;
}
.smartleft-auto {
color: #999;
font-size: 24rpx;
margin-top: 5rpx;
}
.icon-voice {
width: 24rpx;
height: 36rpx;
}
.smart-bottom {
overflow: hidden;
height: 300rpx;
padding: 28rpx 10rpx 14rpx 20rpx;
line-height: 28rpx;
position: relative;
}
.smart-bottom .clear-icon {
position: absolute;
right: 10rpx;
bottom: 10rpx;
}
.textarea-css {
width: 100%;
display: block;
height: 250rpx;
line-height: 42rpx;
color: #333;
font-size: 30rpx;
}
.input-placeholder {
color: #ccc;
}
.textarea-pcss {
color: #d7d7d7ff;
font-size: 28rpx;
line-height: 60rpx;
}
button {
width: 620rpx;
margin: 30rpx 0rpx;
background-color: #ccc;
color: #fff;
margin-left: auto;
margin-right: auto;
font-size: 36rpx;
height: 90rpx;
line-height: 90rpx;
}
.upload-icon {
width: 44rpx;
height: 44rpx;
}
.cropper {
position: absolute;
top: 0;
left: 0;
}
.cropper-buttons {
background-color: rgba(0, 0, 0, 0.4);
}
.btn {
height: 30px;
line-height: 30px;
padding: 0 24rpx;
border-radius: 2px;
color: #fff;
}
.cropper-result image {
width: 100%;
height: 100px;
}
.col-f40 {
color: #56c776 !important;
}
button {
border-radius: 48rpx;
font-size: 32rpx;
}
.iostextarea textarea {
margin-left:-10rpx;
}
.input-v .iostextarea{
margin-left:-10rpx;
}
.input-v .androidtextarea{
margin-left:-8rpx;
}
.shouqi{
margin: 20rpx;
height: 100rpx;
display: flex;
background-color: #fff;
justify-content:space-between;
align-items:center;
padding-left:20rpx;
padding-right: 32rpx;
}
.shouqi .text{
font-size: 30rpx;
color:#ccc;
}
.shouqi image{
width: 44rpx;
height: 44rpx;
}
.tar image{
width: 44rpx;
height: 44rpx;
}
.clearknow{
display:flex;
justify-content:flex-end;
align-items:center;
color:#333;
font-size:24rpx;
}
.clearknow view{
padding:10rpx 34rpx;
background-color:#E8E9EA;
border-radius: 27rpx;
}
.clearknow view:last-child{
background-color:#FFD643;
margin-left:40rpx;
}
.paste{
display:flex;
align-items:center;
}
.paste-title{
color:#56C776;
font-weight:600;
font-size:30rpx;
}
.zhankai{
width:84rpx;
height:44rpx;
display:inline-block;
margin-left:10rpx;
}
.addressInfo-title{
height:80rpx;
padding:22rpx 20rpx;
font-size:28rpx;
color:#333;
display:flex;
justify-content:flex-start;
font-weight:550;
background-color:#fafafa;
box-sizing:border-box;
}
.addressInfo{
display: flex;
background-color: #fff;
position: relative;
color: #666;
font-size: 28rpx;
box-sizing: border-box;
width: 100%;
overflow: hidden;
}
.addressInfo textarea{
max-width:220rpx;
padding-right:10rpx;
box-sizing:border-box;
}
.addressInfo textarea:last-child{
min-width: 190rpx;
padding-right:0rpx;
box-sizing:border-box;
}
.touch-move-active .content, .touch-move-active .del {
-webkit-transform: translateX(0);
transform: translateX(0);
}
.content{
padding: 32rpx 20rpx;
width: 100%;
position: relative;
margin-left: -120rpx;
transform: translateX(120rpx);
-webkit-transform: translateX(120rpx);
transition: all 0.4s;
-webkit-transition: all 0.4s;
border-bottom: 1rpx solid #E8E9EA;
display: flex;
}
.content:last-child{
border:none;
}
.del {
background-color: orangered;
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 120rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
-webkit-transform: translateX(120rpx);
transform: translateX(120rpx);
-webkit-transition: all 0.4s;
transition: all 0.4s;
}
.submit {
width: 100vw;
position: fixed;
left: 0;
bottom: 0;
display: flex;
height: 160rpx;
padding: 0 32rpx;
margin-top: 30rpx;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
z-index: 1000;
background: #fff;
}
.submit .submit-btn {
color:#333;
width: 398rpx;
height: 96rpx;
border-radius: 48rpx;
font-size: 32rpx;
text-align: center;
line-height: 96rpx;
background-color: rgba(243, 203, 60);
}
.submit .submit-btn.clear{
width: 218rpx;
background-color: #fff;
border: 2rpx solid #E8E9EA;
}
.submit-btn text {
margin-left: 10rpx;
}
.submit .submit-btn.disable {
background-color: rgba(243, 203, 60, 0.5);
color:#666;
}
.kong{
width: 100%-120rpx;
background-color: #fff;
padding: 35rpx;
font-size: 28rpx;
color:#666;
text-align: center;
}
.popup {
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
width: 584rpx;
height: 220rpx;
background: #fff;
z-index: 99;
}
.popup-view {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 2;
}
.dialogbtn{
display: flex;
border-top: 1rpx solid #E8E9EA;
justify-content: space-between;
width: 100%;
height: 96rpx;
bottom: 0;
position: absolute;
}
.dialogbtn .headbtn{
color: #333;
font-size: 32rpx;
padding: 25rpx 0;
width: 50%;
text-align: center;
}
.sub{
color:#F3CB3C !important;
border-left:1rpx solid #E8E9EA;
font-weight: 550;
}
.popup-dflex{
display: flex;
border: 1rpx solid #E8E9EA;
border-radius: 8rpx;
padding:18rpx 32rpx;
margin:0 20rpx;
margin-top: 20rpx;
}
.popup-title{
color:#2E3038;
font-size: 30rpx;
font-weight: 550;
text-align: center;
margin: 30rpx 0;
}