From 214f185512ffd83c60f342276e8cb39f95a3567c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=9D=E5=86=9B=E5=8D=8E?= Date: Tue, 11 Mar 2025 20:43:27 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=88=97=E8=A1=A8=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- order/orderConfirm/orderConfirm.vue | 102 ++--- order/orderConfirm/style.scss | 4 +- order/orderList/orderList.vue | 264 +++++++++++ order/orderList/style.scss | 220 +++++++++ pages.json | 15 + pages/cart/cart.vue | 426 +++++++++++++----- pages/cart/style.scss | 331 +++++++++++--- pages/user/user.vue | 23 +- shopProDetail/detail/detail.vue | 7 +- shopProDetail/evallist/evallist.vue | 145 ++++++ shopProDetail/evallist/style.scss | 156 +++++++ static/eval/heart.png | Bin 0 -> 478 bytes static/eval/img.png | Bin 0 -> 525 bytes static/eval/newest.png | Bin 0 -> 732 bytes static/eval/praise.png | Bin 0 -> 489 bytes static/selected.png | Bin 0 -> 2199 bytes store/counter.js | 5 +- uni_modules/uni-swipe-action/changelog.md | 47 ++ .../uni-swipe-action-item/bindingx.js | 302 +++++++++++++ .../components/uni-swipe-action-item/isPC.js | 12 + .../uni-swipe-action-item/mpalipay.js | 195 ++++++++ .../uni-swipe-action-item/mpother.js | 260 +++++++++++ .../components/uni-swipe-action-item/mpwxs.js | 84 ++++ .../uni-swipe-action-item/render.js | 270 +++++++++++ .../uni-swipe-action-item.vue | 348 ++++++++++++++ .../components/uni-swipe-action-item/wx.wxs | 341 ++++++++++++++ .../uni-swipe-action/uni-swipe-action.vue | 60 +++ uni_modules/uni-swipe-action/package.json | 84 ++++ uni_modules/uni-swipe-action/readme.md | 11 + 29 files changed, 3460 insertions(+), 252 deletions(-) create mode 100644 order/orderList/orderList.vue create mode 100644 order/orderList/style.scss create mode 100644 shopProDetail/evallist/evallist.vue create mode 100644 shopProDetail/evallist/style.scss create mode 100644 static/eval/heart.png create mode 100644 static/eval/img.png create mode 100644 static/eval/newest.png create mode 100644 static/eval/praise.png create mode 100644 static/selected.png create mode 100644 uni_modules/uni-swipe-action/changelog.md create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs create mode 100644 uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue create mode 100644 uni_modules/uni-swipe-action/package.json create mode 100644 uni_modules/uni-swipe-action/readme.md diff --git a/order/orderConfirm/orderConfirm.vue b/order/orderConfirm/orderConfirm.vue index 27661cc..830e698 100644 --- a/order/orderConfirm/orderConfirm.vue +++ b/order/orderConfirm/orderConfirm.vue @@ -91,7 +91,7 @@ 订单备注 - + @@ -157,74 +157,6 @@ - - - - - 100 - 满39可用 - - - - - - 新人限时券 - 今日23:59到期 - - - - - - - - - 100 - 满39可用 - - - - - - 新人限时券 - 今日23:59到期 - - - - - - - - - 100 - 满39可用 - - - - - - 新人限时券 - 今日23:59到期 - - - - - - - - - 100 - 满39可用 - - - - - - 新人限时券 - 今日23:59到期 - - - - 不使用优惠券 @@ -243,7 +175,6 @@ + + \ No newline at end of file diff --git a/order/orderList/style.scss b/order/orderList/style.scss new file mode 100644 index 0000000..580dcb4 --- /dev/null +++ b/order/orderList/style.scss @@ -0,0 +1,220 @@ +page{ + background: #f6f6f6; +} +.main{ + .head{ + position: fixed; + z-index: 100; + width: 100%; + top: 0; + left: 0; + background-color: #FFFFFF; + border-bottom: 1rpx solid #f6f6f6; + .head_top{ + display: flex; + align-items: center; + .head_back{ + display: flex; + align-items: center; + border-radius: 50rpx; + margin-left: 10px; + .head_back_img{ + display: block; + width: 18px; + height: 18px; + margin-left: 7px; + } + } + .head_search{ + width: 210px; + margin:0rpx 0px 0rpx 10px;; + display: flex; + align-items: center; + background-color: #F6F6F6; + height: 38px; + border-radius: 50rpx; + font-size: 28rpx; + color: #000000; + justify-content: space-between; + .head_search_img{ + width: 28px; + height: 28px; + margin-right: 13rpx; + margin-left: 23rpx; + } + .head_search_input{ + width: 500rpx; + height: 100%; + font-size: 28rpx; + display: flex; + align-items: center; + } + } + } + .order_nav{ + width: 100%; + display: flex; + background-color: #ffffff; + height: 48px; + margin-top: 5px; + .order_nav_item{ + font-size: 28rpx; + width: 20%; + .order_nav_name{ + width: 100%; + text-align: center; + height: 35px; + color: #666666; + display: flex; + align-items: flex-end; + justify-content: center; + } + .order_nav_m{ + margin: 0 auto; + width: 28px; + height: 10px; + display: block; + } + } + .order_nav_active{ + .order_nav_name{ + font-size: 32rpx; + color: #333333; + font-weight: 500; + } + .order_nav_m{ + background: url(../../static/act.png); + background-repeat: no-repeat; + background-size: 100% 100%; + } + } + } + } + .order_cont{ + .order_list{ + margin: 20rpx 20rpx 0 20rpx; + background-color: #FFFFFF; + border-radius: 16rpx; + padding: 0 25rpx 0 25rpx; + box-shadow: 0 4rpx 8rpx rgba(0,0,0,.05); + .order_type{ + font-size: 34rpx; + color: #000000; + font-weight: 500; + padding: 25rpx 0 25rpx 0; + } + .order_time{ + color: #999999; + font-size: 26rpx; + } + .order_scroll{ + width:100%; + display: flex; + overflow: hidden; + white-space: nowrap; + left: 0; + top: 0; + margin-top: 25rpx; + .order_scroll_ul{ + .order_scroll_li{ + width: 138rpx; + display: inline-block; + margin-right: 20rpx; + .order_scroll_img{ + background: #FFFFFF; + border-radius: 10rpx; + width: 138rpx; + height: 138rpx; + overflow: hidden; + border: 1rpx solid #F3F3F3; + .order_scroll_img_url{ + width: 138rpx; + height: 138rpx; + display: block; + } + } + .order_scroll_title{ + color: #333333; + font-size: 26rpx; + font-weight: 500; + white-space: break-spaces; + text-overflow: ellipsis; + -webkit-box-orient: vertical; + display: -webkit-box; + -webkit-line-clamp: 2; + overflow: hidden; + overflow-wrap: break-word; + margin-top: 20rpx; + } + .order_scroll_price{ + font-size: 32rpx; + color: #FF0000; + font-weight: 500; + margin-top: 10rpx; + } + .order_scroll_market_name{ + color: #999999; + font-size: 28rpx; + text-decoration: line-through; + font-weight: 400; + } + } + } + } + .order_x{ + color: #333333; + font-size: 28rpx; + text-align: right; + .order_price{ + font-size: 34rpx; + font-weight: 500; + color: #000000; + } + .order_price::before{ + content: "¥"; + font-size: 26rpx; + margin: 0 5rpx 0 5rpx; + } + } + .order_bottom{ + display: flex; + align-items: center; + justify-content: space-between; + padding: 25rpx 0 25rpx 0; + .order_l{ + color: #333333; + font-size: 26rpx; + } + .order_r{ + display: flex; + justify-content: flex-end; + .order_btn{ + width: 158rpx; + height: 64rpx; + background: #FFFFFF; + border-radius: 33rpx; + border: 1rpx solid #D9D9D9; + display: flex; + align-items: center; + justify-content: center; + color: #999999; + font-size: 26rpx; + margin-left: 25rpx; + } + .order_bcg{ + width: 158rpx; + height: 64rpx; + background: #FF0000; + border-radius: 33rpx; + border: 1rpx solid #FF0000; + display: flex; + align-items: center; + justify-content: center; + color: #ffffff; + font-size: 26rpx; + } + } + } + } + } +} \ No newline at end of file diff --git a/pages.json b/pages.json index a11e710..a1a1181 100644 --- a/pages.json +++ b/pages.json @@ -89,6 +89,13 @@ "navigationBarTitleText": "", "navigationStyle": "custom" } + }, + { + "path": "evallist/evallist", + "style": { + "navigationBarTitleText": "评价", + "navigationBarBackgroundColor": "#FFFFFF" + } }] }, { @@ -99,6 +106,14 @@ "navigationBarTitleText": "确认订单", "navigationBarBackgroundColor": "#FCEEEF" } + },{ + "path": "orderList/orderList", + "style": { + "navigationBarTitleText": "我的订单", + "navigationBarBackgroundColor": "#FCEEEF", + "navigationStyle": "custom", + "enablePullDownRefresh": true + } }] } ], diff --git a/pages/cart/cart.vue b/pages/cart/cart.vue index 614266f..1b8a4ab 100644 --- a/pages/cart/cart.vue +++ b/pages/cart/cart.vue @@ -1,4 +1,5 @@ + + \ No newline at end of file diff --git a/shopProDetail/evallist/style.scss b/shopProDetail/evallist/style.scss new file mode 100644 index 0000000..688addb --- /dev/null +++ b/shopProDetail/evallist/style.scss @@ -0,0 +1,156 @@ +page{ + background-color: #f6f6f6; +} +.mian{ + .head{ + background-color: #FFFFFF; + padding: 0 20rpx 20rpx 20rpx; + flex-wrap: wrap; + display: flex; + position: sticky; + top: 0; + left: 0; + border-bottom: 1rpx solid #f6f6f6; + .eval_tag{ + font-size: 28rpx; + color: #333333; + background-color: #F5F6FA; + border: 1rpx solid #F5F6FA; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50rpx; + padding: 8rpx 25rpx 8rpx 25rpx; + box-sizing: border-box; + margin: 20rpx 0 0 20rpx ; + .eval_tag_img{ + width: 28rpx; + height: 28rpx; + display: block; + margin-right: 10rpx; + } + } + .eval_tag text{ + color: #999999; + } + .eval_tag_active{ + background: #FFD7D7; + border: 1rpx solid #FFA0A0; + color: #FF5D5D; + + } + .eval_tag_active text{ + color: #FF5D5D; + } + } + .eval_item{ + margin-top: 10rpx; + background-color: #FFFFFF; + margin: 20rpx 20rpx 0 20rpx; + border-radius: 16rpx; + .eval_item_top{ + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 23rpx 0 23rpx; + height: 79rpx; + + background-color: #FFFFFF; + .eval_item_l{ + display: flex; + align-items: center; + .eval_item_userimg{ + width: 40rpx; + height: 40rpx; + border-radius: 50rpx; + background-color: #000 + } + .eval_item_username{ + color: #000000; + font-size: 24rpx; + margin-left: 10rpx; + + } + .eval_item_userdesc{ + width: 95rpx; + height: 34rpx; + background: #FFF4CD; + border-radius: 4rpx; + border: 1rpx solid #F9D448; + font-size: 22rpx; + color: #D0AA1B; + display: flex; + align-items: center; + justify-content: center; + margin-left: 10rpx; + } + .eval_item_usertext{ + margin-left: 10rpx; + display: flex; + align-items: center; + width: 95rpx; + height: 34rpx; + background: linear-gradient( 90deg, #FAEAD3 0%, #FED4AE 100%); + border-radius: 4rpx; + color: #745030; + font-size: 22rpx; + display: flex; + align-items: center; + justify-content: center; + .eval_item_usertext_img{ + width: 28rpx; + height: 28rpx; + display: block; + } + } + } + } + .eval_item_text{ + padding: 20rpx; + font-size: 30rpx; + color: #666666; + } + .eval_item_ul{ + display: flex; + flex-wrap: wrap; + .eval_item_li{ + width: 212rpx; + height: 212rpx; + border-radius: 8rpx; + margin-left: 20rpx; + margin-bottom: 20rpx; + } + .eval_item_li image{ + width: 212rpx; + height: 212rpx; + border-radius: 8rpx; + display: block; + } + } + .eval_item_bottom{ + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 20rpx 20rpx 20rpx; + .eval_item_time{ + font-size: 24rpx; + color: #999999; + } + .eval_item_numa{ + display: flex; + font-size: 24rpx; + color: #999999; + align-items: center; + } + .eval_item_numa image{ + width: 28rpx; + height: 28rpx; + display: block; + margin-right: 10rpx; + } + } + + } + + +} \ No newline at end of file diff --git a/static/eval/heart.png b/static/eval/heart.png new file mode 100644 index 0000000000000000000000000000000000000000..4cad4cf0c2b4445fad6fff59262677edea526163 GIT binary patch literal 478 zcmeAS@N?(olHy`uVBq!ia0vp^79h;Q3?%1AoYnzSjKx9jP7LeL$-D$|JOX?|T!Hj| zYM=o5<32#M#7lzwf*Ax93>*UD6Y>k{8~P{AU$B0|{__{^zgJQW=>|GM(bL5-L_+fE z!P{kr6c}6&^121jZj0cU^Z)gG;3^v;bHS|^K4 zS5A7qD0pk1@%pTJ@nO6?7giq>{1L{?&SJ{p5Y)`Ef^&hILr616&FV&WH&cm5Ki+Q* zo~x!=NQa&+Obb0*WVmY5<5Mc3ozrG7UiC$1kCw&18%vTd7A+6nXsg}K#hc@!W%S8E zfbo32+KZ((CnPS4o534t_G0DD4-K4ENoF=FO>&>w($#DYJ|0@Irg1u3Dv!vE$!0mdK II;Vst0EaoeGynhq literal 0 HcmV?d00001 diff --git a/static/eval/img.png b/static/eval/img.png new file mode 100644 index 0000000000000000000000000000000000000000..096058418a7b45419f8680f207824aa8d560582b GIT binary patch literal 525 zcmeAS@N?(olHy`uVBq!ia0vp^79h;Q3?%1AoYnzSjKx9jP7LeL$-D$|Vgr0aT!FNK zfq{dA1CX?^umF;#rlvsB#Kgqd*ciw#GBN@(fFw`^NWvKq1wbie08s-MIeF)F0MG)t zk|4ie1_1#D1&~bv2?_ZH1@#RL{rwZ>FId0-{Q3L$-{%;gZUZ{c#M8ww#N+teYqz&G zDG0D7@Xy#5X#IvS#Nhq^8LbW5rXKFezJK-36{CF{eoj2GiGO9%cZM3xgKKYlC|rC0 zK;kCj8`C`(WLNxQeZSs()8iLXYM1PT_m@qH^QvC|j(eX0V>Iie^$juxH!BuI)=c7i z+Z1K}crKsyfh{+#ht@UU{w80nvuggXMTetSEWDZS)^xP6s*d;Q!JBPMG`Y5Q$38wI zFoDxJ!lb9r^8VUG8$#34U*(1gv3IYYyG};m*MuqCdd2_Zs}~hY6i;ORJE_PO%dxzs zQhPeb7R3|Cu5Z%fh~>CGXWNN%#e{|GEFxdpC$u~icw`{v#N+17aX5rSaR$#p{@*1W zbsR4RrUh7v@h3)2%v;;_k>``cRfDkdeUXLd4C^!0fBjrhQ@`S)>anybw{7?BQu`gY aXWm@4s&F+v*So-wX7F_Nb6Mw<&;$S;YRsGf literal 0 HcmV?d00001 diff --git a/static/eval/newest.png b/static/eval/newest.png new file mode 100644 index 0000000000000000000000000000000000000000..04ad90e44b1022a02b8de8dbf5140f64c8a10438 GIT binary patch literal 732 zcmeAS@N?(olHy`uVBq!ia0vp^79h;Q3?%1AoYnzSjKx9jP7LeL$-D$|(gJ)!T!FNK zfq{dA1CX?^umF;#rlvsB#KZ(h8iRq6kr7Z3NJ0Qm3djJGKuI72q6V47lse;55DT

=iCKtOy#LP32)Lx2B-`STa7-?0Du`3v{&zrUTAtO<1LcTX3`5Rck=e+8J zi&@VL|C8?LS|EQsAvofJkjzex9WknL;a#mvORM!x>)xsJxq3fWJN9L&%*}&2AypB# z!h-JDzS^O?^j=+CuIBS?^(;4*7joY=-#6Va;b4Hn=bhq9di{@I`sUA2n$);_r)13J z6SLZ9-SN8U`ufbj%^C*VdUV`EYVWwPJxw#Md*@aazBhCApObsbDrc2lzIuA~jA<8x zSFoGUzj#e-XGhA<-MQ+wFKKOBZ+g(SJmb;gsq?>zp5c6V?Q~82QoGWnZ>zq4e|YQG dCGWqCXFSr*7@wOr0hnGGJYD@<);T3K0RTTjH{}2T literal 0 HcmV?d00001 diff --git a/static/eval/praise.png b/static/eval/praise.png new file mode 100644 index 0000000000000000000000000000000000000000..f8850e743de1c977eedbd8deee550a6666d90d7c GIT binary patch literal 489 zcmeAS@N?(olHy`uVBq!ia0vp^79h;Q3?%1AoYnzSjKx9jP7LeL$-D$|G6Q@sMh>Yt=SwzK*n646jYbGcFunVpk+!WL4Lsu0tyNS1_lle z0Riy|3Hb#D^$iXE6DG``zhM3T{pZi$zyCgQ=NE3Ea~V8c978;gpS^aMugQRi^?~n^ z&aNNauLL6Q|5u#4AbG*XZ%4S#%ZkU(Dp|ZbsDA1dt4$N{NRqmD%0oShPzIS=PgHL8@&2}DH z$qN^IUh{oXyneMn#l?=>d;aAkw%#(HN%v&TwCi|6onEYW`To>TRs0s?p7PfxTJ&1p z8hGzeJzj9GM3jqLL`uMntA&+ISR_ke8dr-XSGq!u2nV;wx&VpB4M7TL0y6?uI7Vm* zybH{Td+=BPviP?I9>qxYUHK1pec$`wLvQy@J-PQ=)`Ty<*E#)Z{4=(W;9IuqzrVZ; P3^@i*S3j3^P6 zIkmltqTDKl5jJ8oonojaBr0~cTJd5)S@Aag z2(#Mw;1790o!0K@WM{Z!X>~CDGaM=Ni;SpqEM3xr=#3>U&Q?qeUQ`2Ai8HK12h?$A z7zD_(S_;4$=Mzmew^%SR8VoHB^8iTw=#UQ+!qvkp`tNT8s(z85jPn3?$>K_glnydX ztYd$02gqKnXXYnqpuIr*;Uy*z>Sa$B*ONhDPqzPFI$-6x&a?esQ1h;%T8{=qtcrvi zCJ;Up6Lc__47^1H_L2gC{f}iId@$ct*mLLONX~fta>Sn+SfW}`GaJ5xt|gf)HOSF0 zp47A4ftK7lS6`=1!xFtis$AeWevuHkTz{uNe5HjZh-88=&(br~YN71|7s<%<2q(pa zc6uz-6&4nJ@y)k|^aTb?;QlJ{lAXsf)lMTie)SCQ#4W+q1nDf0SHG(MbvqQoh|2|O zHotltqYFw{K+jsYZbNC-xHcVsUTR(Wa#!0NjfRO_MUgfCh<>DBscp0CpgThCv@8vI zeBn2?`+)79XhtU&SJ$z>7~(eG7)(~Z=x%fL1dfVAl;IE+p-cfiC$AT61Z}gv8W;Ebc%Xq&gSi?|;sc0el?-+7^A+^OLz6h`AwW>I8o@aub&JOZs1bIXr6aq+f}!aWc0(N>85Iy&I|nBVrn|7;&z@imPKN!txyHD^4B(hsR`XtY;1_jM}HaSKX*d%qj6EWW{5{i zbb;`D*%RQKMq-jyNu5|c$uH+AiUo#lLKVwxPBy_!=ZqIu1{VH(G`Xc_Yc$^?%_92u zkvD-Uyuhv(6|DiDeNk^Z&$B3*N2|q#DM9G&Lek^4h$F(rcH3Ag+VR)?=-H2yi^v?i zaegQNw7gZqa&yiVoEP)CK|pcCrVI}{uH4mQZTh-_u|YiB_~Fy|EHX`%JWyx6n3()C zVp-(|W>%vjE81Kw9=M5B$9)#Nq>G{$kie!Xu~bSXGfQ*7J8WRA75AYvnpD<*#wh7W z3+{10z;NDNEFNSpzHE4!1Z6fm$nJ({)Jced)fw3Be6VJ0Q3@_R2BX;RNtKlbf-LJ=p;Gyuz8PC1NJ5k)TAOn=>1;KIwQ;*f+_*vi zvJ-Z*mio#~zc~1CAn%PdG_ivdGGl>U7UFwCWJx=&DTrV?|BK-2iX2~{$P|s*7toCz`xCTH2(NLb_s#pI`6vf^i<-V zV#+d#mip`@q+xX$YD=*UZz2ny332^!snTLM7$(zD#XVY0dlfQJI^Tu!U@p=IxlWvj z@yFE3Jgl7%CU#S13+41u$qbUXIN+9raDvs68_-6H5K{7pl=2kwp06f2a}O-oDVf>V zX@%t>P`Y?uux;QDq?M3{)m{r9R%WTv`KS`FKB%5tyP1a8de#LwjKIFcjS0j>bH7!k zuw7w6mfFl=$ydx^E0jKu1UpodRYRDvF572nAB;)uG#YB47%-{t0cpCxg5G@l%K8{A zi`8Np2JUU~qq7X@d|ugD=E7yU!3;7(EuH&zY7pZPj~9??`0|i$mkv`_WFK$bNt&qJ zU)b}m|Ks;YErzk=;XgTeGIe?7mWp6}sSb&&RwXc~mwmmrhz#iYb`1muRdZdvg4r<0 z{Qa6Afx!$`#ddQ82ydV0t0FMyBJ%oGGaq1qG4Br$7}Oiw-kn9HFl{=uPT!4T>c=|> zk`|3Nt{ const statusHeight = ref(uni.getMenuButtonBoundingClientRect()['height']); const headerHeight = ref(uni.getSystemInfoSync()['statusBarHeight']); const statusBartop = ref(uni.getMenuButtonBoundingClientRect()['top']); - + const ButtonWidth = ref(uni.getMenuButtonBoundingClientRect().width); + const ButtonHeight = ref(uni.getMenuButtonBoundingClientRect().height) //定义数据修改的方法(action) const clickSType = (params)=>{ @@ -20,6 +21,8 @@ export const useCounterStore = defineStore('counter',()=>{ //以对象的形式return供组件调用 return{ + ButtonWidth, + ButtonHeight, statusHeight, headerHeight, statusBartop, diff --git a/uni_modules/uni-swipe-action/changelog.md b/uni_modules/uni-swipe-action/changelog.md new file mode 100644 index 0000000..e28472f --- /dev/null +++ b/uni_modules/uni-swipe-action/changelog.md @@ -0,0 +1,47 @@ +## 1.3.10(2024-01-17) +- 修复 点击按钮时,按钮会被点击穿透导致自动收缩的 bug(兼容阿里/百度/抖音小程序) +## 1.3.9(2024-01-17) +- 修复 点击按钮时,按钮会被点击穿透导致自动收缩的 bug +## 1.3.8(2023-04-13) +- 修复`uni-swipe-action`和`uni-swipe-action-item`不同时使用导致 closeOther 方法报错的 bug +## 1.3.7(2022-06-06) +- 修复 vue3 下使用组件不能正常运行的Bug +## 1.3.6(2022-05-31) +- 修复 h5端点击click触发两次的Bug +## 1.3.5(2022-05-23) +- 修复 isPC 找不到的Bug +## 1.3.4(2022-05-19) +- 修复 在 nvue 下 disabled 失效的bug +## 1.3.3(2022-03-31) +- 修复 按钮字体大小不能设置的bug +## 1.3.2(2022-03-16) +- 修复 h5和app端下报el错误的bug +## 1.3.1(2022-03-07) +- 修复 HBuilderX 1.4.X 版本中,h5和app端下报错的bug +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swipe-action](https://uniapp.dcloud.io/component/uniui/uni-swipe-action) +## 1.2.4(2021-08-20) +- 优化 close-all 方法 +## 1.2.3(2021-08-20) +- 新增 close-all 方法,关闭所有已打开的组件 +## 1.2.2(2021-08-17) +- 新增 resize() 方法,在非微信小程序、h5、app-vue端出现不能滑动的问题的时候,重置组件 +- 修复 app 端偶尔出现类似 Page[x][-x,xx;-x,xx,x,x-x] 的问题 +- 优化 微信小程序、h5、app-vue 滑动逻辑,避免出现动态新增组件后不能滑动的问题 +## 1.2.1(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +- 修复 跨页面修改组件数据 ,导致不能滑动的问题 +## 1.1.10(2021-06-17) +- 修复 按钮点击执行两次的bug +## 1.1.9(2021-05-12) +- 新增 项目示例地址 +## 1.1.8(2021-03-26) +- 修复 微信小程序 nv_navigator is not defined 报错的bug +## 1.1.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 左侧滑动 +- 新增 插槽使用方式 +- 新增 threshold 属性,可以控制滑动缺省值 +- 优化 长列表滚动性能 +- 修复 滚动页面时触发组件滑动的Bug diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js new file mode 100644 index 0000000..707e432 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js @@ -0,0 +1,302 @@ +let bindIngXMixins = {} + +// #ifdef APP-NVUE +const BindingX = uni.requireNativePlugin('bindingx'); +const dom = uni.requireNativePlugin('dom'); +const animation = uni.requireNativePlugin('animation'); + +bindIngXMixins = { + data() { + return {} + }, + + watch: { + show(newVal) { + if (this.autoClose) return + if (this.stop) return + this.stop = true + if (newVal) { + this.open(newVal) + } else { + this.close() + } + }, + leftOptions() { + this.getSelectorQuery() + this.init() + }, + rightOptions(newVal) { + this.init() + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.box = this.getEl(this.$refs['selector-box--hock']) + this.selector = this.getEl(this.$refs['selector-content--hock']); + this.leftButton = this.getEl(this.$refs['selector-left-button--hock']); + this.rightButton = this.getEl(this.$refs['selector-right-button--hock']); + this.init() + }, + // beforeDestroy() { + // this.swipeaction.children.forEach((item, index) => { + // if (item === this) { + // this.swipeaction.children.splice(index, 1) + // } + // }) + // }, + methods: { + init() { + this.$nextTick(() => { + this.x = 0 + this.button = { + show: false + } + setTimeout(() => { + this.getSelectorQuery() + }, 200) + }) + }, + onClick(index, item, position) { + this.$emit('click', { + content: item, + index, + position + }) + }, + touchstart(e) { + // fix by mehaotian 禁止滑动 + if (this.disabled) return + // 每次只触发一次,避免多次监听造成闪烁 + if (this.stop) return + this.stop = true + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + let expression = this.range(this.x, -rightWidth, leftWidth) + let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0) + let rightExpression = this.range(this.x + rightWidth, 0, rightWidth) + + this.eventpan = BindingX.bind({ + anchor: this.box, + eventType: 'pan', + props: [{ + element: this.selector, + property: 'transform.translateX', + expression + }, { + element: this.leftButton, + property: 'transform.translateX', + expression: leftExpression + }, { + element: this.rightButton, + property: 'transform.translateX', + expression: rightExpression + }, ] + }, (e) => { + // nope + if (e.state === 'end') { + this.x = e.deltaX + this.x; + this.isclick = true + this.bindTiming(e.deltaX) + } + }); + }, + touchend(e) { + if (this.isopen !== 'none' && !this.isclick) { + this.open('none') + } + }, + bindTiming(x) { + const left = this.x + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + const threshold = this.threshold + if (!this.isopen || this.isopen === 'none') { + if (left > threshold) { + this.open('left') + } else if (left < -threshold) { + this.open('right') + } else { + this.open('none') + } + } else { + if ((x > -leftWidth && x < 0) || x > rightWidth) { + if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) { + this.open('left') + } else { + this.open('none') + } + } else { + if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) { + this.open('right') + } else { + this.open('none') + } + } + } + }, + + /** + * 移动范围 + * @param {Object} num + * @param {Object} mix + * @param {Object} max + */ + range(num, mix, max) { + return `min(max(x+${num}, ${mix}), ${max})` + }, + + /** + * 开启swipe + */ + open(type) { + this.animation(type) + }, + + /** + * 关闭swipe + */ + close() { + this.animation('none') + }, + + /** + * 开启关闭动画 + * @param {Object} type + */ + animation(type) { + const time = 300 + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + if (this.eventpan && this.eventpan.token) { + BindingX.unbind({ + token: this.eventpan.token, + eventType: 'pan' + }) + } + + switch (type) { + case 'left': + Promise.all([ + this.move(this.selector, leftWidth), + this.move(this.leftButton, 0), + this.move(this.rightButton, rightWidth * 2) + ]).then(() => { + this.setEmit(leftWidth, type) + }) + break + case 'right': + Promise.all([ + this.move(this.selector, -rightWidth), + this.move(this.leftButton, -leftWidth * 2), + this.move(this.rightButton, 0) + ]).then(() => { + this.setEmit(-rightWidth, type) + }) + break + default: + Promise.all([ + this.move(this.selector, 0), + this.move(this.leftButton, -leftWidth), + this.move(this.rightButton, rightWidth) + ]).then(() => { + this.setEmit(0, type) + }) + + } + }, + setEmit(x, type) { + const leftWidth = this.button.left.width + const rightWidth = this.button.right.width + this.isopen = this.isopen || 'none' + this.stop = false + this.isclick = false + // 只有状态不一致才会返回结果 + if (this.isopen !== type && this.x !== x) { + if (type === 'left' && leftWidth > 0) { + this.$emit('change', 'left') + } + if (type === 'right' && rightWidth > 0) { + this.$emit('change', 'right') + } + if (type === 'none') { + this.$emit('change', 'none') + } + } + this.x = x + this.isopen = type + }, + move(ref, value) { + return new Promise((resolve, reject) => { + animation.transition(ref, { + styles: { + transform: `translateX(${value})`, + }, + duration: 150, //ms + timingFunction: 'linear', + needLayout: false, + delay: 0 //ms + }, function(res) { + resolve(res) + }) + }) + + }, + + /** + * 获取ref + * @param {Object} el + */ + getEl(el) { + return el.ref + }, + /** + * 获取节点信息 + */ + getSelectorQuery() { + Promise.all([ + this.getDom('left'), + this.getDom('right'), + ]).then((data) => { + let show = 'none' + if (this.autoClose) { + show = 'none' + } else { + show = this.show + } + + if (show === 'none') { + // this.close() + } else { + this.open(show) + } + + }) + + }, + getDom(str) { + return new Promise((resolve, reject) => { + dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => { + if (data) { + this.button[str] = data.size + resolve(data) + } else { + reject() + } + }) + }) + } + } +} + +// #endif + +export default bindIngXMixins diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js new file mode 100644 index 0000000..917cb48 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js @@ -0,0 +1,12 @@ +export function isPC() { + var userAgentInfo = navigator.userAgent; + var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; + var flag = true; + for (let v = 0; v < Agents.length - 1; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + flag = false; + break; + } + } + return flag; +} diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js new file mode 100644 index 0000000..35c796b --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js @@ -0,0 +1,195 @@ +export default { + data() { + return { + x: 0, + transition: false, + width: 0, + viewWidth: 0, + swipeShow: 0 + } + }, + watch: { + show(newVal) { + if (this.autoClose) return + if (newVal && newVal !== 'none') { + this.transition = true + this.open(newVal) + } else { + this.close() + } + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.isopen = false + setTimeout(() => { + this.getQuerySelect() + }, 50) + }, + methods: { + appTouchStart(e) { + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + /** + * 移动触发 + * @param {Object} e + */ + onChange(e) { + this.moveX = e.detail.x + this.isclose = false + }, + touchstart(e) { + this.transition = false + this.isclose = true + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + }, + touchmove(e) {}, + touchend(e) { + // 0的位置什么都不执行 + if (this.isclose && this.isopen === 'none') return + if (this.isclose && this.isopen !== 'none') { + this.transition = true + this.close() + } else { + this.move(this.moveX + this.leftWidth) + } + }, + + /** + * 移动 + * @param {Object} moveX + */ + move(moveX) { + // 打开关闭的处理逻辑不太一样 + this.transition = true + // 未打开状态 + if (!this.isopen || this.isopen === 'none') { + if (moveX > this.threshold) { + this.open('left') + } else if (moveX < -this.threshold) { + this.open('right') + } else { + this.close() + } + } else { + if (moveX < 0 && moveX < this.rightWidth) { + const rightX = this.rightWidth + moveX + if (rightX < this.threshold) { + this.open('right') + } else { + this.close() + } + } else if (moveX > 0 && moveX < this.leftWidth) { + const leftX = this.leftWidth - moveX + if (leftX < this.threshold) { + this.open('left') + } else { + this.close() + } + } + + } + + }, + + /** + * 打开 + */ + open(type) { + this.x = this.moveX + this.animation(type) + }, + + /** + * 关闭 + */ + close() { + this.x = this.moveX + // TODO 解决 x 值不更新的问题,所以会多触发一次 nextTick ,待优化 + this.$nextTick(() => { + this.x = -this.leftWidth + if (this.isopen !== 'none') { + this.$emit('change', 'none') + } + this.isopen = 'none' + }) + }, + + /** + * 执行结束动画 + * @param {Object} type + */ + animation(type) { + this.$nextTick(() => { + if (type === 'left') { + this.x = 0 + } else { + this.x = -this.rightWidth - this.leftWidth + } + + if (this.isopen !== type) { + this.$emit('change', type) + } + this.isopen = type + }) + + }, + getSlide(x) {}, + getQuerySelect() { + const query = uni.createSelectorQuery().in(this); + query.selectAll('.movable-view--hock').boundingClientRect(data => { + this.leftWidth = data[1].width + this.rightWidth = data[2].width + this.width = data[0].width + this.viewWidth = this.width + this.rightWidth + this.leftWidth + if (this.leftWidth === 0) { + // TODO 疑似bug ,初始化的时候如果x 是0,会导致移动位置错误,所以让元素超出一点 + this.x = -0.1 + } else { + this.x = -this.leftWidth + } + this.moveX = this.x + this.$nextTick(() => { + this.swipeShow = 1 + }) + + if (!this.buttonWidth) { + this.disabledView = true + } + + if (this.autoClose) return + if (this.show !== 'none') { + this.transition = true + this.open(this.shows) + } + }).exec(); + + } + } +} diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js new file mode 100644 index 0000000..d389bce --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js @@ -0,0 +1,260 @@ +let otherMixins = {} + +// #ifndef APP-PLUS|| MP-WEIXIN || H5 +const MIN_DISTANCE = 10; +otherMixins = { + data() { + // TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug + const elClass = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}` + return { + uniShow: false, + left: 0, + buttonShow: 'none', + ani: false, + moveLeft: '', + elClass + } + }, + watch: { + show(newVal) { + if (this.autoClose) return + this.openState(newVal) + }, + left() { + this.moveLeft = `translateX(${this.left}px)` + }, + buttonShow(newVal) { + if (this.autoClose) return + this.openState(newVal) + }, + leftOptions() { + this.init() + }, + rightOptions() { + this.init() + } + }, + mounted() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + this.init() + }, + methods: { + init() { + clearTimeout(this.timer) + this.timer = setTimeout(() => { + this.getSelectorQuery() + }, 100) + // 移动距离 + this.left = 0 + this.x = 0 + }, + + closeSwipe(e) { + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + }, + appTouchStart(e) { + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + touchstart(e) { + if (this.disabled) return + this.ani = false + this.x = this.left || 0 + this.stopTouchStart(e) + this.autoClose && this.closeSwipe() + }, + touchmove(e) { + if (this.disabled) return + // 是否可以滑动页面 + this.stopTouchMove(e); + if (this.direction !== 'horizontal') { + return; + } + this.move(this.x + this.deltaX) + return false + }, + touchend() { + if (this.disabled) return + this.moveDirection(this.left) + }, + /** + * 设置移动距离 + * @param {Object} value + */ + move(value) { + value = value || 0 + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + // 获取可滑动范围 + this.left = this.range(value, -rightWidth, leftWidth); + }, + + /** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ + range(num, min, max) { + return Math.min(Math.max(num, min), max); + }, + /** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + */ + moveDirection(left) { + const threshold = this.threshold + const isopen = this.isopen || 'none' + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + if (this.deltaX === 0) { + this.openState('none') + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > + 0 && rightWidth + + left < threshold)) { + // right + this.openState('right') + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > + 0 && + leftWidth - left < threshold)) { + // left + this.openState('left') + } else { + // default + this.openState('none') + } + }, + + /** + * 开启状态 + * @param {Boolean} type + */ + openState(type) { + const leftWidth = this.leftWidth + const rightWidth = this.rightWidth + let left = '' + this.isopen = this.isopen ? this.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + + if (this.isopen !== type) { + this.throttle = true + this.$emit('change', type) + } + + this.isopen = type + // 添加动画类 + this.ani = true + this.$nextTick(() => { + this.move(left) + }) + // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的 + }, + close() { + this.openState('none') + }, + getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; + }, + + /** + * 重置滑动状态 + * @param {Object} event + */ + resetTouchStatus() { + this.direction = ''; + this.deltaX = 0; + this.deltaY = 0; + this.offsetX = 0; + this.offsetY = 0; + }, + + /** + * 设置滑动开始位置 + * @param {Object} event + */ + stopTouchStart(event) { + this.resetTouchStatus(); + const touch = event.touches[0]; + this.startX = touch.clientX; + this.startY = touch.clientY; + }, + + /** + * 滑动中,是否禁止打开 + * @param {Object} event + */ + stopTouchMove(event) { + const touch = event.touches[0]; + this.deltaX = touch.clientX - this.startX; + this.deltaY = touch.clientY - this.startY; + this.offsetX = Math.abs(this.deltaX); + this.offsetY = Math.abs(this.deltaY); + this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY); + }, + + getSelectorQuery() { + const views = uni.createSelectorQuery().in(this) + views + .selectAll('.' + this.elClass) + .boundingClientRect(data => { + if (data.length === 0) return + let show = 'none' + if (this.autoClose) { + show = 'none' + } else { + show = this.show + } + this.leftWidth = data[0].width || 0 + this.rightWidth = data[1].width || 0 + this.buttonShow = show + }) + .exec() + } + } +} + +// #endif + +export default otherMixins diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js new file mode 100644 index 0000000..08de1c9 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js @@ -0,0 +1,84 @@ +let mpMixins = {} +let is_pc = null +// #ifdef H5 +import { + isPC +} from "./isPC" +is_pc = isPC() +// #endif +// #ifdef APP-VUE|| MP-WEIXIN || H5 + +mpMixins = { + data() { + return { + is_show: 'none' + } + }, + watch: { + show(newVal) { + this.is_show = this.show + } + }, + created() { + this.swipeaction = this.getSwipeAction() + if (this.swipeaction && Array.isArray(this.swipeaction.children)) { + this.swipeaction.children.push(this) + } + }, + mounted() { + this.is_show = this.show + }, + methods: { + // wxs 中调用 + closeSwipe(e) { + if (this.autoClose && this.swipeaction) { + this.swipeaction.closeOther(this) + } + }, + + change(e) { + this.$emit('change', e.open) + if (this.is_show !== e.open) { + this.is_show = e.open + } + }, + + appTouchStart(e) { + if (is_pc) return + const { + clientX + } = e.changedTouches[0] + this.clientX = clientX + this.timestamp = new Date().getTime() + }, + appTouchEnd(e, index, item, position) { + if (is_pc) return + const { + clientX + } = e.changedTouches[0] + // fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题 + let diff = Math.abs(this.clientX - clientX) + let time = (new Date().getTime()) - this.timestamp + if (diff < 40 && time < 300) { + this.$emit('click', { + content: item, + index, + position + }) + } + }, + onClickForPC(index, item, position) { + if (!is_pc) return + // #ifdef H5 + this.$emit('click', { + content: item, + index, + position + }) + // #endif + } + } +} + +// #endif +export default mpMixins diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js new file mode 100644 index 0000000..78f0ec6 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js @@ -0,0 +1,270 @@ +const MIN_DISTANCE = 10; +export default { + showWatch(newVal, oldVal, ownerInstance, instance, self) { + var state = self.state + var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el + if (!$el) return + this.getDom(instance, ownerInstance, self) + if (newVal && newVal !== 'none') { + this.openState(newVal, instance, ownerInstance, self) + return + } + + if (state.left) { + this.openState('none', instance, ownerInstance, self) + } + this.resetTouchStatus(instance, self) + }, + + /** + * 开始触摸操作 + * @param {Object} e + * @param {Object} ins + */ + touchstart(e, ownerInstance, self) { + let instance = e.instance; + let disabled = instance.getDataset().disabled + let state = self.state; + this.getDom(instance, ownerInstance, self) + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + if (disabled) return + // 开始触摸时移除动画类 + instance.requestAnimationFrame(function() { + instance.removeClass('ani'); + ownerInstance.callMethod('closeSwipe'); + }) + + // 记录上次的位置 + state.x = state.left || 0 + // 计算滑动开始位置 + this.stopTouchStart(e, ownerInstance, self) + }, + + /** + * 开始滑动操作 + * @param {Object} e + * @param {Object} ownerInstance + */ + touchmove(e, ownerInstance, self) { + let instance = e.instance; + // 删除之后已经那不到实例了 + if (!instance) return; + let disabled = instance.getDataset().disabled + let state = self.state + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + if (disabled) return + // 是否可以滑动页面 + this.stopTouchMove(e, self); + if (state.direction !== 'horizontal') { + return; + } + if (e.preventDefault) { + // 阻止页面滚动 + e.preventDefault() + } + let x = state.x + state.deltaX + this.move(x, instance, ownerInstance, self) + }, + + /** + * 结束触摸操作 + * @param {Object} e + * @param {Object} ownerInstance + */ + touchend(e, ownerInstance, self) { + let instance = e.instance; + let disabled = instance.getDataset().disabled + let state = self.state + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = this.getDisabledType(disabled) + + if (disabled) return + // 滑动过程中触摸结束,通过阙值判断是开启还是关闭 + // fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13 + this.moveDirection(state.left, instance, ownerInstance, self) + + }, + + /** + * 设置移动距离 + * @param {Object} value + * @param {Object} instance + * @param {Object} ownerInstance + */ + move(value, instance, ownerInstance, self) { + value = value || 0 + let state = self.state + let leftWidth = state.leftWidth + let rightWidth = state.rightWidth + // 获取可滑动范围 + state.left = this.range(value, -rightWidth, leftWidth); + instance.requestAnimationFrame(function() { + instance.setStyle({ + transform: 'translateX(' + state.left + 'px)', + '-webkit-transform': 'translateX(' + state.left + 'px)' + }) + }) + + }, + + /** + * 获取元素信息 + * @param {Object} instance + * @param {Object} ownerInstance + */ + getDom(instance, ownerInstance, self) { + var state = self.state + var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el + var leftDom = $el.querySelector('.button-group--left') + var rightDom = $el.querySelector('.button-group--right') + + state.leftWidth = leftDom.offsetWidth || 0 + state.rightWidth = rightDom.offsetWidth || 0 + state.threshold = instance.getDataset().threshold + }, + + getDisabledType(value) { + return (typeof(value) === 'string' ? JSON.parse(value) : value) || false; + }, + + /** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ + range(num, min, max) { + return Math.min(Math.max(num, min), max); + }, + + + /** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + * @param {Object} ownerInstance + * @param {Object} ins + */ + moveDirection(left, ins, ownerInstance, self) { + var state = self.state + var threshold = state.threshold + var position = state.position + var isopen = state.isopen || 'none' + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + if (state.deltaX === 0) { + this.openState('none', ins, ownerInstance, self) + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && + rightWidth + + left < threshold)) { + // right + this.openState('right', ins, ownerInstance, self) + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 && + leftWidth - left < threshold)) { + // left + this.openState('left', ins, ownerInstance, self) + } else { + // default + this.openState('none', ins, ownerInstance, self) + } + }, + + + /** + * 开启状态 + * @param {Boolean} type + * @param {Object} ins + * @param {Object} ownerInstance + */ + openState(type, ins, ownerInstance, self) { + let state = self.state + let leftWidth = state.leftWidth + let rightWidth = state.rightWidth + let left = '' + state.isopen = state.isopen ? state.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + // && !state.throttle + + if (state.isopen !== type) { + state.throttle = true + ownerInstance.callMethod('change', { + open: type + }) + + } + + state.isopen = type + // 添加动画类 + ins.requestAnimationFrame(() => { + ins.addClass('ani'); + this.move(left, ins, ownerInstance, self) + }) + }, + + + getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; + }, + + /** + * 重置滑动状态 + * @param {Object} event + */ + resetTouchStatus(instance, self) { + let state = self.state; + state.direction = ''; + state.deltaX = 0; + state.deltaY = 0; + state.offsetX = 0; + state.offsetY = 0; + }, + + /** + * 设置滑动开始位置 + * @param {Object} event + */ + stopTouchStart(event, ownerInstance, self) { + let instance = event.instance; + let state = self.state + this.resetTouchStatus(instance, self); + var touch = event.touches[0]; + state.startX = touch.clientX; + state.startY = touch.clientY; + }, + + /** + * 滑动中,是否禁止打开 + * @param {Object} event + */ + stopTouchMove(event, self) { + let instance = event.instance; + let state = self.state; + let touch = event.touches[0]; + + state.deltaX = touch.clientX - state.startX; + state.deltaY = touch.clientY - state.startY; + state.offsetY = Math.abs(state.deltaY); + state.offsetX = Math.abs(state.deltaX); + state.direction = state.direction || this.getDirection(state.offsetX, state.offsetY); + } +} diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue new file mode 100644 index 0000000..a816e92 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue @@ -0,0 +1,348 @@ + + + + + + diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs new file mode 100644 index 0000000..b394244 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs @@ -0,0 +1,341 @@ +var MIN_DISTANCE = 10; + +/** + * 判断当前是否为H5、app-vue + */ +var IS_HTML5 = false +if (typeof window === 'object') IS_HTML5 = true + +/** + * 监听页面内值的变化,主要用于动态开关swipe-action + * @param {Object} newValue + * @param {Object} oldValue + * @param {Object} ownerInstance + * @param {Object} instance + */ +function showWatch(newVal, oldVal, ownerInstance, instance) { + var state = instance.getState() + getDom(instance, ownerInstance) + if (newVal && newVal !== 'none') { + openState(newVal, instance, ownerInstance) + return + } + + if (state.left) { + openState('none', instance, ownerInstance) + } + resetTouchStatus(instance) +} + +/** + * 开始触摸操作 + * @param {Object} e + * @param {Object} ins + */ +function touchstart(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState(); + getDom(instance, ownerInstance) + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + if (disabled) return + // 开始触摸时移除动画类 + instance.requestAnimationFrame(function() { + instance.removeClass('ani'); + ownerInstance.callMethod('closeSwipe'); + }) + + // 记录上次的位置 + state.x = state.left || 0 + // 计算滑动开始位置 + stopTouchStart(e, ownerInstance) +} + +/** + * 开始滑动操作 + * @param {Object} e + * @param {Object} ownerInstance + */ +function touchmove(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState() + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + if (disabled) return + // 是否可以滑动页面 + stopTouchMove(e); + if (state.direction !== 'horizontal') { + return; + } + + if (e.preventDefault) { + // 阻止页面滚动 + e.preventDefault() + } + + move(state.x + state.deltaX, instance, ownerInstance) +} + +/** + * 结束触摸操作 + * @param {Object} e + * @param {Object} ownerInstance + */ +function touchend(e, ownerInstance) { + var instance = e.instance; + var disabled = instance.getDataset().disabled + var state = instance.getState() + // fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复 + disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false; + + if (disabled) return + // 滑动过程中触摸结束,通过阙值判断是开启还是关闭 + // fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13 + moveDirection(state.left, instance, ownerInstance) + +} + +/** + * 设置移动距离 + * @param {Object} value + * @param {Object} instance + * @param {Object} ownerInstance + */ +function move(value, instance, ownerInstance) { + value = value || 0 + var state = instance.getState() + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + // 获取可滑动范围 + state.left = range(value, -rightWidth, leftWidth); + instance.requestAnimationFrame(function() { + instance.setStyle({ + transform: 'translateX(' + state.left + 'px)', + '-webkit-transform': 'translateX(' + state.left + 'px)' + }) + }) + +} + +/** + * 获取元素信息 + * @param {Object} instance + * @param {Object} ownerInstance + */ +function getDom(instance, ownerInstance) { + var state = instance.getState() + var leftDom = ownerInstance.selectComponent('.button-group--left') + var rightDom = ownerInstance.selectComponent('.button-group--right') + var leftStyles = { + width: 0 + } + var rightStyles = { + width: 0 + } + leftStyles = leftDom.getBoundingClientRect() + rightStyles = rightDom.getBoundingClientRect() + + state.leftWidth = leftStyles.width || 0 + state.rightWidth = rightStyles.width || 0 + state.threshold = instance.getDataset().threshold +} + +/** + * 获取范围 + * @param {Object} num + * @param {Object} min + * @param {Object} max + */ +function range(num, min, max) { + return Math.min(Math.max(num, min), max); +} + + +/** + * 移动方向判断 + * @param {Object} left + * @param {Object} value + * @param {Object} ownerInstance + * @param {Object} ins + */ +function moveDirection(left, ins, ownerInstance) { + var state = ins.getState() + var threshold = state.threshold + var position = state.position + var isopen = state.isopen || 'none' + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + if (state.deltaX === 0) { + openState('none', ins, ownerInstance) + return + } + if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && + rightWidth + + left < threshold)) { + // right + openState('right', ins, ownerInstance) + } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 && + leftWidth - left < threshold)) { + // left + openState('left', ins, ownerInstance) + } else { + // default + openState('none', ins, ownerInstance) + } +} + + +/** + * 开启状态 + * @param {Boolean} type + * @param {Object} ins + * @param {Object} ownerInstance + */ +function openState(type, ins, ownerInstance) { + var state = ins.getState() + var leftWidth = state.leftWidth + var rightWidth = state.rightWidth + var left = '' + state.isopen = state.isopen ? state.isopen : 'none' + switch (type) { + case "left": + left = leftWidth + break + case "right": + left = -rightWidth + break + default: + left = 0 + } + + // && !state.throttle + + if (state.isopen !== type) { + state.throttle = true + ownerInstance.callMethod('change', { + open: type + }) + + } + + state.isopen = type + // 添加动画类 + ins.requestAnimationFrame(function() { + ins.addClass('ani'); + move(left, ins, ownerInstance) + }) + // 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的 +} + + +function getDirection(x, y) { + if (x > y && x > MIN_DISTANCE) { + return 'horizontal'; + } + if (y > x && y > MIN_DISTANCE) { + return 'vertical'; + } + return ''; +} + +/** + * 重置滑动状态 + * @param {Object} event + */ +function resetTouchStatus(instance) { + var state = instance.getState(); + state.direction = ''; + state.deltaX = 0; + state.deltaY = 0; + state.offsetX = 0; + state.offsetY = 0; +} + +/** + * 设置滑动开始位置 + * @param {Object} event + */ +function stopTouchStart(event) { + var instance = event.instance; + var state = instance.getState(); + resetTouchStatus(instance); + var touch = event.touches[0]; + if (IS_HTML5 && isPC()) { + touch = event; + } + state.startX = touch.clientX; + state.startY = touch.clientY; +} + +/** + * 滑动中,是否禁止打开 + * @param {Object} event + */ +function stopTouchMove(event) { + var instance = event.instance; + var state = instance.getState(); + var touch = event.touches[0]; + if (IS_HTML5 && isPC()) { + touch = event; + } + state.deltaX = touch.clientX - state.startX; + state.deltaY = touch.clientY - state.startY; + state.offsetY = Math.abs(state.deltaY); + state.offsetX = Math.abs(state.deltaX); + state.direction = state.direction || getDirection(state.offsetX, state.offsetY); +} + +function isPC() { + var userAgentInfo = navigator.userAgent; + var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]; + var flag = true; + for (var v = 0; v < Agents.length - 1; v++) { + if (userAgentInfo.indexOf(Agents[v]) > 0) { + flag = false; + break; + } + } + return flag; +} + +var movable = false + +function mousedown(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + touchstart(e, ins) + movable = true +} + +function mousemove(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + if (!movable) return + touchmove(e, ins) +} + +function mouseup(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + touchend(e, ins) + movable = false +} + +function mouseleave(e, ins) { + if (!IS_HTML5) return + if (!isPC()) return + movable = false +} + +module.exports = { + showWatch: showWatch, + touchstart: touchstart, + touchmove: touchmove, + touchend: touchend, + mousedown: mousedown, + mousemove: mousemove, + mouseup: mouseup, + mouseleave: mouseleave +} diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue b/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue new file mode 100644 index 0000000..4971782 --- /dev/null +++ b/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/uni_modules/uni-swipe-action/package.json b/uni_modules/uni-swipe-action/package.json new file mode 100644 index 0000000..fc5dd8a --- /dev/null +++ b/uni_modules/uni-swipe-action/package.json @@ -0,0 +1,84 @@ +{ + "id": "uni-swipe-action", + "displayName": "uni-swipe-action 滑动操作", + "version": "1.3.10", + "description": "SwipeAction 滑动操作操作组件", + "keywords": [ + "", + "uni-ui", + "uniui", + "滑动删除", + "侧滑删除" + ], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "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", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-swipe-action/readme.md b/uni_modules/uni-swipe-action/readme.md new file mode 100644 index 0000000..93a5cac --- /dev/null +++ b/uni_modules/uni-swipe-action/readme.md @@ -0,0 +1,11 @@ + + +## SwipeAction 滑动操作 +> **组件名:uni-swipe-action** +> 代码块: `uSwipeAction`、`uSwipeActionItem` + + +通过滑动触发选项的容器 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swipe-action) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file