|
|
@@ -323,9 +323,9 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
<view v-if="showlongBtn" class="longView" @tap="closeLongBtn">
|
|
|
- <view class="longbtn" :style="'top:' + longBtnTop + 'px; left:' + longBtnLeft + 'px'">
|
|
|
- <view @tap="copyTextFun" v-if="showCopyBtn">复制</view>
|
|
|
- <view @tap="cancelSend">撤回</view>
|
|
|
+ <view class="longbtn" :style="'top:' + longBtnTop + 'px; left:' + longBtnLeft + 'px'" @tap.stop>
|
|
|
+ <view class="longbtn-item" @tap="copyTextFun" v-if="showCopyBtn">复制</view>
|
|
|
+ <view class="longbtn-item" @tap="cancelSend">撤回</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
<!-- 视频播放弹窗(H5) -->
|
|
|
@@ -2043,16 +2043,79 @@ export default {
|
|
|
} else {
|
|
|
showCopyBtn = true;
|
|
|
}
|
|
|
+
|
|
|
+ // 计算弹层位置:以触摸点为锚,优先显示在上方,并做边界裁剪,避免溢出屏幕
|
|
|
+ let pos = this._calcLongBtnPos(event, showCopyBtn);
|
|
|
+
|
|
|
this.setData({
|
|
|
showlongBtn: true,
|
|
|
- longBtnLeft: event.detail.x,
|
|
|
- longBtnTop: event.detail.y,
|
|
|
+ longBtnLeft: pos.left,
|
|
|
+ longBtnTop: pos.top,
|
|
|
copyText: item.consultText,
|
|
|
clickMsgID: item.msgID,
|
|
|
showCopyBtn: showCopyBtn
|
|
|
});
|
|
|
},
|
|
|
|
|
|
+ /**
|
|
|
+ * 计算长按弹层位置
|
|
|
+ * @param {Object} event 长按事件
|
|
|
+ * @param {Boolean} showCopyBtn 是否显示复制按钮(决定弹层高度)
|
|
|
+ */
|
|
|
+ _calcLongBtnPos: function (event, showCopyBtn) {
|
|
|
+ const sys = uni.getSystemInfoSync();
|
|
|
+ const vw = sys.windowWidth;
|
|
|
+ const vh = sys.windowHeight;
|
|
|
+ const ratio = vw / 750; // rpx -> px
|
|
|
+ const popupW = 140 * ratio; // .longbtn 宽度 140rpx
|
|
|
+ const items = showCopyBtn ? 2 : 1;
|
|
|
+ const popupH = items * 80 * ratio + 2; // 每项 80rpx + 分割线
|
|
|
+ const margin = 12; // 距屏幕边缘安全间距(px)
|
|
|
+
|
|
|
+ // 触摸点坐标(多源兼容:H5 原生触摸 / uni longpress detail)
|
|
|
+ let px = 0;
|
|
|
+ let py = 0;
|
|
|
+ const detail = event.detail || {};
|
|
|
+ const changed = event.changedTouches && event.changedTouches[0];
|
|
|
+ const touches = event.touches && event.touches[0];
|
|
|
+ if (changed) {
|
|
|
+ px = changed.clientX;
|
|
|
+ py = changed.clientY;
|
|
|
+ } else if (touches) {
|
|
|
+ px = touches.clientX;
|
|
|
+ py = touches.clientY;
|
|
|
+ } else if (detail.x !== undefined && detail.x !== null) {
|
|
|
+ px = detail.x;
|
|
|
+ py = detail.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 水平:以触摸点为中心,裁剪到屏幕内
|
|
|
+ let left = px - popupW / 2;
|
|
|
+ if (left < margin) {
|
|
|
+ left = margin;
|
|
|
+ }
|
|
|
+ if (left + popupW > vw - margin) {
|
|
|
+ left = vw - popupW - margin;
|
|
|
+ }
|
|
|
+ if (left < margin) {
|
|
|
+ left = margin;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 垂直:优先在触摸点上方,空间不足则下方,再裁剪到屏幕内
|
|
|
+ let top = py - popupH - 10;
|
|
|
+ if (top < margin) {
|
|
|
+ top = py + 10; // 上方空间不足,改到下方
|
|
|
+ }
|
|
|
+ if (top + popupH > vh - margin) {
|
|
|
+ top = vh - popupH - margin;
|
|
|
+ }
|
|
|
+ if (top < margin) {
|
|
|
+ top = margin;
|
|
|
+ }
|
|
|
+
|
|
|
+ return { left: left, top: top };
|
|
|
+ },
|
|
|
+
|
|
|
/**
|
|
|
* 关闭长按弹框
|
|
|
* @param {*} event
|
|
|
@@ -2072,7 +2135,8 @@ export default {
|
|
|
* @param {*} event
|
|
|
*/
|
|
|
copyTextFun: function (event) {
|
|
|
- let { copyTextFun: copyText } = this;
|
|
|
+ let copyText = this.copyText;
|
|
|
+ this.closeLongBtn();
|
|
|
uni.setClipboardData({
|
|
|
data: copyText,
|
|
|
complete: function () {},
|
|
|
@@ -2087,6 +2151,7 @@ export default {
|
|
|
if (!this.ifOnLine()) {
|
|
|
return;
|
|
|
}
|
|
|
+ this.closeLongBtn();
|
|
|
let { clickMsgID } = this;
|
|
|
const patientData = Cache.get('patientData');
|
|
|
const userData = Cache.get('userData');
|
|
|
@@ -3713,26 +3778,49 @@ page {
|
|
|
}
|
|
|
|
|
|
.longbtn {
|
|
|
- width: 120rpx;
|
|
|
- position: relative;
|
|
|
+ width: 140rpx;
|
|
|
+ position: absolute;
|
|
|
z-index: 9999;
|
|
|
- background: #fff;
|
|
|
+ background: rgba(38, 38, 42, 0.94);
|
|
|
text-align: center;
|
|
|
- border-radius: 12rpx;
|
|
|
- box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.12);
|
|
|
+ border-radius: 16rpx;
|
|
|
+ box-shadow: 0 8rpx 28rpx rgba(0, 0, 0, 0.28);
|
|
|
overflow: hidden;
|
|
|
+ transform-origin: center top;
|
|
|
+ animation: longbtn-in 0.16s ease-out both;
|
|
|
}
|
|
|
|
|
|
-.longbtn > view {
|
|
|
- height: 72rpx;
|
|
|
- line-height: 72rpx;
|
|
|
+@keyframes longbtn-in {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ transform: scale(0.9) translateY(6rpx);
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ transform: scale(1) translateY(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.longbtn-item {
|
|
|
+ height: 80rpx;
|
|
|
+ line-height: 80rpx;
|
|
|
font-size: 28rpx;
|
|
|
- color: #1f2329;
|
|
|
- border-bottom: 1rpx solid #f0f2f5;
|
|
|
+ color: #ffffff;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.longbtn-item + .longbtn-item::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 16rpx;
|
|
|
+ right: 16rpx;
|
|
|
+ height: 1rpx;
|
|
|
+ background: rgba(255, 255, 255, 0.12);
|
|
|
}
|
|
|
|
|
|
-.longbtn > view:last-child {
|
|
|
- border-bottom: none;
|
|
|
+.longbtn-item:active {
|
|
|
+ background: rgba(255, 255, 255, 0.08);
|
|
|
}
|
|
|
|
|
|
/* ============== 其它兼容 ============== */
|