Merge branch 'Branch_1' of https://git.u8t.cn/tangxinyue/alipay-emulator into Branch_1
|
|
@ -4,18 +4,19 @@
|
|||
<!-- <view class="top-placeholder" :style="{ height: data.topBoxHeight + 'px' }"></view> -->
|
||||
<view class="top-box " :style="{ top: data.statusBarHeight + 'px' }">
|
||||
<slot name="top">
|
||||
<view class="top-container" v-show="!sortMode">
|
||||
<view class="top-container" v-show="!sortMode" @click.stop="handleTitleClick">
|
||||
<view class="h100 flex-align-center flex-justify-between">
|
||||
<view class="left flex-align-center">
|
||||
<image @click="util.goBack()" :src="`/static/image/phone-message/${phone}/back.png`">
|
||||
<image @click.stop="util.goBack()" :src="`/static/image/phone-message/${phone}/back.png`">
|
||||
</image>
|
||||
<view v-if="phone == 'iphone' && number > 0" class="number-box">{{ number }}</view>
|
||||
</view>
|
||||
<view class="center">
|
||||
<image v-if="phone == 'iphone' || phone == 'huawei'" class="img shrink-0"
|
||||
:class="chatInfo.imgShape"
|
||||
:src="chatInfo.img || `/static/image/phone-message/${phone}/default.png`">
|
||||
</image>
|
||||
<text v-if="phone != 'iphone'" class="title">{{ chatInfo.title }}</text>
|
||||
<text v-if="phone != 'iphone'" class="title">{{ displayTitle }}</text>
|
||||
<text v-if="phone == 'oppo' && chatInfo.area" class="second-text">{{ chatInfo.area }}</text>
|
||||
</view>
|
||||
<view class="right flex-align-center">
|
||||
|
|
@ -37,7 +38,7 @@
|
|||
</view>
|
||||
</view>
|
||||
<view v-if="phone == 'iphone'" class="text-box flex-align-center flex-justify-center">
|
||||
<text class="title">{{ chatInfo.title }}</text>
|
||||
<text class="title">{{ displayTitle }}</text>
|
||||
<!-- <uni-icons type="right" size="10" color="#D8D8D8"></uni-icons> -->
|
||||
<image style="width: 16rpx;height: 16rpx;"
|
||||
src="/static/image/phone-message/iphone/chat-right.png"></image>
|
||||
|
|
@ -56,7 +57,8 @@
|
|||
<slot name="bottom">
|
||||
<view class="bottom-container flex-align-center" v-show="!sortMode">
|
||||
<image v-if="phone != 'huawei' && phone != 'vivo'" class="add-img shrink-0"
|
||||
:src="`/static/image/phone-message/${phone}/chat-left.png`"></image>
|
||||
:src="`/static/image/phone-message/${phone}/chat-left.png`"
|
||||
@click="phone === 'oppo' ? chooseImage() : null"></image>
|
||||
<image v-if="phone == 'huawei'" class="add-img shrink-0"
|
||||
:src="`/static/image/phone-message/huawei/emoji.png`"></image>
|
||||
<view class="search-box flex-1 flex-align-center">
|
||||
|
|
@ -66,10 +68,11 @@
|
|||
src="/static/image/phone-message/huawei/down.png"></image>
|
||||
<!-- <input class="input flex-1" :placeholder="showInfo.placeholder" v-model="content"
|
||||
@input="onInput"></input> -->
|
||||
<textarea class="input flex-1" :adjust-position="false" fixed auto-height show-confirm-bar
|
||||
<!-- <textarea class="input flex-1" :adjust-position="false" fixed auto-height show-confirm-bar
|
||||
auto-blur :placeholder="showInfo.placeholder" v-model="content" @input="onInput"
|
||||
@focus="onFocus" @blur="onBlur"></textarea>
|
||||
<!-- <editor class="input flex-1" :placeholder="showInfo.placeholder"></editor> -->
|
||||
@focus="onFocus" @blur="onBlur"></textarea> -->
|
||||
<editor id="chat-layout-editor" class="input flex-1" :placeholder="showInfo.placeholder"
|
||||
@input="onInput"></editor>
|
||||
<image v-if="phone == 'iphone' && !isSend" class="right-icon"
|
||||
src="/static/image/phone-message/iphone/mic.png"></image>
|
||||
<image v-if="phone == 'iphone' && isSend" class="right-send-icon"
|
||||
|
|
@ -100,14 +103,13 @@
|
|||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<view class="bottom-placeholder" :style="{ height: (data.bottomBoxHeight + data.keyboardHeight) + 'px' }">
|
||||
<view class="bottom-placeholder" :style="{ height: (data.bottomBoxHeight) + 'px' }">
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed, toRefs } from 'vue'
|
||||
import { onLoad, onPageScroll } from "@dcloudio/uni-app";
|
||||
import { stringUtil, dateUtil, util } from '@/utils/common.js';
|
||||
import { reactive, onMounted, computed, toRefs } from 'vue'
|
||||
import { dateUtil, util } from '@/utils/common.js';
|
||||
const props = defineProps({
|
||||
// 手机品牌
|
||||
phone: {
|
||||
|
|
@ -116,14 +118,14 @@ const props = defineProps({
|
|||
},
|
||||
chatInfo: {
|
||||
type: Object,
|
||||
default: {
|
||||
default: () => ({
|
||||
unRead: false,
|
||||
noNotice: false,
|
||||
img: "",
|
||||
title: "淘宝通知",
|
||||
content: "您关注的商品降价啦,快来抢购吧!",
|
||||
time: "2026-02-20 20:55:12"
|
||||
}
|
||||
})
|
||||
},
|
||||
// 是否处于拖拽排序模式
|
||||
sortMode: {
|
||||
|
|
@ -148,23 +150,16 @@ const data = reactive({
|
|||
lastClickTime: 0
|
||||
})
|
||||
|
||||
let { isSend, content, simIndex, scrollTop, lastClickTime } = toRefs(data)
|
||||
|
||||
const emit = defineEmits(['send', 'dblclick-left', 'dblclick-right'])
|
||||
|
||||
onMounted(() => {
|
||||
// 延迟极小时间确保 DOM 已更新循环并将滚动条拉到极限底端
|
||||
setTimeout(() => {
|
||||
data.scrollTop = 99999 + Math.random();
|
||||
}, 100);
|
||||
})
|
||||
let { isSend, content, simIndex, scrollTop } = toRefs(data)
|
||||
|
||||
const emit = defineEmits(['send', 'dblclick-left', 'dblclick-right', 'title-click'])
|
||||
const onInput = (e) => {
|
||||
content.value = e.detail.value
|
||||
if (content.value.length > 0) {
|
||||
isSend.value = true
|
||||
} else {
|
||||
content.value = e.detail.html
|
||||
const htmlStr = (content.value || '').trim()
|
||||
if (htmlStr === '' || htmlStr === '<p><br></p>' || htmlStr === '<br>') {
|
||||
isSend.value = false
|
||||
} else {
|
||||
isSend.value = true
|
||||
}
|
||||
setTimeout(() => {
|
||||
uni.createSelectorQuery().select('.bottom-box').boundingClientRect(rect => {
|
||||
|
|
@ -175,19 +170,7 @@ const onInput = (e) => {
|
|||
}, 50);
|
||||
}
|
||||
|
||||
const onFocus = (e) => {
|
||||
if (e.detail.height) {
|
||||
data.keyboardHeight = e.detail.height;
|
||||
// 键盘弹起时,也需要滚动到底部
|
||||
setTimeout(() => {
|
||||
data.scrollTop = 99999 + Math.random();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
const onBlur = () => {
|
||||
data.keyboardHeight = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换sim卡
|
||||
|
|
@ -212,6 +195,14 @@ const sendMessage = () => {
|
|||
data.content = ""
|
||||
data.isSend = false
|
||||
|
||||
// 清空 editor 中输入的值
|
||||
uni.createSelectorQuery().select('#chat-layout-editor').context((res) => {
|
||||
if (res && res.context) {
|
||||
res.context.clear()
|
||||
}
|
||||
data.isSend = false
|
||||
}).exec()
|
||||
|
||||
// 延迟极小时间确保 DOM 已更新循环并将滚动条拉到极限底端
|
||||
setTimeout(() => {
|
||||
data.scrollTop = 99999 + Math.random();
|
||||
|
|
@ -220,7 +211,9 @@ const sendMessage = () => {
|
|||
data.bottomBoxHeight = rect.height;
|
||||
}
|
||||
}).exec();
|
||||
data.isSend = false
|
||||
}, 100);
|
||||
data.isSend = false
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -255,6 +248,23 @@ const handleBoxClick = (e) => {
|
|||
}
|
||||
|
||||
|
||||
const handleTitleClick = () => {
|
||||
emit('title-click');
|
||||
}
|
||||
|
||||
|
||||
// 处理标题显示
|
||||
const displayTitle = computed(() => {
|
||||
let title = props.chatInfo.title || '';
|
||||
if (props.phone === 'oppo') {
|
||||
const noSpace = title.replace(/\s+/g, '');
|
||||
if (/^\d{11}$/.test(noSpace)) {
|
||||
return noSpace.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3');
|
||||
}
|
||||
}
|
||||
return title;
|
||||
})
|
||||
|
||||
// 展示文字信息
|
||||
const showInfo = computed(() => {
|
||||
let placeholder
|
||||
|
|
@ -280,6 +290,84 @@ const showInfo = computed(() => {
|
|||
return { placeholder }
|
||||
})
|
||||
|
||||
/**
|
||||
* 选择图片并发送
|
||||
*/
|
||||
const chooseImage = () => {
|
||||
uni.chooseImage({
|
||||
count: 1, // 仅选一张
|
||||
sizeType: ['original', 'compressed'], // 原图或压缩图
|
||||
sourceType: ['album', 'camera'], // 从相册选择或拍照
|
||||
success: (res) => {
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
if (tempFilePaths.length > 0) {
|
||||
const tempPath = tempFilePaths[0];
|
||||
|
||||
const processImage = (finalPath) => {
|
||||
// 获取图片信息,计算横竖向及相应宽高
|
||||
uni.getImageInfo({
|
||||
src: finalPath,
|
||||
success: (image) => {
|
||||
let w = image.width;
|
||||
let h = image.height;
|
||||
|
||||
// 根据 EXIF 方向修正实际视觉宽高
|
||||
if (image.orientation && ['left', 'right', 'left-mirrored', 'right-mirrored'].includes(image.orientation)) {
|
||||
w = image.height;
|
||||
h = image.width;
|
||||
}
|
||||
|
||||
const isHorizontal = w >= h;
|
||||
const width = isHorizontal ? '368rpx' : '274rpx';
|
||||
const height = isHorizontal ? '274rpx' : '368rpx';
|
||||
|
||||
const date = dateUtil.now("YYYY-MM-DD HH:mm")
|
||||
// 封装成HTML的img标签作为消息内容
|
||||
const content = `<img src="${finalPath}" style="width: ${width}; height: ${height}; border-radius: 16rpx; display: block;" />`;
|
||||
const params = {
|
||||
content: content,
|
||||
imgUrl: finalPath,
|
||||
type: 'image',
|
||||
imgWidth: width,
|
||||
imgHeight: height,
|
||||
simIndex: simIndex.value,
|
||||
time: date,
|
||||
isMe: true
|
||||
}
|
||||
emit('send', params)
|
||||
|
||||
// 延迟拉动到底部
|
||||
setTimeout(() => {
|
||||
data.scrollTop = 99999 + Math.random();
|
||||
uni.createSelectorQuery().select('.bottom-box').boundingClientRect(rect => {
|
||||
if (rect) {
|
||||
data.bottomBoxHeight = rect.height;
|
||||
}
|
||||
}).exec();
|
||||
}, 100);
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
uni.saveFile({
|
||||
tempFilePath: tempPath,
|
||||
success: (saveRes) => {
|
||||
processImage(saveRes.savedFilePath);
|
||||
},
|
||||
fail: () => {
|
||||
processImage(tempPath);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
processImage(tempPath);
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 同步获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
|
|
@ -299,6 +387,16 @@ onMounted(() => {
|
|||
}).exec();
|
||||
}, 50);
|
||||
|
||||
// 延迟极小时间确保 DOM 已更新循环并将滚动条拉到极限底端
|
||||
setTimeout(() => {
|
||||
data.scrollTop = 99999 + Math.random();
|
||||
uni.createSelectorQuery().select('.bottom-box').boundingClientRect(rect => {
|
||||
if (rect) {
|
||||
data.bottomBoxHeight = rect.height;
|
||||
}
|
||||
}).exec();
|
||||
}, 300);
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
|
@ -325,7 +423,7 @@ onMounted(() => {
|
|||
.center-box {
|
||||
overflow: hidden;
|
||||
// overflow-y: scroll;
|
||||
padding-bottom: 12px;
|
||||
// padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.fixed-bottom-box {
|
||||
|
|
@ -347,6 +445,13 @@ onMounted(() => {
|
|||
|
||||
//苹果样式
|
||||
.iphone-style {
|
||||
.circle {
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
|
||||
.square {
|
||||
border-radius: 16rpx !important;
|
||||
}
|
||||
|
||||
.status-placeholder {
|
||||
background-color: #F7F7F7;
|
||||
|
|
@ -411,7 +516,6 @@ onMounted(() => {
|
|||
left: 20rpx;
|
||||
margin-right: 6rpx;
|
||||
font-weight: 500;
|
||||
line-height: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -628,11 +732,25 @@ onMounted(() => {
|
|||
|
||||
.top-box {
|
||||
|
||||
.top-container::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #D0D1D3;
|
||||
transform: scaleY(0.3);
|
||||
}
|
||||
|
||||
.top-container {
|
||||
position: relative;
|
||||
padding: 0 52rpx;
|
||||
background-color: #F0F1F3;
|
||||
height: 88rpx;
|
||||
box-shadow: inset 0 -0.3px 0 0 #D0D1D3;
|
||||
height: 98rpx;
|
||||
padding-top: 6rpx;
|
||||
padding-bottom: 12rpx;
|
||||
|
||||
.left {
|
||||
|
||||
|
|
@ -752,6 +870,7 @@ onMounted(() => {
|
|||
max-height: 160rpx;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
caret-color: #1ABA11;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
|
|
@ -821,7 +940,7 @@ onMounted(() => {
|
|||
font-size: 40rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
line-height: 36rpx;
|
||||
line-height: 40rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
|
@ -1057,4 +1176,9 @@ onMounted(() => {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
.bottom-placeholder {
|
||||
margin-top: env(safe-area-inset-bottom);
|
||||
margin-top: constant(safe-area-inset-bottom);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
}">
|
||||
|
||||
<!-- 排序模式下的拖拽手柄 -->
|
||||
<view v-if="sortMode" class="sort-handle-wrap" @longpress="onSortLongPress(index, $event)"
|
||||
@touchmove.stop.prevent="onSortTouchMove(index, $event)" @touchend.stop="onSortTouchEnd(index, $event)">
|
||||
<view v-if="sortMode" class="sort-handle-wrap" @longpress="onSortLongPress(index)"
|
||||
@touchmove.stop.prevent="onSortTouchMove($event)" @touchend.stop="onSortTouchEnd()">
|
||||
<view class="sort-handle-bar"></view>
|
||||
<view class="sort-handle-bar"></view>
|
||||
<view class="sort-handle-bar"></view>
|
||||
|
|
@ -34,13 +34,15 @@
|
|||
</image>
|
||||
</view>
|
||||
<view class="chat-box" :id="'msg-' + index" :class="{
|
||||
'tail-right': shouldApplyTailRight(index),
|
||||
'tail-left': shouldApplyTailLeft(index),
|
||||
'tail-right': shouldApplyTailRight(index) && !isImageMsg(message),
|
||||
'tail-left': shouldApplyTailLeft(index) && !isImageMsg(message),
|
||||
'delivered': isLastMeMessage(index)
|
||||
}" @longpress="!sortMode && onMessageLongPress(index, message)">
|
||||
<text v-if="message.isMe && phone == 'mi'" class="send-text">送达</text>
|
||||
<view class="chat-bubble">
|
||||
<view v-html="formatMessageContent(message.content, message.isMe)"></view>
|
||||
<view class="chat-bubble" :class="{ 'image-bubble': isImageMsg(message) }">
|
||||
<image v-if="isImageMsg(message)" :src="getImageSrc(message)" mode="aspectFill"
|
||||
class="chat-image" :style="getImageStyle(message)"></image>
|
||||
<rich-text v-else :nodes="formatMessageContent(message.content, message.isMe)"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="phone == 'huawei'" class="second-info">
|
||||
|
|
@ -56,9 +58,8 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed, watch, nextTick } from 'vue'
|
||||
import { onLoad, onPageScroll } from "@dcloudio/uni-app";
|
||||
import { stringUtil, util } from '@/utils/common.js';
|
||||
import { ref, onMounted, computed, watch, nextTick } from 'vue'
|
||||
import { util } from '@/utils/common.js';
|
||||
const props = defineProps({
|
||||
// 手机品牌
|
||||
phone: {
|
||||
|
|
@ -67,7 +68,7 @@ const props = defineProps({
|
|||
},
|
||||
messageList: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: () => []
|
||||
},
|
||||
// 是否处于拖拽排序模式
|
||||
sortMode: {
|
||||
|
|
@ -105,7 +106,11 @@ let sortItemRects = []
|
|||
// 当 sortMode 切换时同步本地副本
|
||||
watch(() => props.sortMode, (val) => {
|
||||
if (val) {
|
||||
localSortList.value = props.messageList.map(item => ({ ...item }))
|
||||
let list = props.messageList;
|
||||
if (props.phone !== 'oppo') {
|
||||
list = list.filter(msg => !isImageMsg(msg));
|
||||
}
|
||||
localSortList.value = list.map(item => ({ ...item }))
|
||||
} else {
|
||||
dragIndex.value = -1
|
||||
dragOverIndex.value = -1
|
||||
|
|
@ -115,10 +120,15 @@ watch(() => props.sortMode, (val) => {
|
|||
}
|
||||
})
|
||||
|
||||
// 实际渲染用的列表:排序模式下用内部副本,否则用原始列表
|
||||
// 实际渲染用的列表:排序模式下用内部副本,否则用原始列表(非 oppo 机型过滤图片)
|
||||
const displayList = computed(() => {
|
||||
if (props.sortMode) return localSortList.value
|
||||
return props.messageList
|
||||
|
||||
let list = props.messageList;
|
||||
if (props.phone !== 'oppo') {
|
||||
list = list.filter(msg => !isImageMsg(msg));
|
||||
}
|
||||
return list;
|
||||
})
|
||||
|
||||
// 判断消息isMe==true时上一条消息是否也是isMe==true,如果不是则应用m-t-16样式
|
||||
|
|
@ -132,18 +142,7 @@ const shouldApplyMt16 = (index) => {
|
|||
return false;
|
||||
}
|
||||
|
||||
// 判断消息isMe==true时下一条消息是否也是isMe==true,如果不是则应用m-t-16样式
|
||||
const shouldApplyNextIsMe = (index) => {
|
||||
const currentMsg = displayList.value[index];
|
||||
// 拦截:如果已经是数组的最后一条消息,必然不存在下一条消息
|
||||
if (index >= displayList.value.length - 1) return false;
|
||||
|
||||
const nextMsg = displayList.value[index + 1];
|
||||
if (currentMsg.isMe && nextMsg.isMe) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断是否为最后一条自己发出的消息
|
||||
const isLastMeMessage = (currentIndex) => {
|
||||
|
|
@ -335,11 +334,45 @@ const formatMessageContent = (content, isMe) => {
|
|||
let color = '#3A85F8'
|
||||
if (props.phone == 'iphone') color = '#0B7AE3'
|
||||
if (props.phone == 'mi') color = '#3A85F8'
|
||||
if (props.phone == 'oppo') color = '#03A311'
|
||||
const colorStyle = !isMe ? `color: ${color};` : '';
|
||||
return `<span style="text-decoration: underline; ${colorStyle}">${match}</span>`;
|
||||
});
|
||||
}
|
||||
|
||||
// 判断该消息是否为纯图片消息
|
||||
const isImageMsg = (message) => {
|
||||
if (message.type === 'image') return true;
|
||||
if (message.content && typeof message.content === 'string') {
|
||||
const str = message.content.trim();
|
||||
// 如果是以 <img 开头且没有其他多余文本
|
||||
if (str.startsWith('<img') && str.endsWith('/>') && str.indexOf('<img') === str.lastIndexOf('<img')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 提取图片 src
|
||||
const getImageSrc = (message) => {
|
||||
if (message.imgUrl) return message.imgUrl;
|
||||
if (message.content && typeof message.content === 'string') {
|
||||
const match = message.content.match(/src="([^"]+)"/);
|
||||
if (match && match[1]) return match[1];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// 提取并应用图片的特定宽高
|
||||
const getImageStyle = (message) => {
|
||||
if (message.imgWidth && message.imgHeight) {
|
||||
return {
|
||||
width: message.imgWidth,
|
||||
height: message.imgHeight
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* 长按信息
|
||||
|
|
@ -373,7 +406,7 @@ const refreshSortRects = (callback) => {
|
|||
/**
|
||||
* 长按手柄开始拖拽
|
||||
*/
|
||||
const onSortLongPress = (idx, e) => {
|
||||
const onSortLongPress = (idx) => {
|
||||
dragIndex.value = idx
|
||||
dragOverIndex.value = idx
|
||||
isDragging = true
|
||||
|
|
@ -386,7 +419,7 @@ const onSortLongPress = (idx, e) => {
|
|||
/**
|
||||
* 拖拽移动 - 根据触摸点 Y 坐标確定悬停位置和插入方向
|
||||
*/
|
||||
const onSortTouchMove = (idx, e) => {
|
||||
const onSortTouchMove = (e) => {
|
||||
if (!isDragging || dragIndex.value === -1) return
|
||||
if (!e.touches || !e.touches[0]) return
|
||||
const touchY = e.touches[0].clientY
|
||||
|
|
@ -408,7 +441,7 @@ const onSortTouchMove = (idx, e) => {
|
|||
/**
|
||||
* 拖拽结束 - 根据 dropPosition 決定插入到目标的上方还是下方
|
||||
*/
|
||||
const onSortTouchEnd = (idx, e) => {
|
||||
const onSortTouchEnd = () => {
|
||||
if (!isDragging) return
|
||||
const from = dragIndex.value
|
||||
const to = dragOverIndex.value
|
||||
|
|
@ -483,6 +516,21 @@ const onSortTouchEnd = (idx, e) => {
|
|||
padding-bottom: 4rpx;
|
||||
}
|
||||
|
||||
/* 纯图片消息覆盖样式 */
|
||||
.chat-bubble.image-bubble {
|
||||
background-color: transparent !important;
|
||||
padding: 0 !important;
|
||||
border: none !important;
|
||||
border-radius: 16rpx !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-image {
|
||||
max-width: 400rpx;
|
||||
border-radius: 16rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
// 苹果样式
|
||||
.iphone-style {
|
||||
.m-t-16 {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<view :style="`${phone}-style`">
|
||||
<uni-swipe-action class="swipe-action">
|
||||
<!-- 使用插槽 (请自行给定插槽内容宽度)-->
|
||||
<uni-swipe-action-item class="swipe-action-item" v-for="(item, index) in list" :key="item.id">
|
||||
<uni-swipe-action-item class="swipe-action-item" v-for="item in list" :key="item.id">
|
||||
<view class="flex flex-align-center " @click="clickItem(item)">
|
||||
|
||||
<view class="item flex w100">
|
||||
|
|
@ -19,13 +19,19 @@
|
|||
<view class="border-box m-l-24 flex-1 flex flex-align-start">
|
||||
<view class="main-box flex-1">
|
||||
<view class="title-box flex-between">
|
||||
<text class="title">{{ item.title }}</text>
|
||||
<text class="time">{{ formatDate(item.chatList?.[item.chatList?.length -
|
||||
1]?.time || item.time)
|
||||
<text class="title">{{ displayTitle(item.title) }}</text>
|
||||
<text class="time">{{ formatDate(getLastMessage(item.chatList)?.time || item.time)
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="content"
|
||||
v-html="item.chatList?.[item.chatList?.length - 1]?.content || ''"></view>
|
||||
<view class="content">
|
||||
<view v-if="isImageMsg(getLastMessage(item.chatList))"
|
||||
class="flex flex-align-center">
|
||||
<image style="width: 24rpx;height: 24rpx;margin-right: 16rpx;"
|
||||
src="/static/image/phone-message/oppo/link.png"></image>
|
||||
<text>[图片]</text>
|
||||
</view>
|
||||
<rich-text v-else :nodes="getLastMessage(item.chatList)?.content || ''"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box-right h100 flex-column flex-align-center">
|
||||
<image v-if="phone == 'iphone'" src="/static/image/phone-message/iphone/right.png">
|
||||
|
|
@ -56,18 +62,8 @@
|
|||
</uni-swipe-action>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import { stringUtil } from '@/utils/common.js';
|
||||
|
||||
</script>
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
computed
|
||||
} from 'vue'
|
||||
import {
|
||||
util,
|
||||
dateUtil
|
||||
} from '@/utils/common.js';
|
||||
// 定义事件
|
||||
|
|
@ -107,6 +103,52 @@ const formatDate = (date) => {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化联系人名称,处理 OPPO 纯数字11位手机号显示
|
||||
*/
|
||||
const displayTitle = (title) => {
|
||||
let t = title || '';
|
||||
if (props.phone === 'oppo') {
|
||||
const noSpace = t.replace(/\s+/g, '');
|
||||
if (/^\d{11}$/.test(noSpace)) {
|
||||
return noSpace.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3');
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断该消息是否为图片消息
|
||||
*/
|
||||
const isImageMsg = (message) => {
|
||||
if (!message) return false;
|
||||
if (message.type === 'image') return true;
|
||||
if (message.content && typeof message.content === 'string') {
|
||||
const str = message.content.trim();
|
||||
if (str.startsWith('<img') && str.endsWith('/>') && str.indexOf('<img') === str.lastIndexOf('<img')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新一条有效消息(非 oppo 屏蔽图片消息)
|
||||
*/
|
||||
const getLastMessage = (chatList) => {
|
||||
if (!chatList || chatList.length === 0) return null;
|
||||
if (props.phone === 'oppo') {
|
||||
return chatList[chatList.length - 1];
|
||||
}
|
||||
// 非 oppo 机型,倒序查找最后一条非图片消息
|
||||
for (let i = chatList.length - 1; i >= 0; i--) {
|
||||
if (!isImageMsg(chatList[i])) {
|
||||
return chatList[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击列表元素
|
||||
*/
|
||||
|
|
@ -449,11 +491,24 @@ const editItem = (item) => {
|
|||
|
||||
.border-box {
|
||||
position: relative;
|
||||
padding: 4rpx 34rpx 28rpx 0;
|
||||
padding: 4rpx 0 28rpx 0;
|
||||
margin-left: 32rpx;
|
||||
margin-right: 34rpx;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.border-box::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #E2E2E2;
|
||||
transform: scaleY(0.3);
|
||||
}
|
||||
|
||||
.main-box {
|
||||
.title-box {
|
||||
margin-bottom: 16rpx;
|
||||
|
|
|
|||
33
pages.json
|
|
@ -38,7 +38,10 @@
|
|||
"path": "chat-page/chat-page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "短信聊天页面",
|
||||
"navigationStyle": "custom"
|
||||
"navigationStyle": "custom",
|
||||
"app-plus": {
|
||||
"softinputMode": "adjustResize"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -116,10 +119,23 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"path" : "taobao/add-shangou-order/add-shangou-order",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "添加淘宝闪购订单详情",
|
||||
"path": "taobao/add-shangou-order/add-shangou-order",
|
||||
"style": {
|
||||
"navigationBarTitleText": "添加淘宝闪购订单详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pdd/list-index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "拼多多购物列表",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pdd/order-detail/order-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "拼多多订单详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
|
|
@ -352,10 +368,9 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"path" : "about-this-iphone/about-this-iphone",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "苹果关于本机",
|
||||
"path": "about-this-iphone/about-this-iphone",
|
||||
"style": {
|
||||
"navigationBarTitleText": "苹果关于本机",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,97 +8,96 @@
|
|||
</view>
|
||||
<view :class="`${data.phone}-style`">
|
||||
<ChatLayout :phone="data.phone" :chatInfo="data.data" :sortMode="isSortMode" @send="handleSend"
|
||||
:number="data.number" @dblclick-left="onDblclickLeft" @dblclick-right="onDblclickRight">
|
||||
<!-- 弹出操作层及遮罩 -->
|
||||
<view v-if="showActionPopup" class="action-mask" @tap="closeActionPopup">
|
||||
<view class="action-popup" :style="{ top: popupTop + 'px', left: popupLeft + 'px' }">
|
||||
<view class="action-item" @tap.stop="handleEdit">
|
||||
<image class="action-icon" src="/static/image/phone-message/bianji.png"></image>
|
||||
<text>编辑</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleSwap">
|
||||
<image class="action-icon" src="/static/image/phone-message/huhuan.png"></image>
|
||||
<text>消息互换</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleSort">
|
||||
<image class="action-icon" src="/static/image/phone-message/sort.png"></image>
|
||||
<text>排序</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleChangeSpeaker">
|
||||
<image class="action-icon" src="/static/image/phone-message/change.png"></image>
|
||||
<text>切换发言人</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleDelete">
|
||||
<image class="action-icon" src="/static/image/phone-message/shanchu.png"></image>
|
||||
<text>删除</text>
|
||||
</view>
|
||||
<!-- 向上指的三角形,因为要求在长按元素下方 -->
|
||||
<view class="triangle"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 编辑消息弹窗 -->
|
||||
<view v-if="showEditPopup" class="edit-mask" @tap="closeEditPopup">
|
||||
<view class="edit-popup" @tap.stop>
|
||||
<view class="edit-header">编辑消息</view>
|
||||
<view class="edit-body">
|
||||
<view class="edit-row">
|
||||
<text class="edit-label">时间:</text>
|
||||
<view class="time-picker-group">
|
||||
<picker mode="date" :fields="$system == 'Android' ? 'day' : ''" :value="editingDate"
|
||||
@change="onDateChange">
|
||||
<view class="time-picker-item">
|
||||
<text>{{ editingDate || '选择日期' }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
<picker mode="time" :fields="$system == 'Android' ? 'minute' : ''"
|
||||
:value="editingTimeOfDay" @change="onTimeOfDayChange">
|
||||
<view class="time-picker-item">
|
||||
<text>{{ editingTimeOfDay || '选择时刻' }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="edit-row" style="align-items: flex-start;">
|
||||
<text class="edit-label" style="padding-top: 6rpx;">时间显示:</text>
|
||||
<view class="time-mode-group">
|
||||
<view class="time-mode-btn" :class="{ active: editingTimeMode === 'auto' }"
|
||||
@tap="editingTimeMode = 'auto'">自动</view>
|
||||
<view class="time-mode-btn" :class="{ active: editingTimeMode === 'show' }"
|
||||
@tap="editingTimeMode = 'show'">强制显示</view>
|
||||
<view class="time-mode-btn" :class="{ active: editingTimeMode === 'hide' }"
|
||||
@tap="editingTimeMode = 'hide'">强制隐藏</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="edit-row"
|
||||
v-if="data.phone == 'huawei' || data.phone == 'oppo' || data.phone == 'vivo'">
|
||||
<text class="edit-label">SIM卡:</text>
|
||||
<view class="edit-input"
|
||||
style="padding: 0; background: transparent; display: flex; align-items: center; border-radius: 8rpx; height: 70rpx;">
|
||||
<uni-data-select v-model="editingSimKa" :localdata="simList" :clear="false"
|
||||
placeholder="请选择卡号" @change="onSimKaChange"
|
||||
style="flex: 1; border: none !important; width: 100%;"></uni-data-select>
|
||||
</view>
|
||||
</view>
|
||||
<view class="edit-row">
|
||||
<text class="edit-label">内容:</text>
|
||||
</view>
|
||||
<editor id="editor" class="edit-textarea" placeholder="请输入消息内容..." @ready="onEditorReady">
|
||||
</editor>
|
||||
</view>
|
||||
<view class="edit-footer">
|
||||
<view class="edit-btn cancel" @tap="closeEditPopup">取消</view>
|
||||
<view class="edit-btn confirm" @tap="confirmEdit">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
:number="data.number" @dblclick-left="onDblclickLeft" @dblclick-right="onDblclickRight"
|
||||
@title-click="handleTitleClick">
|
||||
<ChatList :messageList="messageList" :phone="data.phone" :sortMode="isSortMode"
|
||||
@onLongPress="onMessageLongPress" @sort="onSortChange"></ChatList>
|
||||
|
||||
|
||||
</ChatLayout>
|
||||
|
||||
<!-- 弹出操作层及遮罩 -->
|
||||
<view v-if="showActionPopup" class="action-mask" @tap="closeActionPopup">
|
||||
<view class="action-popup" :style="{ top: popupTop + 'px', left: popupLeft + 'px' }">
|
||||
<view class="action-item" @tap.stop="handleEdit">
|
||||
<image class="action-icon" src="/static/image/phone-message/bianji.png"></image>
|
||||
<text>编辑</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleSwap">
|
||||
<image class="action-icon" src="/static/image/phone-message/huhuan.png"></image>
|
||||
<text>消息互换</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleSort">
|
||||
<image class="action-icon" src="/static/image/phone-message/sort.png"></image>
|
||||
<text>排序</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleChangeSpeaker">
|
||||
<image class="action-icon" src="/static/image/phone-message/change.png"></image>
|
||||
<text>切换发言人</text>
|
||||
</view>
|
||||
<view class="action-item" @tap.stop="handleDelete">
|
||||
<image class="action-icon" src="/static/image/phone-message/shanchu.png"></image>
|
||||
<text>删除</text>
|
||||
</view>
|
||||
<!-- 向上指的三角形,因为要求在长按元素下方 -->
|
||||
<view class="triangle"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 编辑消息弹窗 -->
|
||||
<view v-if="showEditPopup" class="edit-mask" @tap="closeEditPopup">
|
||||
<view class="edit-popup" @tap.stop>
|
||||
<view class="edit-header">编辑消息</view>
|
||||
<view class="edit-body">
|
||||
<view class="edit-row">
|
||||
<text class="edit-label">时间:</text>
|
||||
<view class="time-picker-group">
|
||||
<picker mode="date" :fields="$system == 'Android' ? 'day' : ''" :value="editingDate"
|
||||
@change="onDateChange">
|
||||
<view class="time-picker-item">
|
||||
<text>{{ editingDate || '选择日期' }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
<picker mode="time" :fields="$system == 'Android' ? 'minute' : ''" :value="editingTimeOfDay"
|
||||
@change="onTimeOfDayChange">
|
||||
<view class="time-picker-item">
|
||||
<text>{{ editingTimeOfDay || '选择时刻' }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="edit-row" style="align-items: flex-start;">
|
||||
<text class="edit-label" style="padding-top: 6rpx;">时间显示:</text>
|
||||
<view class="time-mode-group">
|
||||
<view class="time-mode-btn" :class="{ active: editingTimeMode === 'auto' }"
|
||||
@tap="editingTimeMode = 'auto'">自动</view>
|
||||
<view class="time-mode-btn" :class="{ active: editingTimeMode === 'show' }"
|
||||
@tap="editingTimeMode = 'show'">强制显示</view>
|
||||
<view class="time-mode-btn" :class="{ active: editingTimeMode === 'hide' }"
|
||||
@tap="editingTimeMode = 'hide'">强制隐藏</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="edit-row"
|
||||
v-if="data.phone == 'huawei' || data.phone == 'oppo' || data.phone == 'vivo'">
|
||||
<text class="edit-label">SIM卡:</text>
|
||||
<view class="edit-input"
|
||||
style="padding: 0; background: transparent; display: flex; align-items: center; border-radius: 8rpx; height: 70rpx;">
|
||||
<uni-data-select v-model="editingSimKa" :localdata="simList" :clear="false"
|
||||
placeholder="请选择卡号" @change="onSimKaChange"
|
||||
style="flex: 1; border: none !important; width: 100%;"></uni-data-select>
|
||||
</view>
|
||||
</view>
|
||||
<view class="edit-row">
|
||||
<text class="edit-label">内容:</text>
|
||||
</view>
|
||||
<editor id="editor" class="edit-textarea" placeholder="请输入消息内容..." @ready="onEditorReady">
|
||||
</editor>
|
||||
</view>
|
||||
<view class="edit-footer">
|
||||
<view class="edit-btn cancel" @tap="closeEditPopup">取消</view>
|
||||
<view class="edit-btn confirm" @tap="confirmEdit">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 排序模式底部工具条 -->
|
||||
<view v-if="isSortMode" class="sort-toolbar">
|
||||
<view class="sort-toolbar-tip">长按消息并拖动调整顺序</view>
|
||||
|
|
@ -107,6 +106,61 @@
|
|||
<view class="sort-toolbar-btn confirm" @tap="confirmSort">完成</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 修改当前短信信息弹窗 -->
|
||||
<view v-if="showAddPopup" class="add-mask" @tap="closeAddPopup">
|
||||
<view class="add-popup" @tap.stop>
|
||||
<view class="add-header">编辑当前短信信息</view>
|
||||
<view class="add-body">
|
||||
<view class="add-row">
|
||||
<text class="add-label">头像URL:</text>
|
||||
<view style="position: relative;">
|
||||
<view class="image-box" :class="addForm.imgShape" style="width: 84rpx;height: 84rpx;"
|
||||
@tap="selectImage">
|
||||
<image v-if="addForm.img" class="image w100 h100" :src="addForm.img" mode="aspectFill">
|
||||
</image>
|
||||
<image v-else class="image w100 h100" src="/static/image/phone-message/add.png"
|
||||
mode="aspectFill">
|
||||
</image>
|
||||
</view>
|
||||
<view v-if="addForm.img" class="delete-img-icon" @tap.stop="deleteImage">
|
||||
×
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="data.phone == 'iphone'"
|
||||
style="flex: 1;display: flex;align-items: center;justify-content: flex-end;">
|
||||
<uni-data-checkbox style="display: flex;justify-content: flex-end;"
|
||||
v-model="addForm.imgShape" :localdata="shape"></uni-data-checkbox>
|
||||
</view>
|
||||
</view>
|
||||
<view class="add-row">
|
||||
<text class="add-label required">联系人</text>
|
||||
<input class="add-input" v-model="addForm.title" placeholder="请输入名称或号码" />
|
||||
</view>
|
||||
<view class="add-row" v-if="data.phone == 'oppo'">
|
||||
<text class="add-label">地区</text>
|
||||
<input class="add-input" v-model="addForm.area" placeholder="请输入地区" />
|
||||
</view>
|
||||
<view class="add-row between" v-if="data.phone == 'iphone'">
|
||||
<text class="add-label">取消通知</text>
|
||||
<switch :checked="addForm.noNotice" @change="addForm.noNotice = !addForm.noNotice" />
|
||||
</view>
|
||||
<view class="add-row between">
|
||||
<text class="add-label">是否未读</text>
|
||||
<switch :checked="addForm.unRead" @change="addForm.unRead = !addForm.unRead" />
|
||||
</view>
|
||||
<view class="add-row"
|
||||
v-if="addForm.unRead && (data.phone == 'oppo' || data.phone == 'huawei' || data.phone == 'iphone')">
|
||||
<text class="add-label">未读数量</text>
|
||||
<input class="add-input" type="number" v-model="addForm.unReadNumber" placeholder="请输入未读数量" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="add-footer">
|
||||
<view class="add-btn cancel" @tap="closeAddPopup">取消</view>
|
||||
<view class="add-btn confirm" @tap="confirmAdd">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
@ -378,6 +432,19 @@ const handleChangeSpeaker = () => {
|
|||
*/
|
||||
const handleDelete = () => {
|
||||
const index = messageList.value.findIndex(item => item.id === selectedMessage.value.id)
|
||||
const deletedMsg = messageList.value[index]
|
||||
|
||||
// 如果是图片消息且存在本地持久化路径,则执行删除物理文件
|
||||
// #ifdef APP-PLUS
|
||||
if (deletedMsg && deletedMsg.type === 'image' && deletedMsg.imgUrl && deletedMsg.imgUrl.includes('_doc/')) {
|
||||
uni.removeSavedFile({
|
||||
filePath: deletedMsg.imgUrl,
|
||||
success: () => console.log('单条图片消息本地文件删除成功:', deletedMsg.imgUrl),
|
||||
fail: (err) => console.warn('单条图片消息本地文件删除失败:', deletedMsg.imgUrl, err)
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
messageList.value.splice(index, 1)
|
||||
closeActionPopup();
|
||||
saveChatList()
|
||||
|
|
@ -440,6 +507,7 @@ onShow(() => {
|
|||
// #endif
|
||||
})
|
||||
|
||||
|
||||
const handleSend = (params) => {
|
||||
console.log(params)
|
||||
params.id = stringUtil.uuid()
|
||||
|
|
@ -469,6 +537,99 @@ const onDblclickRight = () => {
|
|||
icon: "none"
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const showAddPopup = ref(false)
|
||||
const addForm = reactive({
|
||||
title: '',
|
||||
img: '',
|
||||
imgShape: 'circle',
|
||||
area: '',
|
||||
unRead: false,
|
||||
unReadNumber: 1,
|
||||
noNotice: false
|
||||
})
|
||||
const shape = [{ text: '圆形', value: 'circle' }, { text: '方形', value: 'square' }]
|
||||
|
||||
const handleTitleClick = () => {
|
||||
const item = data.data
|
||||
addForm.title = item.title || ''
|
||||
addForm.img = item.img || ''
|
||||
addForm.imgShape = item.imgShape || 'circle'
|
||||
addForm.area = item.area || ''
|
||||
addForm.unRead = !!item.unRead
|
||||
addForm.unReadNumber = item.unReadNumber || 0
|
||||
addForm.noNotice = item.noNotice || false
|
||||
showAddPopup.value = true
|
||||
}
|
||||
|
||||
const closeAddPopup = () => {
|
||||
showAddPopup.value = false
|
||||
}
|
||||
|
||||
const selectImage = () => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
addForm.img = res.tempFilePaths[0]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const deleteImage = () => {
|
||||
addForm.img = ''
|
||||
}
|
||||
|
||||
const confirmAdd = async () => {
|
||||
if (!addForm.title.trim()) {
|
||||
uni.showToast({ title: '请输入联系人名称', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
let finalImgPath = addForm.img
|
||||
if (addForm.img && !addForm.img.startsWith('_doc') && !addForm.img.startsWith('/static')) {
|
||||
try {
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
uni.saveFile({
|
||||
tempFilePath: addForm.img,
|
||||
success: resolve,
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
finalImgPath = res.savedFilePath
|
||||
} catch (e) {
|
||||
console.error('保存图片失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
data.data.title = addForm.title.trim()
|
||||
data.data.img = finalImgPath
|
||||
data.data.unRead = addForm.unRead
|
||||
data.data.unReadNumber = addForm.unReadNumber
|
||||
data.data.noNotice = addForm.noNotice
|
||||
data.data.imgShape = addForm.imgShape
|
||||
data.data.area = addForm.area
|
||||
|
||||
try {
|
||||
const cached = uni.getStorageSync(STORAGE_KEY)
|
||||
let list = cached ? JSON.parse(cached) : []
|
||||
const idx = list.findIndex(item => item.id == currentId)
|
||||
if (idx > -1) {
|
||||
list[idx].title = data.data.title
|
||||
list[idx].img = data.data.img
|
||||
list[idx].unRead = data.data.unRead
|
||||
list[idx].unReadNumber = data.data.unReadNumber
|
||||
list[idx].noNotice = data.data.noNotice
|
||||
list[idx].imgShape = data.data.imgShape
|
||||
list[idx].area = data.data.area
|
||||
uni.setStorageSync(STORAGE_KEY, JSON.stringify(list))
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
closeAddPopup()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
@ -563,7 +724,7 @@ const onDblclickRight = () => {
|
|||
justify-content: space-between;
|
||||
transform: translateX(-50%);
|
||||
width: 540rpx;
|
||||
z-index: 10;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.action-popup .triangle {
|
||||
|
|
@ -739,4 +900,144 @@ const onDblclickRight = () => {
|
|||
color: #333333;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ===== 添加短信弹窗 ===== */
|
||||
.add-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1300;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.add-popup {
|
||||
width: 88%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.add-header {
|
||||
padding: 36rpx 40rpx 20rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #1A1A1A;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.add-body {
|
||||
padding: 8rpx 0;
|
||||
}
|
||||
|
||||
.add-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 32rpx;
|
||||
gap: 16rpx;
|
||||
|
||||
.image-box {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.square {
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.required {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.required::before {
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
content: '*';
|
||||
top: 0;
|
||||
color: #EA0000;
|
||||
}
|
||||
|
||||
.add-label {
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
width: 150rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.add-input {
|
||||
flex: 1;
|
||||
height: 70rpx;
|
||||
background-color: #F6F6F6;
|
||||
border-radius: 14rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
|
||||
::v-deep .uni-input {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
}
|
||||
|
||||
.add-footer {
|
||||
padding: 32rpx 24rpx;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
flex: 1;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
background-color: #F1F1F1;
|
||||
margin: 0 16rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.add-btn.cancel {
|
||||
color: #767676;
|
||||
}
|
||||
|
||||
.add-btn.confirm {
|
||||
color: #fff;
|
||||
background-color: #1777FF;
|
||||
}
|
||||
|
||||
.delete-img-icon {
|
||||
position: absolute;
|
||||
top: -12rpx;
|
||||
right: -12rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
padding-bottom: 2rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -30,13 +30,18 @@
|
|||
<view class="add-body">
|
||||
<view class="add-row">
|
||||
<text class="add-label">头像URL:</text>
|
||||
<view class="image-box" :class="addForm.imgShape" style="width: 84rpx;height: 84rpx;"
|
||||
@tap="selectImage">
|
||||
<image v-if="addForm.img" class="image w100 h100" :src="addForm.img" mode="aspectFill">
|
||||
</image>
|
||||
<image v-else class="image w100 h100" src="/static/image/phone-message/add.png"
|
||||
mode="aspectFill">
|
||||
</image>
|
||||
<view style="position: relative;">
|
||||
<view class="image-box" :class="addForm.imgShape" style="width: 84rpx;height: 84rpx;"
|
||||
@tap="selectImage">
|
||||
<image v-if="addForm.img" class="image w100 h100" :src="addForm.img" mode="aspectFill">
|
||||
</image>
|
||||
<image v-else class="image w100 h100" src="/static/image/phone-message/add.png"
|
||||
mode="aspectFill">
|
||||
</image>
|
||||
</view>
|
||||
<view v-if="addForm.img" class="delete-img-icon" @tap.stop="deleteImage">
|
||||
×
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="data.phone == 'iphone'"
|
||||
style="flex: 1;display: flex;align-items: center;justify-content: flex-end;">
|
||||
|
|
@ -210,7 +215,7 @@ onShow(() => {
|
|||
if (cachedNotice !== '') {
|
||||
data.noticeCount = Number(cachedNotice)
|
||||
}
|
||||
} catch (e) { }
|
||||
} catch (e) { console.error(e) }
|
||||
})
|
||||
|
||||
|
||||
|
|
@ -228,7 +233,7 @@ onPageScroll((e) => {
|
|||
* @returns {Promise<string>} 持久化后的文件路径
|
||||
*/
|
||||
const saveImageToLocal = (tempFilePath) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve) => {
|
||||
// 如果是已经持久化的路径或是静态资源,直接返回
|
||||
if (!tempFilePath || tempFilePath.startsWith('_doc') || tempFilePath.startsWith('/static')) {
|
||||
return resolve(tempFilePath)
|
||||
|
|
@ -277,10 +282,18 @@ const deleteItem = (item) => {
|
|||
if (res.confirm) {
|
||||
const idx = defaultList.value.findIndex(i => i.id === item.id)
|
||||
if (idx > -1) {
|
||||
// 删除关联的本地图片文件
|
||||
// 删除关联的本地图片文件(头像)
|
||||
if (item.img) {
|
||||
removeLocalFile(item.img)
|
||||
}
|
||||
// 删除该对话中所有的图片文件
|
||||
if (item.chatList && item.chatList.length > 0) {
|
||||
item.chatList.forEach(msg => {
|
||||
if (msg.type === 'image' && msg.imgUrl && msg.imgUrl.includes('_doc/')) {
|
||||
removeLocalFile(msg.imgUrl)
|
||||
}
|
||||
})
|
||||
}
|
||||
defaultList.value.splice(idx, 1)
|
||||
uni.setStorageSync(STORAGE_KEY, JSON.stringify(defaultList.value))
|
||||
}
|
||||
|
|
@ -303,6 +316,10 @@ const selectImage = () => {
|
|||
})
|
||||
}
|
||||
|
||||
const deleteImage = () => {
|
||||
addForm.img = ''
|
||||
}
|
||||
|
||||
const itemClick = (item) => {
|
||||
util.goPage(`/pages/message/chat-page/chat-page?phone=${data.phone}&id=${item.id}`)
|
||||
}
|
||||
|
|
@ -439,7 +456,7 @@ const confirmAdd = async () => {
|
|||
})
|
||||
try {
|
||||
uni.setStorageSync(STORAGE_KEY, JSON.stringify(defaultList.value))
|
||||
} catch (e) { }
|
||||
} catch (e) { console.error(e) }
|
||||
closeAddPopup()
|
||||
}
|
||||
|
||||
|
|
@ -474,7 +491,7 @@ const confirmSim = () => {
|
|||
sim2: simForm.sim2.trim() || '移动'
|
||||
}))
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
} catch (e) { }
|
||||
} catch (e) { console.error(e) }
|
||||
closeSimPopup()
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +515,7 @@ const confirmNotice = () => {
|
|||
try {
|
||||
uni.setStorageSync(NOTICE_COUNT_KEY, data.noticeCount)
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
} catch (e) { }
|
||||
} catch (e) { console.error(e) }
|
||||
closeNoticePopup()
|
||||
}
|
||||
|
||||
|
|
@ -738,4 +755,22 @@ page {
|
|||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-img-icon {
|
||||
position: absolute;
|
||||
top: -12rpx;
|
||||
right: -12rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
padding-bottom: 2rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -16,10 +16,18 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, getCurrentInstance } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app'
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
const data = reactive({
|
||||
phone: ''
|
||||
})
|
||||
|
|
@ -36,51 +44,50 @@ onLoad((options) => {
|
|||
})
|
||||
})
|
||||
|
||||
const menuList = ref([
|
||||
{
|
||||
name: "京东",
|
||||
icon: "jingdong",
|
||||
bgColor: ["#FFE0DF", "#FFFFFF"],
|
||||
btnBg: "#FF4848",
|
||||
shadowColor: "#FF4848",
|
||||
url: "/pages/shopping/jingdong/list-index"
|
||||
}, {
|
||||
name: "淘宝",
|
||||
icon: "taobao",
|
||||
bgColor: ["#FFF0DA", "#FFFFFF"],
|
||||
btnBg: "#FF953C",
|
||||
shadowColor: "#FF953C",
|
||||
url: "/pages/shopping/taobao/list-index"
|
||||
}, {
|
||||
name: "快手",
|
||||
icon: "kuaishou",
|
||||
bgColor: ["#FFF0DA", "#FFFFFF"],
|
||||
btnBg: "#FF953C",
|
||||
shadowColor: "#FF953C",
|
||||
url: ""
|
||||
}, {
|
||||
name: "抖音",
|
||||
icon: "douyin",
|
||||
bgColor: ["#FAE5FF", "#FFFFFF"],
|
||||
btnBg: "#393939",
|
||||
shadowColor: "#D15CFF",
|
||||
url: ""
|
||||
}, {
|
||||
name: "得物",
|
||||
icon: "dewu",
|
||||
bgColor: ["#FAE5FF", "#FFFFFF"],
|
||||
btnBg: "#393939",
|
||||
shadowColor: "#D15CFF",
|
||||
url: ""
|
||||
}, {
|
||||
name: "拼多多",
|
||||
icon: "pinduoduo",
|
||||
bgColor: ["#FFE0DF", "#FFFFFF"],
|
||||
btnBg: "#FF4848",
|
||||
shadowColor: "#FF4848",
|
||||
url: ""
|
||||
}
|
||||
]);
|
||||
const menuList = ref([{
|
||||
name: "京东",
|
||||
icon: "jingdong",
|
||||
bgColor: ["#FFE0DF", "#FFFFFF"],
|
||||
btnBg: "#FF4848",
|
||||
shadowColor: "#FF4848",
|
||||
url: "/pages/shopping/jingdong/list-index"
|
||||
}, {
|
||||
name: "淘宝",
|
||||
icon: "taobao",
|
||||
bgColor: ["#FFF0DA", "#FFFFFF"],
|
||||
btnBg: "#FF953C",
|
||||
shadowColor: "#FF953C",
|
||||
url: "/pages/shopping/taobao/list-index"
|
||||
}, {
|
||||
name: "拼多多",
|
||||
icon: "pinduoduo",
|
||||
bgColor: ["#FFE0DF", "#FFFFFF"],
|
||||
btnBg: "#FF4848",
|
||||
shadowColor: "#FF4848",
|
||||
// url: "/pages/shopping/pdd/list-index"
|
||||
url: ""
|
||||
}, {
|
||||
name: "快手",
|
||||
icon: "kuaishou",
|
||||
bgColor: ["#FFF0DA", "#FFFFFF"],
|
||||
btnBg: "#FF953C",
|
||||
shadowColor: "#FF953C",
|
||||
url: ""
|
||||
}, {
|
||||
name: "抖音",
|
||||
icon: "douyin",
|
||||
bgColor: ["#FAE5FF", "#FFFFFF"],
|
||||
btnBg: "#393939",
|
||||
shadowColor: "#D15CFF",
|
||||
url: ""
|
||||
}, {
|
||||
name: "得物",
|
||||
icon: "dewu",
|
||||
bgColor: ["#FAE5FF", "#FFFFFF"],
|
||||
btnBg: "#393939",
|
||||
shadowColor: "#D15CFF",
|
||||
url: ""
|
||||
}]);
|
||||
|
||||
const goTo = (url) => {
|
||||
if (url) {
|
||||
|
|
@ -170,4 +177,4 @@ page {
|
|||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,479 @@
|
|||
<template>
|
||||
<view class="list-card-container" v-if="item">
|
||||
<!-- 头部店铺信息和状态 -->
|
||||
<view class="header-box flex-between flex-align-center">
|
||||
<view class="shop-info flex-align-center">
|
||||
<view class="shop-logo-placeholder flex-center" v-if="item.isBrand"><text class="logo-text">正品</text>
|
||||
</view>
|
||||
<text class="shop-name">{{ item.shopName }}</text>
|
||||
<!-- <view class="tag-brand" v-if="item.isBrand">品牌认证</view> -->
|
||||
<image v-if="item.isBrand" class="brand-img" src="/static/image/shopping/pdd/pinpairenzheng.png">
|
||||
</image>
|
||||
<image class="flag-img" v-if="item.isFlagship" src="/static/image/shopping/pdd/qijiandian.png"></image>
|
||||
<uni-icons style="margin-top: 4rpx;" type="right" color="#999999" size="12"></uni-icons>
|
||||
</view>
|
||||
<view class="status-text" v-if="item.orderType === 'wait_pay'">待支付</view>
|
||||
<view class="status-text" v-if="item.orderType === 'wait_recv'">待收货</view>
|
||||
<view class="status-text" v-if="item.orderType === 'received'">交易成功</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品主要内容 -->
|
||||
<view class="product-box flex">
|
||||
<view class="product-img-box">
|
||||
<image class="product-img" :src="item.productImg" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="product-content flex-1">
|
||||
<view class="title-box">
|
||||
<view class="brand-tag flex-center">品牌</view>
|
||||
<text class="title-text">{{ item.productTitle }}</text>
|
||||
</view>
|
||||
<view class="spec-text text-ellipsis">{{ item.productSpec }}</view>
|
||||
<view class="tags-box flex-align-center">
|
||||
<view class="green-tag" v-for="(tag, index) in item.tags" :key="index">{{ tag }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="price-box flex-column align-end">
|
||||
<text class="price">¥
|
||||
<text style="font-size: 30rpx;">{{ Number(item.price).toFixed(1).split('.')[0] + '.' }}</text>
|
||||
<text style="font-size: 22rpx;">{{ Number(item.price).toFixed(1).split('.')[1] }}</text>
|
||||
</text>
|
||||
<text class="count">x{{ item.quantity }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view>
|
||||
<!-- 价格汇总 -->
|
||||
<view class="summary-box flex-between flex-align-center">
|
||||
<view class="avatar-group flex-align-center">
|
||||
<image class="avatar" v-for="(avatar, idx) in item.avatars" :key="idx" :src="avatar"
|
||||
mode="aspectFill">
|
||||
</image>
|
||||
</view>
|
||||
<view class="total-price flex-align-center">
|
||||
<text class="label">{{ item.orderType === 'wait_pay' ? '应付' : '实付' }}:</text>
|
||||
<text class="symbol">¥</text>
|
||||
<text class="amount">{{ item.totalAmount }}</text>
|
||||
<text class="freight">({{ item.freightText }})</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 按钮组 -->
|
||||
<view class="action-box flex-end flex-align-center">
|
||||
<template v-if="item.orderType === 'wait_pay'">
|
||||
<view class="btn plain">取消订单</view>
|
||||
<view class="btn primary">去支付</view>
|
||||
</template>
|
||||
<template v-if="item.orderType === 'wait_recv'">
|
||||
<text class="more-btn">更多</text>
|
||||
<view class="btn plain">申请退款</view>
|
||||
<view class="btn plain">追加评价</view>
|
||||
<view class="btn primary with-badge">
|
||||
确认收货
|
||||
<!-- <view class="badge" v-if="item.collectCount">{{ item.collectCount }}人收藏</view> -->
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.orderType === 'received'">
|
||||
<text class="more-btn">更多</text>
|
||||
<view class="btn plain">申请退款</view>
|
||||
<view class="btn plain">追加评价</view>
|
||||
<view class="btn primary with-badge">
|
||||
再次拼单
|
||||
<!-- <view class="badge" v-if="item.collectCount">{{ item.collectCount }}人收藏</view> -->
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<!-- 物流状态栏 -->
|
||||
<view class="delivery-box flex-align-center" v-if="item.deliveryStatus">
|
||||
<view class="truck-icon flex-center">
|
||||
<image style="width:32rpx;height: 32rpx;" src="/static/image/shopping/pdd/yunshuzhong.png"></image>
|
||||
</view>
|
||||
<view class="delivery-content text-ellipsis flex-1">
|
||||
<template v-if="item.orderType === 'wait_pay'">
|
||||
<text class="green-text">{{ item.deliveryStatus }}</text>
|
||||
<text class="green-text">{{ item.deliveryDetail }}</text>
|
||||
</template>
|
||||
<template v-if="item.orderType === 'wait_recv'">
|
||||
<text class="green-text">{{ item.deliveryStatus }}</text>
|
||||
<text class="gray-text">{{ item.deliveryDetail }}</text>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.list-card-container {
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 16rpx;
|
||||
padding: 22rpx 0;
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.flex-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flex-align-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-end {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.text-ellipsis {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.header-box {
|
||||
padding: 0 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.shop-logo-placeholder {
|
||||
width: 44rpx;
|
||||
height: 24rpx;
|
||||
background-color: #E01B13;
|
||||
border-radius: 20rpx;
|
||||
margin-right: 8rpx;
|
||||
|
||||
.logo-text {
|
||||
color: #fff;
|
||||
font-size: 16rpx;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 24rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.brand-img {
|
||||
width: 94rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.flag-img {
|
||||
width: 74rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #DF2E26;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* Product Info */
|
||||
.product-box {
|
||||
padding: 0 24rpx;
|
||||
padding-bottom: 14rpx;
|
||||
margin-bottom: 10rpx;
|
||||
border-bottom: 1rpx solid #EFEFEF;
|
||||
|
||||
.product-img-box {
|
||||
width: 148rpx;
|
||||
height: 148rpx;
|
||||
margin-right: 14rpx;
|
||||
border-radius: 4rpx;
|
||||
overflow: hidden;
|
||||
background-color: #f5f5f5;
|
||||
flex-shrink: 0;
|
||||
|
||||
.product-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.product-content {
|
||||
width: 0;
|
||||
|
||||
.title-box {
|
||||
font-size: 26rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 36rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
|
||||
.brand-tag {
|
||||
display: inline-block;
|
||||
background-color: #252525;
|
||||
color: #fff;
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
padding: 4rpx 8rpx;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 8rpx;
|
||||
margin-top: -4rpx;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.spec-text {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
line-height: 26rpx;
|
||||
margin-top: 6rpx;
|
||||
margin-bottom: 14rpx;
|
||||
}
|
||||
|
||||
.tags-box {
|
||||
|
||||
/* Overriding image style */
|
||||
.green-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0 4rpx;
|
||||
border-radius: 4rpx;
|
||||
margin: 0 4rpx;
|
||||
font-weight: 400;
|
||||
height: 30rpx;
|
||||
color: #fff;
|
||||
background-color: #2BB40C;
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.price-box {
|
||||
margin-left: 10rpx;
|
||||
flex-shrink: 0;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
|
||||
.price {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.count {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.align-end {
|
||||
align-items: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Summary */
|
||||
.summary-box {
|
||||
position: relative;
|
||||
margin-bottom: 16rpx;
|
||||
padding: 0 16rpx;
|
||||
padding-bottom: 14rpx;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
transform: scaleY(0.3);
|
||||
background-color: #D2D2D2;
|
||||
}
|
||||
|
||||
.avatar-group {
|
||||
position: relative;
|
||||
width: 110rpx;
|
||||
height: 44rpx;
|
||||
|
||||
.avatar {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #FFFFFF;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.avatar:nth-child(1) {
|
||||
left: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.avatar:nth-child(2) {
|
||||
left: 34rpx;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.avatar:nth-child(3) {
|
||||
left: 68rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.avatar:nth-child(4) {
|
||||
left: 102rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.total-price {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
font-size: 24rpx;
|
||||
color: #1A1A1A;
|
||||
|
||||
.label {
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
.symbol {
|
||||
font-size: 24rpx;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 34rpx;
|
||||
}
|
||||
|
||||
.freight {
|
||||
font-size: 26rpx;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.action-box {
|
||||
margin-bottom: 16rpx;
|
||||
padding: 0 16rpx;
|
||||
|
||||
.more-btn {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 28rpx;
|
||||
margin-right: 46rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
min-width: 138rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 28rpx;
|
||||
margin-left: 14rpx;
|
||||
padding: 0 12rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.plain {
|
||||
border: 1rpx solid #9E9E9E;
|
||||
color: #1A1A1A;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
border: 1rpx solid #DF2E26;
|
||||
background-color: #DF2E26;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.with-badge {
|
||||
position: relative;
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
top: -18rpx;
|
||||
right: -12rpx;
|
||||
background-color: #FFE669;
|
||||
color: #E01B13;
|
||||
font-size: 18rpx;
|
||||
padding: 2rpx 10rpx;
|
||||
border-radius: 20rpx;
|
||||
white-space: nowrap;
|
||||
transform: scale(0.9);
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Delivery Info */
|
||||
.delivery-box {
|
||||
background-color: #F5F5F5;
|
||||
padding: 10rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
margin: 0 16rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.truck-icon {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.delivery-content {
|
||||
font-size: 24rpx;
|
||||
|
||||
.green-text {
|
||||
color: #2BB40C;
|
||||
}
|
||||
|
||||
.gray-text {
|
||||
color: #595959;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
<template>
|
||||
<view class="page-container flex-column">
|
||||
<view class="nav-bar">
|
||||
<nav-bar>
|
||||
<template v-slot:left>
|
||||
<image style="width: 48rpx;height: 48rpx;" src="/static/image/shopping/pdd/back.png"></image>
|
||||
</template>
|
||||
<template v-slot:center>
|
||||
<view class="title-box flex-center flex-column">
|
||||
<view class="title">我的订单</view>
|
||||
<view class="flex-center text">
|
||||
<image style="width: 30rpx;height: 30rpx;" src="/static/image/shopping/pdd/safety.png">
|
||||
</image>
|
||||
<text>专属客服 ·闪电退换 ·售后无忧</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right>
|
||||
<image style="width: 48rpx;height: 48rpx;" src="/static/image/shopping/pdd/search.png"></image>
|
||||
</template>
|
||||
</nav-bar>
|
||||
</view>
|
||||
<view class="tab-list flex-align-center">
|
||||
<view class="tab-item" :class="{ active: tab.id == activeTab }" v-for="(tab, index) in tabList"
|
||||
:key="index">
|
||||
<text>{{ tab.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="flex-1" style="height: 100px;" scroll-y="true">
|
||||
<list-card v-for="(item, index) in orderList" :key="index" :item="item"></list-card>
|
||||
<view v-if="orderList.length == 0" class="null-data-box flex-align-center">
|
||||
<text>没找到订单?试试</text>
|
||||
<text style="color: #2686E4;">查看全部</text>
|
||||
<text>或</text>
|
||||
<text style="color: #2686E4;">切换账号</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import ListCard from './components/list-card/list-card.vue';
|
||||
|
||||
const activeTab = ref(0);
|
||||
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全部',
|
||||
id: 0
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
name: '拼团中',
|
||||
id: 2
|
||||
},
|
||||
{
|
||||
name: '打包中',
|
||||
id: 3
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
id: 4
|
||||
},
|
||||
{
|
||||
name: '评价',
|
||||
id: 5
|
||||
},
|
||||
]);
|
||||
|
||||
const orderList = ref([
|
||||
{
|
||||
// type: 1,
|
||||
orderType: "wait_pay",
|
||||
shopName: '澳松旗舰店',
|
||||
isBrand: true,
|
||||
isFlagship: true,
|
||||
productImg: 'https://picsum.photos/200/200?random=1',
|
||||
productTitle: '适配哈哈哈哈哈哈哈哈哈哈哈哈头配哈哈哈哈哈哈哈哈哈哈哈哈很好...',
|
||||
productSpec: '(小头款)哈哈哈哈哈哈哈哈哈哈哈哈很好...',
|
||||
tags: ['坏了包赔', '7天无理由退货'],
|
||||
price: '35.9',
|
||||
quantity: 1,
|
||||
avatars: [
|
||||
'https://picsum.photos/40/40?random=1',
|
||||
'https://picsum.photos/40/40?random=2',
|
||||
'https://picsum.photos/40/40?random=3',
|
||||
'https://picsum.photos/40/40?random=4'
|
||||
],
|
||||
totalAmount: '35.9',
|
||||
freightText: '免运费',
|
||||
deliveryStatus: '现在支付,预计6小时内发货,',
|
||||
deliveryDetail: '后天送达'
|
||||
},
|
||||
{
|
||||
// type: 2,
|
||||
orderType: "wait_recv",
|
||||
shopName: '澳松旗舰店',
|
||||
isBrand: true,
|
||||
isFlagship: true,
|
||||
productImg: 'https://picsum.photos/200/200?random=2',
|
||||
productTitle: '适配哈哈哈哈哈哈哈哈哈哈哈哈头配哈哈哈哈哈哈哈哈哈哈哈哈很好...',
|
||||
productSpec: '(小头款)哈哈哈哈哈哈哈哈哈哈哈哈很好...',
|
||||
tags: ['7天无理由退货'],
|
||||
price: '35.9',
|
||||
quantity: 1,
|
||||
avatars: [
|
||||
'https://picsum.photos/40/40?random=5',
|
||||
'https://picsum.photos/40/40?random=6',
|
||||
'https://picsum.photos/40/40?random=7',
|
||||
'https://picsum.photos/40/40?random=8'
|
||||
],
|
||||
totalAmount: '35.9',
|
||||
freightText: '免运费',
|
||||
collectCount: 558,
|
||||
deliveryStatus: '运输中 预计明天送达',
|
||||
deliveryDetail: '申通快递:【洛阳市】快件已发往 新...'
|
||||
},
|
||||
{
|
||||
// type: 3,
|
||||
orderType: "received",
|
||||
shopName: '澳松旗舰店',
|
||||
isBrand: true,
|
||||
isFlagship: true,
|
||||
productImg: 'https://picsum.photos/200/200?random=3',
|
||||
productTitle: '适配哈哈哈哈哈哈哈哈哈哈哈哈头配哈哈哈哈哈哈哈哈哈哈哈哈很好...',
|
||||
productSpec: '(小头款)哈哈哈哈哈哈哈哈哈哈哈哈很好...',
|
||||
tags: ['退货包运费保障中'],
|
||||
price: '35.9',
|
||||
quantity: 1,
|
||||
avatars: [
|
||||
'https://picsum.photos/40/40?random=9',
|
||||
'https://picsum.photos/40/40?random=10',
|
||||
'https://picsum.photos/40/40?random=11',
|
||||
'https://picsum.photos/40/40?random=12'
|
||||
],
|
||||
totalAmount: '35.9',
|
||||
freightText: '免运费',
|
||||
collectCount: 558
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.page-container {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
border-bottom: 1rpx solid #D2D2D2;
|
||||
}
|
||||
|
||||
.title-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.title {
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #16B800;
|
||||
line-height: 24rpx;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
height: 80rpx;
|
||||
background-color: #ffff;
|
||||
border-bottom: 0.5px solid #D2D2D2;
|
||||
|
||||
.tab-item {
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 80rpx;
|
||||
white-space: nowrap;
|
||||
margin: 0 22rpx;
|
||||
|
||||
&.active {
|
||||
color: #E01B13;
|
||||
font-weight: 500;
|
||||
border-bottom: 4rpx solid #E01B13;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.null-data-box {
|
||||
justify-content: center;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
line-height: 28rpx;
|
||||
padding: 42rpx 0;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
|
||||
page {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,376 @@
|
|||
<template>
|
||||
<view class="page-container flex-column">
|
||||
<view class="hightlight-box">
|
||||
<nav-bar>
|
||||
<template v-slot:center>
|
||||
<view class="flex-column flex-center">
|
||||
<view class="title">待付款 预计后天送达</view>
|
||||
<view class="sub-title">请在23:59:27.2内支付,逾期订单将自动取消</view>
|
||||
</view>
|
||||
</template>
|
||||
</nav-bar>
|
||||
</view>
|
||||
<view class="adress-box flex-align-center flex-justify-between">
|
||||
<image style="width:40rpx;height: 40rpx;flex-shrink: 0;" src="/static/image/shopping/pdd/location.png">
|
||||
</image>
|
||||
<view class="user-info flex-1">
|
||||
<view>
|
||||
<text>姓名</text> <text>电话</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>地址</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="order.orderType == 'wait_pay'" class="edit-btn">修改</view>
|
||||
</view>
|
||||
<view class="upload-shop-logo-box flex-justify-between flex-align-center">
|
||||
<text>上传店铺头像</text>
|
||||
<view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="product-card">
|
||||
<!-- 店铺信息 -->
|
||||
<view class="shop-header flex-align-center">
|
||||
<view class="shop-logo flex-center">
|
||||
<text>卫松</text>
|
||||
</view>
|
||||
<text class="shop-name">卫松旗舰店</text>
|
||||
<image class="brand-auth-tag" src="/static/image/shopping/pdd/pinpairenzheng.png" mode="heightFix">
|
||||
</image>
|
||||
<image class="flagship-tag" src="/static/image/shopping/pdd/qijiandian.png" mode="heightFix"></image>
|
||||
</view>
|
||||
|
||||
<!-- 商品主要内容 -->
|
||||
<view class="product-content flex">
|
||||
<view class="img-box">
|
||||
<image class="product-img"
|
||||
src="https://img.pddpic.com/mms-material-img/2022-09-02/76b7e127-ecdf-41ef-8d69-a36c561570d5.png"
|
||||
mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="info-box flex-1">
|
||||
<view class="title-price flex">
|
||||
<view class="title text-ellipsis-2 flex-1">
|
||||
【云南傣味】 头配哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
|
||||
</view>
|
||||
<view class="price-box flex-column align-end">
|
||||
<text class="price">¥35.9</text>
|
||||
<text class="count">x1</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="spec text-ellipsis-2">
|
||||
傣味头款哈哈哈哈哈哈哈哈哈哈哈哈哈很哈哈哈哈哈哈
|
||||
</view>
|
||||
<view class="tags flex-align-center">
|
||||
<view class="green-tag">坏了包赔<uni-icons type="right" size="10" color="#fff"
|
||||
style="margin-left: 2rpx;"></uni-icons></view>
|
||||
<view class="green-tag">7天无理由退货<uni-icons type="right" size="10" color="#fff"
|
||||
style="margin-left: 2rpx;"></uni-icons></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系商家按钮 -->
|
||||
<view class="contact-box flex">
|
||||
<view style="flex: 1;"></view>
|
||||
<view class="contact-btn flex-center">
|
||||
<view class="chat-icon">
|
||||
<view class="dot"></view>
|
||||
<view class="dot"></view>
|
||||
<view class="dot"></view>
|
||||
</view>
|
||||
<text>联系商家</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="divider"></view>
|
||||
|
||||
<!-- 底部支付金额 -->
|
||||
<view class="payment-box flex-align-center">
|
||||
<view style="flex: 1;"></view>
|
||||
<text class="label">应付: </text>
|
||||
<text class="symbol">¥</text>
|
||||
<text class="amount">16.9</text>
|
||||
<text class="freight">(免运费)</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
const order = ref({
|
||||
orderType: 'wait_pay'
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.title {
|
||||
font-weight: 500;
|
||||
font-size: 36rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 36rpx;
|
||||
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #DF2E26;
|
||||
line-height: 26rpx;
|
||||
white-space: nowrap;
|
||||
margin-top: 14rpx;
|
||||
}
|
||||
|
||||
.hightlight-box {
|
||||
border-bottom: 1rpx solid #F4F4F4;
|
||||
}
|
||||
|
||||
.adress-box {
|
||||
background-color: #ffffff;
|
||||
padding: 24rpx 26rpx;
|
||||
margin-bottom: 18rpx;
|
||||
|
||||
.user-info {
|
||||
margin-left: 22rpx;
|
||||
margin-right: 56rpx;
|
||||
color: #535353;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
flex-shrink: 0;
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
line-height: 30rpx;
|
||||
color: #DF2E26;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #DF2E26;
|
||||
text-align: center;
|
||||
padding: 16rpx 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background-color: #ffffff;
|
||||
padding: 24rpx 24rpx 0;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.shop-header {
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.shop-logo {
|
||||
width: 48rpx;
|
||||
height: 26rpx;
|
||||
background-color: #E02020;
|
||||
border-radius: 13rpx;
|
||||
margin-right: 12rpx;
|
||||
position: relative;
|
||||
box-shadow: 0 0 0 2rpx #fff, 0 0 0 4rpx #E02020;
|
||||
|
||||
text {
|
||||
font-size: 16rpx;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
font-size: 30rpx;
|
||||
color: #151515;
|
||||
margin-right: 12rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.brand-auth-tag {
|
||||
height: 30rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.flagship-tag {
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.product-content {
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.img-box {
|
||||
width: 156rpx;
|
||||
height: 156rpx;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f5f5f5;
|
||||
margin-right: 18rpx;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.product-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.info-box {
|
||||
width: 0;
|
||||
|
||||
.title-price {
|
||||
align-items: flex-start;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #151515;
|
||||
line-height: 40rpx;
|
||||
font-weight: 400;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.price-box {
|
||||
flex-shrink: 0;
|
||||
|
||||
.price {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.count {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 4rpx;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spec {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
line-height: 36rpx;
|
||||
margin-top: 4rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.tags {
|
||||
.green-tag {
|
||||
background-color: #49B113;
|
||||
color: #ffffff;
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
padding: 6rpx 4rpx 6rpx 8rpx;
|
||||
border-radius: 6rpx;
|
||||
margin-right: 10rpx;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contact-box {
|
||||
padding-bottom: 24rpx;
|
||||
|
||||
.contact-btn {
|
||||
height: 56rpx;
|
||||
padding: 0 24rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #DEDEDE;
|
||||
|
||||
.chat-icon {
|
||||
width: 28rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 6rpx;
|
||||
border: 2rpx solid #49B113;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
margin-right: 10rpx;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -6rpx;
|
||||
left: 4rpx;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6rpx solid transparent;
|
||||
border-right: 6rpx solid transparent;
|
||||
border-top: 8rpx solid #49B113;
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 4rpx;
|
||||
height: 4rpx;
|
||||
background-color: #49B113;
|
||||
border-radius: 50%;
|
||||
margin: 0 1rpx;
|
||||
}
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 26rpx;
|
||||
color: #151515;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: #EFEFEF;
|
||||
transform: scaleY(0.5);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.payment-box {
|
||||
padding: 24rpx 0;
|
||||
|
||||
.label {
|
||||
font-size: 26rpx;
|
||||
color: #151515;
|
||||
}
|
||||
|
||||
.symbol {
|
||||
font-size: 24rpx;
|
||||
color: #DF2E26;
|
||||
margin-left: 10rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 36rpx;
|
||||
color: #DF2E26;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.freight {
|
||||
font-size: 26rpx;
|
||||
color: #151515;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-ellipsis-2 {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.align-end {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.upload-shop-logo-box {
|
||||
background-color: #fff;
|
||||
padding: 24rpx 26rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
</style>
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
<view class="goods-title-row">
|
||||
<view class="good-info-box" :id="'title-box-' + index + '-0'">
|
||||
<text class="goods-title">{{ getTruncatedTitle(item, index, item.goodsList[0], 0)
|
||||
}}</text>
|
||||
}}</text>
|
||||
<view class="goods-spec" style="margin-top: 18rpx; color: #999;">默认</view>
|
||||
<view class="goods-tags" v-if="item.goodsList[0].tags || item.goodsList[0].tag"
|
||||
style="margin-top: 18rpx;">
|
||||
|
|
@ -118,7 +118,7 @@
|
|||
<text>好评</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 单个商品的售后状态 -->
|
||||
<!-- 单个商品的退款状态 -->
|
||||
<view class="goods-evaluation" v-if="item.statusType == 'refunding' && currentFilter != 4">
|
||||
<view class="left">
|
||||
<image style="width: 24rpx;height: 24rpx;margin-right: 8rpx;"
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 996 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |